euh lots of changes nothing works ahhh

This commit is contained in:
unurled 2025-07-14 01:09:42 +02:00
parent 95d8988876
commit 36b937c5b6
Signed by: unurled
GPG key ID: EFC5F5E709B47DDD
246 changed files with 1758 additions and 1443 deletions

View file

@ -18,6 +18,6 @@
setContext('permissions', data.permissions);
</script>
<Toaster />
<Toaster richColors />
<ModeWatcher />
{@render children()}

View file

@ -1,11 +1,14 @@
import { browser } from '$app/environment';
import '$lib/i18n'; // Import to initialize. Important :)
import { locale, waitLocale } from 'svelte-i18n';
import type { LayoutLoad } from './$types';
import type { LayoutLoad, LayoutLoadEvent } from './$types';
export const load: LayoutLoad = async () => {
export const load: LayoutLoad = async ({ data }: LayoutLoadEvent) => {
if (browser) {
locale.set(window.navigator.language);
}
await waitLocale();
// return server data
return data;
};

View file

@ -9,33 +9,40 @@ export const POST: RequestHandler = async ({ request, params }) => {
const body = await request.json();
let competitionId;
try {
competitionId = Number.parseInt(params.id, 10);
competitionId = params.id;
} catch {
throw new Error('Invalid competition id');
}
if (competitionId === -1) {
if (competitionId === '') {
throw new Error('Invalid competition id');
}
console.log('body', body);
console.log('competitionId', competitionId);
let schedulingMode: SchedulingMode;
let name: string;
let nbMmatches: number;
try {
schedulingMode = SchedulingMode[body.scheduling_mode as keyof typeof SchedulingMode];
name = body.name;
nbMmatches = body.nb_matches;
} catch {
throw new Error('Invalid scheduling mode');
}
// create round
const roundInsert: RoundInsert = {
nb_matches: 0,
nb_matches: nbMmatches,
name: name,
competition_id: competitionId,
scheduling_mode: schedulingMode
scheduling_mode: schedulingMode,
round_number: -1
};
const round = await insertRound(competitionId, roundInsert);
const [round] = await insertRound(competitionId, roundInsert);
return new Response(JSON.stringify(round));
return new Response(JSON.stringify(round), {
headers: {
'Content-Type': 'application/json'
}
});
};

View file

@ -12,9 +12,7 @@ import { getCompetitionWithAll } from '@/lib/server/db/queries/competitions';
export const load: PageServerLoad = async ({ params, locals }) => {
try {
const id = Number.parseInt(params.id);
const competition = await getCompetitionWithAll(id);
const competition = await getCompetitionWithAll(params.id);
if (!competition) {
throw error(404, 'Competition not found');
@ -28,7 +26,7 @@ export const load: PageServerLoad = async ({ params, locals }) => {
competition: competition,
createForm: await superValidate(zod(formSchema))
};
} catch (e) {
} catch {
return redirect(302, '/');
}
};
@ -44,9 +42,9 @@ export const actions = {
}
// get competition id from url
const id = Number.parseInt(event.params.id, 10);
const id = event.params.id;
if (id === -1) {
if (id === '') {
throw error(400, 'Invalid competition id');
}
@ -84,12 +82,12 @@ export const actions = {
throw error(400, 'Team name is required');
}
const teamId = Number.parseInt(team, 10);
const teamId = team;
// get competition id from url
const id = Number.parseInt(event.params.id, 10);
const id = event.params.id;
if (id === -1) {
if (id === '') {
throw error(400, 'Invalid competition id');
}
@ -120,9 +118,9 @@ export const actions = {
const description = data.get('description')?.toString();
// get competition id from url
const id = Number.parseInt(event.params.id, 10);
const id = event.params.id;
if (id === -1) {
if (id === '') {
console.log(id);
throw error(400, 'Invalid competition id');
}

View file

@ -14,13 +14,14 @@
import Tabs from '$lib/components/ui/tabs/tabs.svelte';
import Textarea from '$lib/components/ui/textarea/textarea.svelte';
import { formatDate } from '$lib/utils';
import { CalendarDays, Clock, MapPin, PlusIcon, Trash2Icon, Trophy, Users } from 'lucide-svelte';
import { Svelvet } from 'svelvet';
import type { PageProps } from './$types';
import CreateRound from '@/lib/components/rounds/create-round.svelte';
import { CalendarDays, Clock, MapPin, PlusIcon, Trash2Icon, Users } from 'lucide-svelte';
import type { PageProps } from './$types';
let { data }: PageProps = $props();
let competition = $state(data.competition);
let tabValue = $state('rounds');
let showInputTeam = $state(false);
@ -29,33 +30,54 @@
let showAddRound = $state(false);
$effect(() => {
competition = data.competition;
});
$effect(() => {
if (competition.rounds) {
// on new one added scroll to it
const round = competition.rounds[competition.rounds.length - 1];
if (round) {
console.log(round.id);
const roundElement = document.getElementById(`round-${round.id}`);
if (roundElement) {
console.log('found element', roundElement);
roundElement.scrollIntoView({ behavior: 'smooth' });
} else {
console.log('no element found');
}
}
}
});
function clearAndCloseDescription() {
showInputDescription = false;
}
</script>
<svelte:head>
<title>{data.competition.name} | Competition Details</title>
<title>{competition.name} | Competition Details</title>
</svelte:head>
<div class="container mx-auto max-w-4xl px-4 py-8">
<div class="mb-8 flex items-start justify-between">
<div>
<h1 class="text-3xl font-bold">{data.competition.name}</h1>
<h1 class="text-3xl font-bold">{competition.name}</h1>
<div class="mt-2 flex items-center gap-2">
<Badge variant="outline" class="flex items-center gap-1">
<CalendarDays class="h-4 w-4" />
{formatDate(new Date(data.competition.start_date))}
{formatDate(new Date(competition.start_date))}
</Badge>
{#if data.competition.location}
{#if competition.location}
<Badge variant="outline" class="flex items-center gap-1">
<MapPin class="h-4 w-4" />
{data.competition.location}
{competition.location}
</Badge>
{/if}
<Badge variant="outline" class="flex items-center gap-1">
<Users class="h-4 w-4" />
Teams: {data.competition.teams?.length || 0}
Teams: {competition.teams?.length || 0}
</Badge>
</div>
</div>
@ -71,9 +93,7 @@
<TabsTrigger value="rounds">Rounds</TabsTrigger>
</TabsList>
<Button
hidden={tabValue !== 'rounds' ||
!data.competition.rounds ||
data.competition.rounds.length === 0}
hidden={tabValue !== 'rounds' || !competition.rounds || competition.rounds.length === 0}
onclick={() => (showAddRound = !showAddRound)}>Add Round<PlusIcon /></Button
>
</div>
@ -97,8 +117,8 @@
<Button onclick={() => clearAndCloseDescription()}>Cancel</Button>
</div>
</form>
{:else if data.competition.description}
<p class="text-gray-700 dark:text-gray-300">{data.competition.description}</p>
{:else if competition.description}
<p class="text-gray-700 dark:text-gray-300">{competition.description}</p>
{:else}
<p class="text-gray-500 italic">No description available</p>
{/if}
@ -117,12 +137,12 @@
<CardContent>
<div class="flex items-center gap-2">
<Clock class="h-5 w-5 text-blue-500" />
<span>Created: {formatDate(new Date(data.competition.created_at))}</span>
<span>Created: {formatDate(new Date(competition.created_at))}</span>
</div>
{#if data.competition.updated_at}
{#if competition.updated_at}
<div class="flex items-center gap-2">
<Clock class="h-5 w-5 text-green-500" />
<span>Updated: {formatDate(new Date(data.competition.updated_at))}</span>
<span>Updated: {formatDate(new Date(competition.updated_at))}</span>
</div>
{/if}
</CardContent>
@ -135,11 +155,11 @@
<h2 class="text-xl font-semibold">Teams</h2>
</CardHeader>
<CardContent>
{#if !data.competition.teams || data.competition.teams.length === 0}
{#if !competition.teams || competition.teams.length === 0}
<p class="text-gray-500 italic">No teams have been added yet</p>
{:else}
<div class="flex flex-col gap-4">
{#each data.competition.teams as team}
{#each competition.teams as team}
<div class="">
<form
method="post"
@ -179,11 +199,15 @@
</TabsContent>
<TabsContent value="rounds">
{#if showAddRound || !data.competition.rounds || data.competition.rounds.length === 0}
<CreateRound competitionId={data.competition.id} />
{#if showAddRound || !competition.rounds || competition.rounds.length === 0}
<CreateRound
bind:showAddRound
bind:rounds={competition.rounds}
competitionId={competition.id}
/>
{:else}
{#each data.competition.rounds as round (round.id)}
<Round {round} />
{#each competition.rounds as round, round_number (round.id)}
<Round id={round.id} {round} {round_number} />
{/each}
{/if}
</TabsContent>

View file

@ -0,0 +1,31 @@
import { getCompetition } from '@/lib/server/db/queries/competitions';
import { getRound } from '@/lib/server/db/queries/rounds';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ params, locals }) => {
const competitionId = params.id;
const roundId = params.round_id;
const { user } = locals;
if (!user) {
throw new Error('Unauthorized');
}
if (competitionId === '') {
throw new Error('Invalid competition id');
}
if (roundId === '') {
throw new Error('Invalid round id');
}
const competition = await getCompetition(competitionId);
if (!competition) {
throw new Error('Invalid competition');
}
if (competition.owner !== locals.user.id) {
throw new Error('Unauthorized');
}
const round = await getRound(competitionId, roundId);
if (!round) {
throw new Error('Invalid round');
}
return { competition: competition, round };
};

View file

@ -0,0 +1,7 @@
<script lang="ts">
import type { PageProps } from './$types';
let { data }: PageProps = $props();
</script>
{JSON.stringify(data)}