Add create and show page for competition
This commit is contained in:
parent
1485f3daf5
commit
744308d0cb
10 changed files with 151 additions and 72 deletions
|
@ -39,14 +39,8 @@ class TournamentController extends Controller
|
|||
'description' => 'nullable|string',
|
||||
'location' => 'nullable|string|max:255',
|
||||
'start_date' => 'required|date',
|
||||
'end_date' => 'required|date|after_or_equal:start_date',
|
||||
'registration_deadline' => 'nullable|date|before_or_equal:start_date',
|
||||
'max_teams' => 'nullable|integer|min:2',
|
||||
'status' => 'required|in:draft,public,private',
|
||||
'team_ids' => 'nullable|array',
|
||||
'team_ids.*' => 'exists:teams,id',
|
||||
'field_ids' => 'nullable|array',
|
||||
'field_ids.*' => 'exists:fields,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
|
@ -59,23 +53,11 @@ class TournamentController extends Controller
|
|||
$tournament->description = $request->description;
|
||||
$tournament->location = $request->location;
|
||||
$tournament->start_date = $request->start_date;
|
||||
$tournament->end_date = $request->end_date;
|
||||
$tournament->registration_deadline = $request->registration_deadline;
|
||||
$tournament->max_teams = $request->max_teams;
|
||||
$tournament->status = $request->status;
|
||||
$tournament->owner = Auth::id();
|
||||
$tournament->save();
|
||||
|
||||
// Associate teams with the tournament
|
||||
if ($request->has('team_ids') && is_array($request->team_ids)) {
|
||||
$tournament->teams()->attach($request->team_ids, ['status' => 'confirmed']);
|
||||
}
|
||||
|
||||
// Associate fields with the tournament
|
||||
if ($request->has('field_ids') && is_array($request->field_ids)) {
|
||||
$tournament->fields()->attach($request->field_ids);
|
||||
}
|
||||
|
||||
// Create a default scheduling mode
|
||||
$schedulingMode = new SchedulingMode();
|
||||
$schedulingMode->competition_id = $tournament->id;
|
||||
|
|
|
@ -20,7 +20,6 @@ class Competition extends Model
|
|||
'name',
|
||||
'description',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'status',
|
||||
'location',
|
||||
'max_teams',
|
||||
|
|
|
@ -4,7 +4,9 @@ namespace App\Providers;
|
|||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
|
@ -65,5 +67,15 @@ class AppServiceProvider extends ServiceProvider
|
|||
|
||||
return false;
|
||||
});
|
||||
|
||||
DB::listen(function ($query) {
|
||||
Log::info(
|
||||
$query->sql,
|
||||
[
|
||||
'bindings' => $query->bindings,
|
||||
'time' => $query->time,
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"$schema": "https://next.shadcn-svelte.com/schema.json",
|
||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
||||
"tailwind": {
|
||||
"css": "resources/css/app.css",
|
||||
"baseColor": "neutral"
|
||||
|
@ -12,5 +12,5 @@
|
|||
"lib": "@/lib"
|
||||
},
|
||||
"typescript": true,
|
||||
"registry": "https://next.shadcn-svelte.com/registry"
|
||||
"registry": "https://shadcn-svelte.com/registry"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ return new class extends Migration
|
|||
$table->string('name');
|
||||
$table->text('description')->nullable();
|
||||
$table->date('start_date');
|
||||
$table->date('end_date');
|
||||
$table->string('status')->default('planned');
|
||||
$table->string('location')->nullable();
|
||||
$table->integer('max_teams')->default(0);
|
||||
|
@ -31,6 +30,11 @@ return new class extends Migration
|
|||
$table->id();
|
||||
$table->string('name');
|
||||
$table->text('description')->nullable();
|
||||
$table->integer('competition_id')->nullable();
|
||||
$table->string('algorithm')->default('round_robin');
|
||||
$table->json('config')->nullable();
|
||||
$table->integer('sequence_order')->default(1);
|
||||
$table->string('status')->default('active');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
|
@ -48,6 +52,13 @@ return new class extends Migration
|
|||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('competition_field', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('competition_id')->constrained('competitions')->onDelete('cascade');
|
||||
$table->foreignId('field_id')->constrained('fields')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// Create teams table
|
||||
Schema::create('teams', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
@ -59,12 +70,11 @@ return new class extends Migration
|
|||
$table->timestamps();
|
||||
});
|
||||
|
||||
// Create team members table
|
||||
Schema::create('team_members', function (Blueprint $table) {
|
||||
Schema::create('competition_team', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('competition_id')->constrained('competitions')->onDelete('cascade');
|
||||
$table->foreignId('team_id')->constrained('teams')->onDelete('cascade');
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->string('role')->default('member');
|
||||
$table->string('status')->default('confirmed');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
|
@ -103,7 +113,7 @@ return new class extends Migration
|
|||
{
|
||||
Schema::dropIfExists('break_periods');
|
||||
Schema::dropIfExists('matches');
|
||||
Schema::dropIfExists('team_members');
|
||||
Schema::dropIfExists('competition_team');
|
||||
Schema::dropIfExists('teams');
|
||||
Schema::dropIfExists('fields');
|
||||
Schema::dropIfExists('scheduling_modes');
|
||||
|
|
|
@ -87,11 +87,11 @@
|
|||
<div class="flex flex-col gap-2 text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<Calendar class="h-4 w-4 text-muted-foreground" />
|
||||
<span>{formatDate(tournament.date)}</span>
|
||||
<span>{formatDate(tournament.start_date)}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Users class="h-4 w-4 text-muted-foreground" />
|
||||
<span>{tournament.participantsCount} participants</span>
|
||||
<span>{tournament.max_teams} participants</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
@ -107,7 +107,7 @@
|
|||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="my" class="mt-6">
|
||||
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 w-full">
|
||||
{#if !userTournaments.original.data || userTournaments.original.data.length === 0}
|
||||
<div class="flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center">
|
||||
<Trophy class="h-10 w-10 text-muted-foreground" />
|
||||
|
@ -118,7 +118,6 @@
|
|||
</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{#each userTournaments.original.data as tournament (tournament.id)}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
@ -132,11 +131,11 @@
|
|||
<div class="flex flex-col gap-2 text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<Calendar class="h-4 w-4 text-muted-foreground" />
|
||||
<span>{formatDate(tournament.date)}</span>
|
||||
<span>{formatDate(tournament.start_date)}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Users class="h-4 w-4 text-muted-foreground" />
|
||||
<span>{tournament.participantsCount} participants</span>
|
||||
<span>{tournament.max_teams} participants</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<User class="h-4 w-4 text-muted-foreground" />
|
||||
|
@ -150,7 +149,7 @@
|
|||
>View</Link
|
||||
>
|
||||
</Button>
|
||||
<Button variant="secondary" class="flex-1">
|
||||
<Button class="flex-1">
|
||||
<Link href={`/tournaments/${tournament.id}/edit`} class="flex items-center justify-center w-full">
|
||||
Edit
|
||||
</Link>
|
||||
|
@ -158,7 +157,6 @@
|
|||
</CardFooter>
|
||||
</Card>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
<AppLayout {breadcrumbs}>
|
||||
<div class="container mx-auto py-10">
|
||||
<h1 class="text-2xl font-bold mb-6">Create New Tournament</h1>
|
||||
|
||||
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-lg p-6">
|
||||
<form onsubmit={handleSubmit} class="space-y-6">
|
||||
<!-- Tournament Name -->
|
||||
|
|
55
resources/js/pages/tournaments/Show.svelte
Normal file
55
resources/js/pages/tournaments/Show.svelte
Normal file
|
@ -0,0 +1,55 @@
|
|||
<script lang="ts">
|
||||
import Button from '@/components/ui/button/button.svelte';
|
||||
import * as Card from '@/components/ui/card/index.js';
|
||||
import * as Table from '@/components/ui/table';
|
||||
import AppLayout from '@/layouts/AppLayout.svelte';
|
||||
import { type Tournament } from '@/types';
|
||||
|
||||
const breadcrumbs = [
|
||||
{ title: 'Home', href: '/' },
|
||||
{ title: 'Tournaments', href: '/tournaments' },
|
||||
{ title: 'Tournament Name', href: '/tournaments/1' },
|
||||
];
|
||||
|
||||
let { tournament }: { tournament: Tournament } = $props();
|
||||
|
||||
function handleAddTeam() {
|
||||
// add a new row to write the team name, on write complete save it
|
||||
}
|
||||
</script>
|
||||
|
||||
<AppLayout {breadcrumbs}>
|
||||
{JSON.stringify(tournament)}
|
||||
<!-- Teams -->
|
||||
<Card.Root>
|
||||
<Card.Header>
|
||||
<Card.Title>Teams</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<Table.Root>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.Head>Name</Table.Head>
|
||||
<Table.Head>Actions</Table.Head>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{#each tournament.teams as team (team)}
|
||||
<Table.Row>
|
||||
<Table.Cell>{JSON.stringify(team)}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button variant="outline">Edit</Button>
|
||||
<Button variant="destructive">Delete</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{/each}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Button onsubmit={handleAddTeam} variant="outline">+ Add Team</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</AppLayout>
|
24
resources/js/types/index.d.ts
vendored
24
resources/js/types/index.d.ts
vendored
|
@ -44,3 +44,27 @@ export interface Permission {
|
|||
description: string;
|
||||
is_wildcard: boolean;
|
||||
}
|
||||
|
||||
export enum Status {
|
||||
DRAFT = 'draft',
|
||||
PUBLIC = 'public',
|
||||
PRIVATE = 'private',
|
||||
}
|
||||
|
||||
export interface Tournament {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
start_date: string;
|
||||
status: Status;
|
||||
location?: string;
|
||||
max_teams: number;
|
||||
current_scheduling_mode_id?: number;
|
||||
owner: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
teams: object[];
|
||||
fields: object[];
|
||||
matches: object[];
|
||||
break_periods: object[];
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ Route::get('/', function () {
|
|||
$user = Auth::user();
|
||||
$userTournaments = [];
|
||||
if ($user) {
|
||||
$userTournaments = Inertia::defer(fn() => CompetitionController::getUser($user, 1, 10));
|
||||
$userTournaments = Inertia::defer(fn() => CompetitionController::getUser($user, 0, 10));
|
||||
}
|
||||
return Inertia::render('Home', [
|
||||
'publicTournaments' => Inertia::defer(fn() => CompetitionController::getPublics(1, 10)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue