From 764d0c0526a190ca7c5ea73ae854c86e2459c69b Mon Sep 17 00:00:00 2001 From: unurled Date: Sun, 6 Jul 2025 14:56:26 +0200 Subject: [PATCH] add round creation --- package.json | 2 + src/app.d.ts | 8 ++++ src/lib/components/app-layout.svelte | 2 +- src/lib/components/nav.svelte | 4 +- src/lib/components/rounds/create-round.svelte | 41 +++++++++++++++++++ src/lib/components/rounds/create-schema.ts | 7 ++++ src/lib/components/rounds/rounds.svelte | 10 +++++ src/lib/components/ui/form/form-button.svelte | 7 ++++ .../ui/form/form-description.svelte | 17 ++++++++ .../ui/form/form-element-field.svelte | 24 +++++++++++ .../ui/form/form-field-errors.svelte | 30 ++++++++++++++ src/lib/components/ui/form/form-field.svelte | 29 +++++++++++++ .../components/ui/form/form-fieldset.svelte | 15 +++++++ src/lib/components/ui/form/form-label.svelte | 24 +++++++++++ src/lib/components/ui/form/form-legend.svelte | 16 ++++++++ src/lib/components/ui/form/index.ts | 33 +++++++++++++++ src/lib/components/ui/radio-group/index.ts | 10 +++++ .../ui/radio-group/radio-group-item.svelte | 31 ++++++++++++++ .../ui/radio-group/radio-group.svelte | 19 +++++++++ src/routes/+layout.svelte | 2 +- src/routes/+page.server.ts | 2 +- src/routes/+page.svelte | 2 +- src/routes/competitions/[id]/+page.server.ts | 12 ++++-- src/routes/competitions/[id]/+page.svelte | 33 ++++++++------- svelte.config.js | 3 +- 25 files changed, 356 insertions(+), 27 deletions(-) create mode 100644 src/lib/components/rounds/create-round.svelte create mode 100644 src/lib/components/rounds/create-schema.ts create mode 100644 src/lib/components/rounds/rounds.svelte create mode 100644 src/lib/components/ui/form/form-button.svelte create mode 100644 src/lib/components/ui/form/form-description.svelte create mode 100644 src/lib/components/ui/form/form-element-field.svelte create mode 100644 src/lib/components/ui/form/form-field-errors.svelte create mode 100644 src/lib/components/ui/form/form-field.svelte create mode 100644 src/lib/components/ui/form/form-fieldset.svelte create mode 100644 src/lib/components/ui/form/form-label.svelte create mode 100644 src/lib/components/ui/form/form-legend.svelte create mode 100644 src/lib/components/ui/form/index.ts create mode 100644 src/lib/components/ui/radio-group/index.ts create mode 100644 src/lib/components/ui/radio-group/radio-group-item.svelte create mode 100644 src/lib/components/ui/radio-group/radio-group.svelte diff --git a/package.json b/package.json index 206ab80..004e239 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "bits-ui": "^2.8.6", "clsx": "^2.1.1", "drizzle-kit": "^0.30.2", + "formsnap": "^2.0.1", "mode-watcher": "^1.1.0", "oxlint": "^1.5.0", "prettier": "^3.4.2", @@ -38,6 +39,7 @@ "svelte": "^5.0.0", "svelte-check": "^4.0.0", "svelte-sonner": "^1.0.5", + "sveltekit-superforms": "^2.26.1", "tailwind-merge": "^3.3.1", "tailwind-variants": "^1.0.0", "tailwindcss": "^4.0.0", diff --git a/src/app.d.ts b/src/app.d.ts index b4153f3..651c570 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -30,3 +30,11 @@ export interface NavItem { isActive?: boolean; requireAdmin?: boolean; } + +export enum SchedulingMode { + single = 'signle', + double = 'double', + swiss = 'swiss', + round_robin = 'round_robin', + double_round_robin = 'double_round_robin' +} diff --git a/src/lib/components/app-layout.svelte b/src/lib/components/app-layout.svelte index 6bfecb7..acacb84 100644 --- a/src/lib/components/app-layout.svelte +++ b/src/lib/components/app-layout.svelte @@ -9,7 +9,7 @@ import { cn } from '$lib/utils'; import { getContext } from 'svelte'; import Nav from '$lib/components/nav.svelte'; - import type { User } from '@/server/db/schema/users'; + import type { User } from '$lib/server/db/schema/users'; let { breadcrumbs, diff --git a/src/lib/components/nav.svelte b/src/lib/components/nav.svelte index 08d034c..359dd7f 100644 --- a/src/lib/components/nav.svelte +++ b/src/lib/components/nav.svelte @@ -4,8 +4,8 @@ import { Button } from '$lib/components/ui/button'; import type { NavItem } from '../../app'; import { Home, Trophy, Calendar, UserCircle, Settings } from 'lucide-svelte'; - import type { User } from '@/server/db/schema/users'; - import { type Role } from '@/server/db/schema/roles'; + import type { User } from '$lib/server/db/schema/users'; + import { type Role } from '$lib/server/db/schema/roles'; import { page } from '$app/state'; let { className }: { className?: string } = $props(); diff --git a/src/lib/components/rounds/create-round.svelte b/src/lib/components/rounds/create-round.svelte new file mode 100644 index 0000000..2e9b5f9 --- /dev/null +++ b/src/lib/components/rounds/create-round.svelte @@ -0,0 +1,41 @@ + + +
+ + + {#each Object.values(SchedulingMode) as mode} +
+ + {#snippet children({ props })} + + {mode} + {/snippet} + +
+ {/each} +
+ + + +
+
diff --git a/src/lib/components/rounds/create-schema.ts b/src/lib/components/rounds/create-schema.ts new file mode 100644 index 0000000..89b1b97 --- /dev/null +++ b/src/lib/components/rounds/create-schema.ts @@ -0,0 +1,7 @@ +import z from 'zod'; + +export const formSchema = z.object({ + scheduling_mode: z.nativeEnum(SchedulingMode) +}); + +export type FormSchema = typeof formSchema; diff --git a/src/lib/components/rounds/rounds.svelte b/src/lib/components/rounds/rounds.svelte new file mode 100644 index 0000000..d7eb96d --- /dev/null +++ b/src/lib/components/rounds/rounds.svelte @@ -0,0 +1,10 @@ + + +{JSON.stringify(rounds)} +
+ + diff --git a/src/lib/components/ui/form/form-button.svelte b/src/lib/components/ui/form/form-button.svelte new file mode 100644 index 0000000..cc0c590 --- /dev/null +++ b/src/lib/components/ui/form/form-button.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/form/form-description.svelte b/src/lib/components/ui/form/form-description.svelte new file mode 100644 index 0000000..a5f42be --- /dev/null +++ b/src/lib/components/ui/form/form-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/form/form-element-field.svelte b/src/lib/components/ui/form/form-element-field.svelte new file mode 100644 index 0000000..c3ba111 --- /dev/null +++ b/src/lib/components/ui/form/form-element-field.svelte @@ -0,0 +1,24 @@ + + + + {#snippet children({ constraints, errors, tainted, value })} +
+ {@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })} +
+ {/snippet} +
diff --git a/src/lib/components/ui/form/form-field-errors.svelte b/src/lib/components/ui/form/form-field-errors.svelte new file mode 100644 index 0000000..b4c6fba --- /dev/null +++ b/src/lib/components/ui/form/form-field-errors.svelte @@ -0,0 +1,30 @@ + + + + {#snippet children({ errors, errorProps })} + {#if childrenProp} + {@render childrenProp({ errors, errorProps })} + {:else} + {#each errors as error (error)} +
{error}
+ {/each} + {/if} + {/snippet} +
diff --git a/src/lib/components/ui/form/form-field.svelte b/src/lib/components/ui/form/form-field.svelte new file mode 100644 index 0000000..7481fda --- /dev/null +++ b/src/lib/components/ui/form/form-field.svelte @@ -0,0 +1,29 @@ + + + + {#snippet children({ constraints, errors, tainted, value })} +
+ {@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })} +
+ {/snippet} +
diff --git a/src/lib/components/ui/form/form-fieldset.svelte b/src/lib/components/ui/form/form-fieldset.svelte new file mode 100644 index 0000000..2c85857 --- /dev/null +++ b/src/lib/components/ui/form/form-fieldset.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/lib/components/ui/form/form-label.svelte b/src/lib/components/ui/form/form-label.svelte new file mode 100644 index 0000000..8749360 --- /dev/null +++ b/src/lib/components/ui/form/form-label.svelte @@ -0,0 +1,24 @@ + + + + {#snippet child({ props })} + + {/snippet} + diff --git a/src/lib/components/ui/form/form-legend.svelte b/src/lib/components/ui/form/form-legend.svelte new file mode 100644 index 0000000..9d52f6a --- /dev/null +++ b/src/lib/components/ui/form/form-legend.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/form/index.ts b/src/lib/components/ui/form/index.ts new file mode 100644 index 0000000..0713927 --- /dev/null +++ b/src/lib/components/ui/form/index.ts @@ -0,0 +1,33 @@ +import * as FormPrimitive from "formsnap"; +import Description from "./form-description.svelte"; +import Label from "./form-label.svelte"; +import FieldErrors from "./form-field-errors.svelte"; +import Field from "./form-field.svelte"; +import Fieldset from "./form-fieldset.svelte"; +import Legend from "./form-legend.svelte"; +import ElementField from "./form-element-field.svelte"; +import Button from "./form-button.svelte"; + +const Control = FormPrimitive.Control; + +export { + Field, + Control, + Label, + Button, + FieldErrors, + Description, + Fieldset, + Legend, + ElementField, + // + Field as FormField, + Control as FormControl, + Description as FormDescription, + Label as FormLabel, + FieldErrors as FormFieldErrors, + Fieldset as FormFieldset, + Legend as FormLegend, + ElementField as FormElementField, + Button as FormButton, +}; diff --git a/src/lib/components/ui/radio-group/index.ts b/src/lib/components/ui/radio-group/index.ts new file mode 100644 index 0000000..90b33fe --- /dev/null +++ b/src/lib/components/ui/radio-group/index.ts @@ -0,0 +1,10 @@ +import Root from "./radio-group.svelte"; +import Item from "./radio-group-item.svelte"; + +export { + Root, + Item, + // + Root as RadioGroup, + Item as RadioGroupItem, +}; diff --git a/src/lib/components/ui/radio-group/radio-group-item.svelte b/src/lib/components/ui/radio-group/radio-group-item.svelte new file mode 100644 index 0000000..2cb0710 --- /dev/null +++ b/src/lib/components/ui/radio-group/radio-group-item.svelte @@ -0,0 +1,31 @@ + + + + {#snippet children({ checked })} +
+ {#if checked} + + {/if} +
+ {/snippet} +
diff --git a/src/lib/components/ui/radio-group/radio-group.svelte b/src/lib/components/ui/radio-group/radio-group.svelte new file mode 100644 index 0000000..da2912b --- /dev/null +++ b/src/lib/components/ui/radio-group/radio-group.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 7521dc2..7a39ed9 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -3,7 +3,7 @@ import '../app.css'; import { setContext } from 'svelte'; import type { PageProps } from './$types'; - import { Toaster } from '@/components/ui/sonner'; + import { Toaster } from '$lib/components/ui/sonner'; let { children, diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index 13de5ea..a148c75 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,4 +1,4 @@ -import { getCompetitionsWithAll } from '@/server/db/schema/competitions'; +import { getCompetitionsWithAll } from '$lib/server/db/schema/competitions'; import type { PageServerLoad } from './$types'; export const load: PageServerLoad = async ({ locals }) => { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 39fb630..896d7ad 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -16,7 +16,7 @@ import { Skeleton } from '$lib/components/ui/skeleton'; import type { PageProps } from './$types.js'; import { toast } from 'svelte-sonner'; - import { formatDate } from '@/utils'; + import { formatDate } from '$lib/utils'; const breadcrumbs: BreadcrumbItem[] = [ { diff --git a/src/routes/competitions/[id]/+page.server.ts b/src/routes/competitions/[id]/+page.server.ts index d69b36b..937ae67 100644 --- a/src/routes/competitions/[id]/+page.server.ts +++ b/src/routes/competitions/[id]/+page.server.ts @@ -1,10 +1,13 @@ -import { db } from '@/server/db'; +import { db } from '$lib/server/db'; import type { Actions, PageServerLoad } from './$types'; -import { competitions, getCompetitionWithAll } from '@/server/db/schema/competitions'; +import { competitions, getCompetitionWithAll } from '$lib/server/db/schema/competitions'; import { error, redirect } from '@sveltejs/kit'; import { eq } from 'drizzle-orm'; import { and } from 'drizzle-orm'; -import { teams } from '@/server/db/schema/teams'; +import { teams } from '$lib/server/db/schema/teams'; +import { superValidate } from 'sveltekit-superforms'; +import { zod } from 'sveltekit-superforms/adapters'; +import { formSchema } from '$lib/components/rounds/create-schema'; export const load: PageServerLoad = async ({ params, locals }) => { try { @@ -21,7 +24,8 @@ export const load: PageServerLoad = async ({ params, locals }) => { } return { - competition: competition + competition: competition, + createForm: await superValidate(zod(formSchema)) }; } catch (e) { return redirect(302, '/'); diff --git a/src/routes/competitions/[id]/+page.svelte b/src/routes/competitions/[id]/+page.svelte index 9838361..e68dfcb 100644 --- a/src/routes/competitions/[id]/+page.svelte +++ b/src/routes/competitions/[id]/+page.svelte @@ -1,21 +1,22 @@