mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Moving validations to separate folder, upgrading superforms v2, and shadcn components.
This commit is contained in:
parent
becf1d8349
commit
8f9db3fea5
53 changed files with 997 additions and 583 deletions
24
package.json
24
package.json
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@melt-ui/pp": "^0.3.0",
|
||||
"@melt-ui/svelte": "^0.74.1",
|
||||
"@melt-ui/svelte": "^0.74.2",
|
||||
"@playwright/test": "^1.41.2",
|
||||
"@resvg/resvg-js": "^2.6.0",
|
||||
"@sveltejs/adapter-auto": "^3.1.1",
|
||||
|
|
@ -34,14 +34,14 @@
|
|||
"@sveltejs/kit": "^2.5.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/pg": "^8.11.0",
|
||||
"@types/node": "^20.11.20",
|
||||
"@types/pg": "^8.11.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"dotenv": "^16.4.5",
|
||||
"drizzle-kit": "^0.20.14",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"just-clone": "^6.2.0",
|
||||
|
|
@ -53,17 +53,17 @@
|
|||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-svelte": "^3.2.1",
|
||||
"prisma": "^5.9.1",
|
||||
"sass": "^1.71.0",
|
||||
"sass": "^1.71.1",
|
||||
"satori": "^0.10.13",
|
||||
"satori-html": "^0.3.2",
|
||||
"svelte": "^4.2.11",
|
||||
"svelte": "^4.2.12",
|
||||
"svelte-check": "^3.6.4",
|
||||
"svelte-meta-tags": "^3.1.0",
|
||||
"svelte-preprocess": "^5.1.3",
|
||||
"svelte-sequential-preprocessor": "^2.0.1",
|
||||
"sveltekit-flash-message": "^2.4.2",
|
||||
"sveltekit-rate-limiter": "^0.4.3",
|
||||
"sveltekit-superforms": "^1.13.4",
|
||||
"sveltekit-superforms": "^2.6.2",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslib": "^2.6.1",
|
||||
|
|
@ -93,31 +93,31 @@
|
|||
"@sveltejs/adapter-vercel": "^5.1.0",
|
||||
"@types/feather-icons": "^4.29.4",
|
||||
"@vercel/og": "^0.5.20",
|
||||
"bits-ui": "^0.18.1",
|
||||
"bits-ui": "^0.18.2",
|
||||
"boardgamegeekclient": "^1.9.1",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.0",
|
||||
"cookie": "^0.6.0",
|
||||
"drizzle-orm": "^0.29.4",
|
||||
"feather-icons": "^4.29.1",
|
||||
"formsnap": "^0.4.4",
|
||||
"formsnap": "^0.5.1",
|
||||
"html-entities": "^2.4.0",
|
||||
"iconify-icon": "^2.0.0",
|
||||
"just-kebab-case": "^4.2.0",
|
||||
"loader": "^2.1.1",
|
||||
"lucia": "3.0.1",
|
||||
"lucide-svelte": "^0.335.0",
|
||||
"lucide-svelte": "^0.340.0",
|
||||
"mysql2": "^3.9.1",
|
||||
"nanoid": "^5.0.6",
|
||||
"open-props": "^1.6.19",
|
||||
"oslo": "^1.1.2",
|
||||
"oslo": "^1.1.3",
|
||||
"pg": "^8.11.3",
|
||||
"postgres": "^3.4.3",
|
||||
"radix-svelte": "^0.9.0",
|
||||
"svelte-french-toast": "^1.2.0",
|
||||
"svelte-lazy-loader": "^1.0.0",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"tailwind-variants": "^0.1.20",
|
||||
"tailwind-variants": "^0.2.0",
|
||||
"tailwindcss-animate": "^1.0.6",
|
||||
"zod-to-json-schema": "^3.22.4"
|
||||
}
|
||||
|
|
|
|||
981
pnpm-lock.yaml
981
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -1,16 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { ConicGradient } from '@skeletonlabs/skeleton';
|
||||
import type { ConicStop } from '@skeletonlabs/skeleton';
|
||||
import { i } from "@inlang/sdk-js";
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
//import SuperDebug from 'sveltekit-superforms/client/SuperDebug.svelte';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import { userSchema } from '$lib/validations/zod-schemas';
|
||||
import { AlertTriangle } from 'lucide-svelte';
|
||||
import { i } from "@inlang/sdk-js";
|
||||
import { signInSchema } from '$lib/validations/auth';
|
||||
export let data;
|
||||
const signInSchema = userSchema.pick({ email: true, password: true });
|
||||
|
||||
const { form, errors, enhance, delayed } = superForm(data.form, {
|
||||
taintedMessage: null,
|
||||
validators: signInSchema,
|
||||
validators: zodClient(signInSchema),
|
||||
delayMs: 0
|
||||
});
|
||||
const conicStops: ConicStop[] = [
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<script lang="ts">
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
import { signUpSchema } from '$lib/config/zod-schemas';
|
||||
import { signUpSchema } from '$lib/validations/auth';
|
||||
|
||||
export let data;
|
||||
|
||||
const { form, errors, enhance } = superForm(data.form, {
|
||||
taintedMessage: null,
|
||||
validators: signUpSchema,
|
||||
validators: zodClient(signUpSchema),
|
||||
delayMs: 0
|
||||
});
|
||||
// $: termsValue = $form.terms as Writable<boolean>;
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@
|
|||
</script>
|
||||
|
||||
<AvatarPrimitive.Fallback
|
||||
class={cn(
|
||||
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
||||
className
|
||||
)}
|
||||
class={cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -11,10 +11,7 @@
|
|||
|
||||
<AvatarPrimitive.Root
|
||||
{delayMs}
|
||||
class={cn(
|
||||
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
||||
className
|
||||
)}
|
||||
class={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ export {
|
|||
//
|
||||
Root as Avatar,
|
||||
Image as AvatarImage,
|
||||
Fallback as AvatarFallback
|
||||
Fallback as AvatarFallback,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,19 +12,19 @@ const buttonVariants = tv({
|
|||
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline"
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10"
|
||||
}
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default"
|
||||
}
|
||||
size: "default",
|
||||
},
|
||||
});
|
||||
|
||||
type Variant = VariantProps<typeof buttonVariants>["variant"];
|
||||
|
|
@ -45,5 +45,5 @@ export {
|
|||
Root as Button,
|
||||
type Props as ButtonProps,
|
||||
type Events as ButtonEvents,
|
||||
buttonVariants
|
||||
buttonVariants,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
class={cn(
|
||||
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
||||
className
|
||||
)}
|
||||
class={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export {
|
|||
Description as CardDescription,
|
||||
Footer as CardFooter,
|
||||
Header as CardHeader,
|
||||
Title as CardTitle
|
||||
Title as CardTitle,
|
||||
};
|
||||
|
||||
export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
export let transition: $$Props["transition"] = slide;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = {
|
||||
duration: 150
|
||||
duration: 150,
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ export {
|
|||
//
|
||||
Root as Collapsible,
|
||||
Content as CollapsibleContent,
|
||||
Trigger as CollapsibleTrigger
|
||||
Trigger as CollapsibleTrigger,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||
import Check from "lucide-svelte/icons/check";
|
||||
import { cn } from "$lib/utils";
|
||||
import { Check } from "lucide-svelte";
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.CheckboxItemProps;
|
||||
type $$Events = DropdownMenuPrimitive.CheckboxItemEvents;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<DropdownMenuPrimitive.CheckboxItem
|
||||
bind:checked
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
type $$Events = DropdownMenuPrimitive.ContentEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let sideOffset: $$Props["sideOffset"] = 4;
|
||||
export let transition: $$Props["transition"] = flyAndScale;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = undefined;
|
||||
export { className as class };
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
<DropdownMenuPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
{sideOffset}
|
||||
class={cn(
|
||||
"z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none",
|
||||
className
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<DropdownMenuPrimitive.Item
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||
import Circle from "lucide-svelte/icons/circle";
|
||||
import { cn } from "$lib/utils";
|
||||
import { Circle } from "lucide-svelte";
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.RadioItemProps;
|
||||
type $$Events = DropdownMenuPrimitive.RadioItemEvents;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
{value}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,6 @@
|
|||
export { className as class };
|
||||
</script>
|
||||
|
||||
<span
|
||||
class={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<span class={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...$$restProps}>
|
||||
<slot />
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
export let transition: $$Props["transition"] = flyAndScale;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = {
|
||||
x: -10,
|
||||
y: 0
|
||||
y: 0,
|
||||
};
|
||||
export { className as class };
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
|
||||
import ChevronRight from "lucide-svelte/icons/chevron-right";
|
||||
import { cn } from "$lib/utils";
|
||||
import { ChevronRight } from "lucide-svelte";
|
||||
|
||||
type $$Props = DropdownMenuPrimitive.SubTriggerProps & {
|
||||
inset?: boolean;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
class={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent",
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:text-accent-foreground",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -44,5 +44,5 @@ export {
|
|||
RadioGroup as DropdownMenuRadioGroup,
|
||||
SubContent as DropdownMenuSubContent,
|
||||
SubTrigger as DropdownMenuSubTrigger,
|
||||
CheckboxItem as DropdownMenuCheckboxItem
|
||||
CheckboxItem as DropdownMenuCheckboxItem,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts">
|
||||
import * as Button from "$lib/components/ui/button";
|
||||
|
||||
type $$Props = Button.Props;
|
||||
type $$Events = Button.Events;
|
||||
</script>
|
||||
|
||||
<Button.Root type="submit" {...$$restProps} on:click on:keydown>
|
||||
<Button.Root type="submit" {...$$restProps}>
|
||||
<slot />
|
||||
</Button.Root>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Form as FormPrimitive } from "formsnap";
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
|
|
@ -8,6 +8,10 @@
|
|||
export { className as class };
|
||||
</script>
|
||||
|
||||
<FormPrimitive.Description class={cn("text-sm text-muted-foreground", className)} {...$$restProps}>
|
||||
<slot />
|
||||
<FormPrimitive.Description
|
||||
class={cn("text-sm text-muted-foreground", className)}
|
||||
{...$$restProps}
|
||||
let:descriptionAttrs
|
||||
>
|
||||
<slot {descriptionAttrs} />
|
||||
</FormPrimitive.Description>
|
||||
|
|
|
|||
26
src/lib/components/ui/form/form-element-field.svelte
Normal file
26
src/lib/components/ui/form/form-element-field.svelte
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<script lang="ts" context="module">
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import type { FormPathLeaves, SuperForm } from "sveltekit-superforms";
|
||||
type T = Record<string, unknown>;
|
||||
type U = unknown;
|
||||
</script>
|
||||
|
||||
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPathLeaves<T>">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = FormPrimitive.ElementFieldProps<T, U> & HTMLAttributes<HTMLElement>;
|
||||
|
||||
export let form: SuperForm<T>;
|
||||
export let name: U;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<FormPrimitive.ElementField {form} {name} let:constraints let:errors let:tainted let:value>
|
||||
<div class={cn("space-y-2", className)}>
|
||||
<slot {constraints} {errors} {tainted} {value} />
|
||||
</div>
|
||||
</FormPrimitive.ElementField>
|
||||
26
src/lib/components/ui/form/form-field-errors.svelte
Normal file
26
src/lib/components/ui/form/form-field-errors.svelte
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<script lang="ts">
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = FormPrimitive.FieldErrorsProps & {
|
||||
errorClasses?: string | undefined | null;
|
||||
};
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
export let errorClasses: $$Props["class"] = undefined;
|
||||
</script>
|
||||
|
||||
<FormPrimitive.FieldErrors
|
||||
class={cn("text-sm font-medium text-destructive", className)}
|
||||
{...$$restProps}
|
||||
let:errors
|
||||
let:fieldErrorsAttrs
|
||||
let:errorAttrs
|
||||
>
|
||||
<slot {errors} {fieldErrorsAttrs} {errorAttrs}>
|
||||
{#each errors as error}
|
||||
<div {...errorAttrs} class={cn(errorClasses)}>{error}</div>
|
||||
{/each}
|
||||
</slot>
|
||||
</FormPrimitive.FieldErrors>
|
||||
26
src/lib/components/ui/form/form-field.svelte
Normal file
26
src/lib/components/ui/form/form-field.svelte
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<script lang="ts" context="module">
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import type { FormPath, SuperForm } from "sveltekit-superforms";
|
||||
type T = Record<string, unknown>;
|
||||
type U = unknown;
|
||||
</script>
|
||||
|
||||
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = FormPrimitive.FieldProps<T, U> & HTMLAttributes<HTMLElement>;
|
||||
|
||||
export let form: SuperForm<T>;
|
||||
export let name: U;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<FormPrimitive.Field {form} {name} let:constraints let:errors let:tainted let:value>
|
||||
<div class={cn("space-y-2", className)}>
|
||||
<slot {constraints} {errors} {tainted} {value} />
|
||||
</div>
|
||||
</FormPrimitive.Field>
|
||||
31
src/lib/components/ui/form/form-fieldset.svelte
Normal file
31
src/lib/components/ui/form/form-fieldset.svelte
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<script lang="ts" context="module">
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import type { FormPath, SuperForm } from "sveltekit-superforms";
|
||||
type T = Record<string, unknown>;
|
||||
type U = unknown;
|
||||
</script>
|
||||
|
||||
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = FormPrimitive.FieldsetProps<T, U>;
|
||||
|
||||
export let form: SuperForm<T>;
|
||||
export let name: U;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<FormPrimitive.Fieldset
|
||||
{form}
|
||||
{name}
|
||||
let:constraints
|
||||
let:errors
|
||||
let:tainted
|
||||
let:value
|
||||
class={cn("space-y-2", className)}
|
||||
>
|
||||
<slot {constraints} {errors} {tainted} {value} />
|
||||
</FormPrimitive.Fieldset>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import type { Label as LabelPrimitive } from "bits-ui";
|
||||
import { getFormField } from "formsnap";
|
||||
import { getFormControl } from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
import { Label } from "$lib/components/ui/label";
|
||||
|
||||
|
|
@ -9,9 +9,9 @@
|
|||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
|
||||
const { errors, ids } = getFormField();
|
||||
const { labelAttrs } = getFormControl();
|
||||
</script>
|
||||
|
||||
<Label for={$ids.input} class={cn($errors && "text-destructive", className)} {...$$restProps}>
|
||||
<slot />
|
||||
<Label {...$labelAttrs} class={cn("data-[fs-error]:text-destructive", className)} {...$$restProps}>
|
||||
<slot {labelAttrs} />
|
||||
</Label>
|
||||
|
|
|
|||
17
src/lib/components/ui/form/form-legend.svelte
Normal file
17
src/lib/components/ui/form/form-legend.svelte
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<script lang="ts">
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import { cn } from "$lib/utils";
|
||||
|
||||
type $$Props = FormPrimitive.LegendProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<FormPrimitive.Legend
|
||||
{...$$restProps}
|
||||
class={cn("text-sm font-medium leading-none data-[fs-error]:text-destructive", className)}
|
||||
let:legendAttrs
|
||||
>
|
||||
<slot {legendAttrs} />
|
||||
</FormPrimitive.Legend>
|
||||
|
|
@ -1,82 +1,33 @@
|
|||
import { Form as FormPrimitive, getFormField } from "formsnap";
|
||||
import * as RadioGroupComp from "$lib/components/ui/radio-group";
|
||||
import * as SelectComp from "$lib/components/ui/select";
|
||||
import type { Writable } from "svelte/store";
|
||||
import Item from "./form-item.svelte";
|
||||
import Input from "./form-input.svelte";
|
||||
import Textarea from "./form-textarea.svelte";
|
||||
import * as FormPrimitive from "formsnap";
|
||||
import Description from "./form-description.svelte";
|
||||
import Label from "./form-label.svelte";
|
||||
import Validation from "./form-validation.svelte";
|
||||
import Checkbox from "./form-checkbox.svelte";
|
||||
import Switch from "./form-switch.svelte";
|
||||
import NativeSelect from "./form-native-select.svelte";
|
||||
import RadioGroup from "./form-radio-group.svelte";
|
||||
import Select from "./form-select.svelte";
|
||||
import SelectTrigger from "./form-select-trigger.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 Root = FormPrimitive.Root;
|
||||
const Field = FormPrimitive.Field;
|
||||
const Control = FormPrimitive.Control;
|
||||
const RadioItem = RadioGroupComp.Item;
|
||||
const NativeRadio = FormPrimitive.Radio;
|
||||
const SelectContent = SelectComp.Content;
|
||||
const SelectLabel = SelectComp.Label;
|
||||
const SelectGroup = SelectComp.Group;
|
||||
const SelectItem = SelectComp.Item;
|
||||
const SelectSeparator = SelectComp.Separator;
|
||||
|
||||
export type TextareaGetFormField = Omit<ReturnType<typeof getFormField>, "value"> & {
|
||||
value: Writable<string>;
|
||||
};
|
||||
|
||||
export {
|
||||
Root,
|
||||
Field,
|
||||
Control,
|
||||
Item,
|
||||
Input,
|
||||
Label,
|
||||
Button,
|
||||
Switch,
|
||||
Select,
|
||||
Checkbox,
|
||||
Textarea,
|
||||
Validation,
|
||||
RadioGroup,
|
||||
RadioItem,
|
||||
FieldErrors,
|
||||
Description,
|
||||
SelectContent,
|
||||
SelectLabel,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectSeparator,
|
||||
SelectTrigger,
|
||||
NativeSelect,
|
||||
NativeRadio,
|
||||
Fieldset,
|
||||
Legend,
|
||||
ElementField,
|
||||
//
|
||||
Root as Form,
|
||||
Field as FormField,
|
||||
Control as FormControl,
|
||||
Item as FormItem,
|
||||
Input as FormInput,
|
||||
Textarea as FormTextarea,
|
||||
Description as FormDescription,
|
||||
Label as FormLabel,
|
||||
Validation as FormValidation,
|
||||
NativeSelect as FormNativeSelect,
|
||||
NativeRadio as FormNativeRadio,
|
||||
Checkbox as FormCheckbox,
|
||||
Switch as FormSwitch,
|
||||
RadioGroup as FormRadioGroup,
|
||||
RadioItem as FormRadioItem,
|
||||
Select as FormSelect,
|
||||
SelectContent as FormSelectContent,
|
||||
SelectLabel as FormSelectLabel,
|
||||
SelectGroup as FormSelectGroup,
|
||||
SelectItem as FormSelectItem,
|
||||
SelectSeparator as FormSelectSeparator,
|
||||
SelectTrigger as FormSelectTrigger,
|
||||
Button as FormButton
|
||||
FieldErrors as FormFieldErrors,
|
||||
Fieldset as FormFieldset,
|
||||
Legend as FormLegend,
|
||||
ElementField as FormElementField,
|
||||
Button as FormButton,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ import Root from "./label.svelte";
|
|||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Label
|
||||
Root as Label,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ export {
|
|||
Link as PaginationLink,
|
||||
PrevButton as PaginationPrevButton,
|
||||
NextButton as PaginationNextButton,
|
||||
Ellipsis as PaginationEllipsis
|
||||
Ellipsis as PaginationEllipsis,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import MoreHorizontal from "lucide-svelte/icons/more-horizontal";
|
||||
import { cn } from "$lib/utils";
|
||||
import { MoreHorizontal } from "lucide-svelte";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLSpanElement>;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
class={cn(
|
||||
buttonVariants({
|
||||
variant: isActive ? "outline" : "ghost",
|
||||
size
|
||||
size,
|
||||
}),
|
||||
className
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { Pagination as PaginationPrimitive } from "bits-ui";
|
||||
import ChevronRight from "lucide-svelte/icons/chevron-right";
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { cn } from "$lib/utils";
|
||||
import { ChevronRight } from "lucide-svelte";
|
||||
|
||||
type $$Props = PaginationPrimitive.NextButtonProps;
|
||||
type $$Events = PaginationPrimitive.NextButtonEvents;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { Pagination as PaginationPrimitive } from "bits-ui";
|
||||
import ChevronLeft from "lucide-svelte/icons/chevron-left";
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { cn } from "$lib/utils";
|
||||
import { ChevronLeft } from "lucide-svelte";
|
||||
|
||||
type $$Props = PaginationPrimitive.PrevButtonProps;
|
||||
type $$Events = PaginationPrimitive.PrevButtonEvents;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
asChild
|
||||
{...$$restProps}
|
||||
>
|
||||
<nav {...builder} class={cn("mx-auto flex flex-col w-full items-center", className)}>
|
||||
<nav {...builder} class={cn("mx-auto flex w-full flex-col items-center", className)}>
|
||||
<slot {pages} {range} {currentPage} />
|
||||
</nav>
|
||||
</PaginationPrimitive.Root>
|
||||
|
|
|
|||
|
|
@ -1,90 +1,43 @@
|
|||
import { z } from 'zod';
|
||||
import { userSchema } from './zod-schemas';
|
||||
|
||||
export type ListGame = {
|
||||
id: string;
|
||||
game_name: string;
|
||||
game_id: string;
|
||||
collection_id: string;
|
||||
wishlist_id: string;
|
||||
times_played: number;
|
||||
thumb_url: string | null;
|
||||
in_collection: boolean;
|
||||
in_wishlist: boolean;
|
||||
};
|
||||
|
||||
export const modifyListGameSchema = z.object({
|
||||
id: z.string()
|
||||
export const profileSchema = userSchema.pick({
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
username: true
|
||||
});
|
||||
|
||||
export type ModifyListGame = typeof modifyListGameSchema;
|
||||
|
||||
export const userSchema = z.object({
|
||||
firstName: z.string().trim().optional(),
|
||||
lastName: z.string().trim().optional(),
|
||||
email: z.string().email({ message: 'Please enter a valid email address' }).optional(),
|
||||
username: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(3, { message: 'Username must be at least 3 characters' })
|
||||
.max(50, { message: 'Username must be less than 50 characters' }),
|
||||
password: z
|
||||
.string({ required_error: 'Password is required' })
|
||||
.trim(),
|
||||
confirm_password: z
|
||||
.string({ required_error: 'Confirm Password is required' })
|
||||
.trim(),
|
||||
verified: z.boolean().default(false),
|
||||
token: z.string().optional(),
|
||||
receiveEmail: z.boolean().default(false),
|
||||
createdAt: z.date().optional(),
|
||||
updatedAt: z.date().optional()
|
||||
});
|
||||
|
||||
export const signUpSchema = userSchema
|
||||
.pick({
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
username: true,
|
||||
password: true,
|
||||
confirm_password: true,
|
||||
terms: true
|
||||
export const changeUserPasswordSchema = z
|
||||
.object({
|
||||
current_password: z.string({ required_error: 'Current Password is required' }),
|
||||
password: z.string({ required_error: 'Password is required' }).trim(),
|
||||
confirm_password: z.string({ required_error: 'Confirm Password is required' }).trim()
|
||||
})
|
||||
.superRefine(({ confirm_password, password }, ctx) => {
|
||||
refinePasswords(confirm_password, password, ctx);
|
||||
});
|
||||
|
||||
export const signInSchema = userSchema.pick({
|
||||
username: true,
|
||||
password: true
|
||||
});
|
||||
|
||||
export const updateUserPasswordSchema = userSchema
|
||||
.pick({ password: true, confirm_password: true })
|
||||
.superRefine(({ confirm_password, password }, ctx) => {
|
||||
refinePasswords(confirm_password, password, ctx);
|
||||
});
|
||||
|
||||
export const changeUserPasswordSchema = z
|
||||
.object({
|
||||
current_password: z.string({ required_error: 'Current Password is required' }),
|
||||
password: z
|
||||
.string({ required_error: 'Password is required' })
|
||||
.trim(),
|
||||
confirm_password: z
|
||||
.string({ required_error: 'Confirm Password is required' })
|
||||
.trim()
|
||||
})
|
||||
.superRefine(({ confirm_password, password }, ctx) => {
|
||||
refinePasswords(confirm_password, password, ctx);
|
||||
});
|
||||
|
||||
const refinePasswords = async function(confirm_password: string, password: string, ctx: z.RefinementCtx) {
|
||||
export const refinePasswords = async function (
|
||||
confirm_password: string,
|
||||
password: string,
|
||||
ctx: z.RefinementCtx
|
||||
) {
|
||||
comparePasswords(confirm_password, password, ctx);
|
||||
checkPasswordStrength(password, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
const comparePasswords = async function(confirm_password: string, password: string, ctx: z.RefinementCtx) {
|
||||
const comparePasswords = async function (
|
||||
confirm_password: string,
|
||||
password: string,
|
||||
ctx: z.RefinementCtx
|
||||
) {
|
||||
if (confirm_password !== password) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
|
|
@ -92,15 +45,14 @@ const comparePasswords = async function(confirm_password: string, password: stri
|
|||
path: ['confirm_password']
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkPasswordStrength = async function (password: string, ctx: z.RefinementCtx) {
|
||||
const minimumLength = password.length < 8;
|
||||
const maximumLength = password.length > 128;
|
||||
const containsUppercase = (ch: string) => /[A-Z]/.test(ch);
|
||||
const containsLowercase = (ch: string) => /[a-z]/.test(ch);
|
||||
const containsSpecialChar = (ch: string) =>
|
||||
/[`!@#$%^&*()_\-+=\[\]{};':"\\|,.<>\/?~ ]/.test(ch);
|
||||
const containsSpecialChar = (ch: string) => /[`!@#$%^&*()_\-+=\[\]{};':"\\|,.<>\/?~ ]/.test(ch);
|
||||
let countOfUpperCase = 0,
|
||||
countOfLowerCase = 0,
|
||||
countOfNumbers = 0,
|
||||
|
|
@ -139,7 +91,6 @@ const checkPasswordStrength = async function (password: string, ctx: z.Refinemen
|
|||
errorMessage += ' Be less than 128 characters long.';
|
||||
}
|
||||
|
||||
|
||||
if (errorMessage.length > 'Your password:'.length) {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
|
|
@ -147,4 +98,4 @@ const checkPasswordStrength = async function (password: string, ctx: z.Refinemen
|
|||
path: ['password']
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
21
src/lib/validations/auth.ts
Normal file
21
src/lib/validations/auth.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { refinePasswords } from "./account";
|
||||
import { userSchema } from "./zod-schemas";
|
||||
|
||||
export const signUpSchema = userSchema
|
||||
.pick({
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
username: true,
|
||||
password: true,
|
||||
confirm_password: true,
|
||||
terms: true
|
||||
})
|
||||
.superRefine(({ confirm_password, password }, ctx) => {
|
||||
refinePasswords(confirm_password, password, ctx);
|
||||
});
|
||||
|
||||
export const signInSchema = userSchema.pick({
|
||||
username: true,
|
||||
password: true
|
||||
});
|
||||
45
src/lib/validations/zod-schemas.ts
Normal file
45
src/lib/validations/zod-schemas.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
export type ListGame = {
|
||||
id: string;
|
||||
game_name: string;
|
||||
game_id: string;
|
||||
collection_id: string;
|
||||
wishlist_id: string;
|
||||
times_played: number;
|
||||
thumb_url: string | null;
|
||||
in_collection: boolean;
|
||||
in_wishlist: boolean;
|
||||
};
|
||||
|
||||
export const modifyListGameSchema = z.object({
|
||||
id: z.string()
|
||||
});
|
||||
|
||||
export type ModifyListGame = typeof modifyListGameSchema;
|
||||
|
||||
export const userSchema = z.object({
|
||||
firstName: z.string().trim().optional(),
|
||||
lastName: z.string().trim().optional(),
|
||||
email: z.string()
|
||||
.trim()
|
||||
.max(64, { message: 'Email must be less than 64 characters' })
|
||||
.email({ message: 'Please enter a valid email address' })
|
||||
.optional(),
|
||||
username: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(3, { message: 'Username must be at least 3 characters' })
|
||||
.max(50, { message: 'Username must be less than 50 characters' }),
|
||||
password: z
|
||||
.string({ required_error: 'Password is required' })
|
||||
.trim(),
|
||||
confirm_password: z
|
||||
.string({ required_error: 'Confirm Password is required' })
|
||||
.trim(),
|
||||
verified: z.boolean().default(false),
|
||||
token: z.string().optional(),
|
||||
receiveEmail: z.boolean().default(false),
|
||||
createdAt: z.date().optional(),
|
||||
updatedAt: z.date().optional()
|
||||
});
|
||||
|
|
@ -4,11 +4,11 @@ import { drizzle } from 'drizzle-orm/postgres-js';
|
|||
import { migrate } from 'drizzle-orm/postgres-js/migrator';
|
||||
|
||||
const connection = postgres({
|
||||
host: process.env.DATABASE_HOST,
|
||||
host: process.env.DATABASE_HOST || 'localhost',
|
||||
port: 3306,
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
database: process.env.DATABASE_DB,
|
||||
user: process.env.DATABASE_USER || 'root',
|
||||
password: process.env.DATABASE_PASSWORD || '',
|
||||
database: process.env.DATABASE_DB || 'boredgame',
|
||||
ssl: 'require',
|
||||
max: 1
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { type Actions, error, fail, redirect } from '@sveltejs/kit';
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
import { superValidate } from 'sveltekit-superforms/server';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { modifyListGameSchema, type ListGame } from '$lib/config/zod-schemas.js';
|
||||
import { search_schema } from '$lib/zodValidation.js';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import db from '$lib/drizzle';
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
import { collection_items, collections, games } from '../../../../schema';
|
||||
|
||||
export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
||||
|
|
@ -26,8 +27,8 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
|||
skip
|
||||
};
|
||||
|
||||
const searchForm = await superValidate(searchData, search_schema);
|
||||
const listManageForm = await superValidate(modifyListGameSchema);
|
||||
const searchForm = await superValidate(searchData, zod(search_schema));
|
||||
const listManageForm = await superValidate(zod(modifyListGameSchema));
|
||||
|
||||
try {
|
||||
const collection = await db.query.collections.findFirst({
|
||||
|
|
@ -98,7 +99,7 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
|||
export const actions: Actions = {
|
||||
// Add game to a wishlist
|
||||
add: async (event) => {
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
const form = await superValidate(event, zod(modifyListGameSchema));
|
||||
|
||||
if (!event.locals.user) {
|
||||
throw fail(401);
|
||||
|
|
@ -160,7 +161,7 @@ export const actions: Actions = {
|
|||
// Remove game from a wishlist
|
||||
remove: async (event) => {
|
||||
const { locals } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
const form = await superValidate(event, zod(modifyListGameSchema));
|
||||
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { redirect } from "@sveltejs/kit";
|
||||
import { superValidate } from "sveltekit-superforms/server";
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import type { PageServerLoad } from "../$types";
|
||||
import { BggForm } from "$lib/zodValidation";
|
||||
import { superValidate } from "sveltekit-superforms/server";
|
||||
|
||||
export const load: PageServerLoad = async ({ locals, fetch }) => {
|
||||
const user = locals.user;
|
||||
|
|
@ -9,7 +10,7 @@ export const load: PageServerLoad = async ({ locals, fetch }) => {
|
|||
redirect(302, '/login');
|
||||
}
|
||||
|
||||
const form = await superValidate({}, BggForm);
|
||||
const form = await superValidate({}, zod(BggForm));
|
||||
|
||||
return { form };
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ export const actions: Actions = {
|
|||
// Add game to a wishlist
|
||||
add: async (event) => {
|
||||
const { params, locals, request } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
const form = await superValidate(event, zod(modifyListGameSchema));
|
||||
|
||||
if (!locals.user) {
|
||||
throw fail(401);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { fail, redirect, type Actions } from "@sveltejs/kit";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { setError, superValidate } from 'sveltekit-superforms/server';
|
||||
import { Argon2id } from "oslo/password";
|
||||
import db from "$lib/drizzle";
|
||||
|
|
@ -9,7 +10,7 @@ import type { PageServerLoad } from "./$types";
|
|||
import { users } from "../../../../../schema";
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
const form = await superValidate(event, changeUserPasswordSchema);
|
||||
const form = await superValidate(event, zod(changeUserPasswordSchema));
|
||||
const user = event.locals.user;
|
||||
|
||||
if (!user) {
|
||||
|
|
@ -28,7 +29,7 @@ export const load: PageServerLoad = async (event) => {
|
|||
|
||||
export const actions: Actions = {
|
||||
default: async (event) => {
|
||||
const form = await superValidate(event, changeUserPasswordSchema);
|
||||
const form = await superValidate(event, zod(changeUserPasswordSchema));
|
||||
|
||||
if (!form.valid) {
|
||||
return fail(400, {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
import { changeUserPasswordSchema, userSchema } from '$lib/config/zod-schemas';
|
||||
import { changeUserPasswordSchema, userSchema } from '$lib/validations/zod-schemas.js';
|
||||
import { Label } from '$components/ui/label';
|
||||
import { Input } from '$components/ui/input';
|
||||
import { Button } from '$components/ui/button';
|
||||
|
|
@ -9,7 +10,7 @@
|
|||
|
||||
const { form, errors, enhance, delayed, message } = superForm(data.form, {
|
||||
taintedMessage: null,
|
||||
validators: changeUserPasswordSchema,
|
||||
validators: zodClient(changeUserPasswordSchema),
|
||||
delayMs: 0
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { fail, type Actions } from '@sveltejs/kit';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { message, setError, superValidate } from 'sveltekit-superforms/server';
|
||||
import { redirect } from 'sveltekit-flash-message/server';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import { userSchema } from '$lib/validations/zod-schemas';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { users } from '../../../../schema';
|
||||
import db from '$lib/drizzle';
|
||||
|
|
@ -15,7 +16,7 @@ const profileSchema = userSchema.pick({
|
|||
});
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
const form = await superValidate(event, profileSchema);
|
||||
const form = await superValidate(event, zod(profileSchema));
|
||||
|
||||
if (!event.locals.user) {
|
||||
const message = { type: 'error', message: 'You are not signed in' } as const;
|
||||
|
|
@ -37,7 +38,7 @@ export const load: PageServerLoad = async (event) => {
|
|||
|
||||
export const actions: Actions = {
|
||||
default: async (event) => {
|
||||
const form = await superValidate(event, profileSchema);
|
||||
const form = await superValidate(event, zod(profileSchema));
|
||||
|
||||
if (!form.valid) {
|
||||
return fail(400, {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
import { AlertTriangle, KeyRound } from 'lucide-svelte';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import { profileSchema } from '$lib/validations/account';
|
||||
import * as Alert from "$lib/components/ui/alert";
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import { Input } from '$components/ui/input';
|
||||
|
|
@ -9,16 +10,9 @@
|
|||
|
||||
export let data;
|
||||
|
||||
const profileSchema = userSchema.pick({
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
email: true,
|
||||
username: true
|
||||
});
|
||||
|
||||
const { form, errors, enhance, message } = superForm(data.form, {
|
||||
taintedMessage: null,
|
||||
validators: profileSchema,
|
||||
validators: zodClient(profileSchema),
|
||||
delayMs: 0
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { error, redirect, type Actions } from '@sveltejs/kit';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { superValidate } from 'sveltekit-superforms/server';
|
||||
import { modifyListGameSchema } from '$lib/config/zod-schemas.js';
|
||||
import db from '$lib/drizzle.js';
|
||||
|
|
@ -49,7 +50,7 @@ export const actions: Actions = {
|
|||
// Add game to a wishlist
|
||||
add: async (event) => {
|
||||
const { locals } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
const form = await superValidate(event, zod(modifyListGameSchema));
|
||||
|
||||
try {
|
||||
if (!locals.user) {
|
||||
|
|
@ -111,7 +112,7 @@ export const actions: Actions = {
|
|||
// Remove game from a wishlist
|
||||
remove: async (event) => {
|
||||
const { locals } = event;
|
||||
const form = await superValidate(event, modifyListGameSchema);
|
||||
const form = await superValidate(event, zod(modifyListGameSchema));
|
||||
|
||||
try {
|
||||
if (!locals.user) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
import { Image } from 'svelte-lazy-loader';
|
||||
import { Dices, ExternalLinkIcon, MinusIcon, PlusIcon } from 'lucide-svelte';
|
||||
import type { SavedGameType } from '$lib/types';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { error } from '@sveltejs/kit';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { superValidate } from 'sveltekit-superforms/server';
|
||||
import kebabCase from 'just-kebab-case';
|
||||
import type { GameType, SearchQuery } from '$lib/types';
|
||||
|
|
@ -16,7 +17,7 @@ async function searchForGames(
|
|||
try {
|
||||
console.log('urlQueryParams search games', urlQueryParams);
|
||||
|
||||
const headers: HeadersInit = new Headers();
|
||||
const headers = new Headers();
|
||||
headers.set('Content-Type', 'application/json');
|
||||
const requestInit: RequestInit = {
|
||||
method: 'GET',
|
||||
|
|
@ -112,7 +113,7 @@ export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
|||
skip: Number(searchParams.skip || defaults.skip),
|
||||
limit: Number(searchParams.limit || defaults.limit),
|
||||
exact: searchParams.exact ? searchParams.exact === 'true' : defaults.exact
|
||||
}, search_schema);
|
||||
}, zod(search_schema));
|
||||
|
||||
const queryParams: SearchQuery = {
|
||||
limit: form.data?.limit,
|
||||
|
|
@ -189,7 +190,7 @@ export const load: PageServerLoad = async ({ locals, fetch, url }) => {
|
|||
|
||||
export const actions = {
|
||||
random: async ({ request, locals, fetch }): Promise<any> => {
|
||||
const form = await superValidate(request, search_schema);
|
||||
const form = await superValidate(request, zod(search_schema));
|
||||
const queryParams: SearchQuery = {
|
||||
order_by: 'rank',
|
||||
ascending: false,
|
||||
|
|
|
|||
|
|
@ -1,21 +1,17 @@
|
|||
import { fail, type Actions } from '@sveltejs/kit';
|
||||
import { eq, sql } from 'drizzle-orm';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { setError, superValidate } from 'sveltekit-superforms/server';
|
||||
import { redirect } from 'sveltekit-flash-message/server';
|
||||
import { lucia } from '$lib/server/auth';
|
||||
import { Argon2id } from 'oslo/password';
|
||||
import { userSchema } from '$lib/config/zod-schemas';
|
||||
import db from '$lib/drizzle';
|
||||
import { signInSchema } from '$lib/validations/auth'
|
||||
import { collections, users, wishlists } from '../../../schema';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
const signInSchema = userSchema.pick({
|
||||
username: true,
|
||||
password: true
|
||||
});
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
const form = await superValidate(event, signInSchema);
|
||||
const form = await superValidate(event, zod(signInSchema));
|
||||
|
||||
console.log('login load event', event);
|
||||
if (event.locals.user) {
|
||||
|
|
@ -31,7 +27,7 @@ export const load: PageServerLoad = async (event) => {
|
|||
export const actions: Actions = {
|
||||
default: async (event) => {
|
||||
const { locals } = event;
|
||||
const form = await superValidate(event, signInSchema);
|
||||
const form = await superValidate(event, zod(signInSchema));
|
||||
|
||||
if (!form.valid) {
|
||||
form.data.password = '';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
import * as flashModule from 'sveltekit-flash-message/client';
|
||||
import { AlertCircle } from "lucide-svelte";
|
||||
import { signInSchema } from '$lib/config/zod-schemas.js';
|
||||
import { signInSchema } from '$lib/validations/zod-schemas.js';
|
||||
import { Label } from '$components/ui/label';
|
||||
import { Input } from '$components/ui/input';
|
||||
import { Button } from '$components/ui/button';
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
syncFlashMessage: false,
|
||||
taintedMessage: null,
|
||||
validators: signInSchema,
|
||||
validators: zodClient(signInSchema),
|
||||
validationMethod: 'oninput',
|
||||
delayMs: 0,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { slide } from 'svelte/transition';
|
||||
import { quintIn } from 'svelte/easing';
|
||||
import { zodClient } from 'sveltekit-superforms/adapters';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
import * as flashModule from 'sveltekit-flash-message/client';
|
||||
import { ChevronsUpDown } from "lucide-svelte";
|
||||
import { Button } from '$components/ui/button';
|
||||
import { Label } from '$components/ui/label';
|
||||
import { Input } from '$components/ui/input';
|
||||
import { signUpSchema } from '$lib/config/zod-schemas.js';
|
||||
import { signUpSchema } from '$lib/validations/zod-schemas.js';
|
||||
import * as Collapsible from '$lib/components/ui/collapsible';
|
||||
import * as Alert from '$lib/components/ui/alert';
|
||||
import { boredState } from '$lib/stores/boredState.js';
|
||||
|
|
@ -25,7 +26,7 @@
|
|||
},
|
||||
},
|
||||
taintedMessage: null,
|
||||
validators: signUpSchema,
|
||||
validators: zodClient(signUpSchema),
|
||||
delayMs: 0,
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue