From cb325692f71ff142df5e9ae9c8fae9a3c2ee2f57 Mon Sep 17 00:00:00 2001 From: Noa Virellia Date: Sun, 19 Apr 2026 00:17:20 +0800 Subject: [PATCH] feat(onboarding): detect UUID username and add completeProfile layout action Co-Authored-By: Claude Sonnet 4.6 --- src/routes/(app)/+layout.server.ts | 42 +++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/routes/(app)/+layout.server.ts b/src/routes/(app)/+layout.server.ts index 4e3afde..7fb3240 100644 --- a/src/routes/(app)/+layout.server.ts +++ b/src/routes/(app)/+layout.server.ts @@ -1,11 +1,45 @@ -import { redirect } from '@sveltejs/kit'; -import type { LayoutServerLoad } from './$types'; +import { redirect, fail } from '@sveltejs/kit'; +import { isErr, unwrapErr } from 'option-t/plain_result'; +import { zod, type ZodObjectType } from 'sveltekit-superforms/adapters'; +import { setError, superValidate } from 'sveltekit-superforms'; +import { patchUserUpdate } from '$lib/api'; +import { createApiClient } from '$lib/server/api'; +import { callSdk } from '$lib/server/errors'; +import { onboardingSchema } from '$lib/schemas/onboarding'; +import type { LayoutServerLoad, Actions } from './$types'; -export const load: LayoutServerLoad = ({ locals, url, cookies }) => { +const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; + +// onboardingSchema fields are required strings but don't satisfy ZodObjectType's +// Record index signature — same cast pattern as profile page. +const schema = onboardingSchema as unknown as ZodObjectType; + +export const load: LayoutServerLoad = async ({ locals, url, cookies }) => { if (!locals.user) { const redirectTo = encodeURIComponent(url.pathname + url.search); throw redirect(303, `/app/authorize?redirect_to=${redirectTo}`); } const theme = (cookies.get('theme') as 'dark' | 'light') ?? 'dark'; - return { user: locals.user, theme }; + const needsOnboarding = UUID_RE.test(locals.user.username); + const onboardingForm = await superValidate(zod(schema)); + return { user: locals.user, theme, needsOnboarding, onboardingForm }; +}; + +export const actions: Actions = { + completeProfile: async (event) => { + const onboardingForm = await superValidate(event.request, zod(schema)); + if (!onboardingForm.valid) return fail(400, { onboardingForm }); + const api = createApiClient(event); + const result = await callSdk(() => + patchUserUpdate({ + client: api, + body: { + username: onboardingForm.data.username as string, + nickname: onboardingForm.data.nickname as string + } + }) + ); + if (isErr(result)) return setError(onboardingForm, '', unwrapErr(result).message); + return { onboardingForm }; + } };