From 6d3a4185251c55053753a6a736ecf99717ebb94b Mon Sep 17 00:00:00 2001 From: Rasmus Q Date: Mon, 16 Mar 2026 14:37:33 +0000 Subject: [PATCH] refactor: convert wishlist creation from API to form action --- src/routes/+page.server.ts | 43 +++++++++++++++++- src/routes/+page.svelte | 67 ++++++++++++----------------- src/routes/api/wishlists/+server.ts | 52 ---------------------- 3 files changed, 70 insertions(+), 92 deletions(-) delete mode 100644 src/routes/api/wishlists/+server.ts diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index 89f19c3..707a13f 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,4 +1,9 @@ -import type { PageServerLoad } from './$types'; +import type { PageServerLoad, Actions } from './$types'; +import { db } from '$lib/server/db'; +import { wishlists } from '$lib/db/schema'; +import { createId } from '@paralleldrive/cuid2'; +import { fail } from '@sveltejs/kit'; +import { wishlistSchema } from '$lib/server/validation'; export const load: PageServerLoad = async (event) => { const session = await event.locals.auth(); @@ -6,3 +11,39 @@ export const load: PageServerLoad = async (event) => { session }; }; + +export const actions: Actions = { + createWishlist: async ({ request, locals }) => { + const formData = await request.formData(); + const rawData = Object.fromEntries(formData); + + const result = wishlistSchema.safeParse(rawData); + if (!result.success) { + return fail(400, { success: false, error: result.error.errors.map(e => e.message).join(', ') }); + } + + const session = await locals.auth(); + const userId = session?.user?.id || null; + + const ownerToken = createId(); + const publicToken = createId(); + + const [wishlist] = await db + .insert(wishlists) + .values({ + ...result.data, + ownerToken, + publicToken, + userId + }) + .returning(); + + return { + success: true, + ownerToken, + publicToken, + title: wishlist.title, + createdAt: wishlist.createdAt + }; + } +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1defa79..18d5bec 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -14,11 +14,12 @@ import { LanguageToggle } from '$lib/components/ui/language-toggle'; import { goto } from '$app/navigation'; import ColorPicker from '$lib/components/ui/ColorPicker.svelte'; - import type { PageData } from './$types'; + import type { PageData, ActionData } from './$types'; import { languageStore } from '$lib/stores/language.svelte'; import { addLocalWishlist } from '$lib/utils/localWishlists'; + import { enhance } from '$app/forms'; - let { data }: { data: PageData } = $props(); + let { data, form }: { data: PageData; form: ActionData } = $props(); const t = $derived(languageStore.t); @@ -26,40 +27,6 @@ let description = $state(''); let color = $state(null); let isCreating = $state(false); - - async function createWishlist() { - if (!title.trim()) return; - - isCreating = true; - try { - const response = await fetch('/api/wishlists', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ title, description, color }) - }); - - if (response.ok) { - const result = await response.json(); - const { ownerToken, publicToken, title: wishlistTitle, createdAt } = result; - - // If user is not authenticated, save to localStorage - if (!data.session?.user) { - addLocalWishlist({ - ownerToken, - publicToken, - title: wishlistTitle, - createdAt - }); - } - - goto(`/wishlist/${ownerToken}/edit`); - } - } catch (error) { - console.error('Failed to create wishlist:', error); - } finally { - isCreating = false; - } - }
@@ -84,9 +51,28 @@
{ - e.preventDefault(); - createWishlist(); + method="POST" + action="?/createWishlist" + use:enhance={() => { + isCreating = true; + return async ({ result, update }) => { + if (result.type === 'success' && result.data) { + const data = result.data as { ownerToken: string; publicToken: string; title: string; createdAt: string }; + // If user is not authenticated, save to localStorage + if (!data?.session?.user) { + addLocalWishlist({ + ownerToken: data.ownerToken, + publicToken: data.publicToken, + title: data.title, + createdAt: new Date(data.createdAt) + }); + } + goto(`/wishlist/${data.ownerToken}/edit`); + } else { + await update(); + isCreating = false; + } + }; }} class="space-y-4" > @@ -94,6 +80,7 @@ {t.form.descriptionOptional}