diff --git a/frontend/src/routes/[famSlug]/join/[username]/+page.server.ts b/frontend/src/routes/[famSlug]/join/[username]/+page.server.ts new file mode 100644 index 0000000..f05325e --- /dev/null +++ b/frontend/src/routes/[famSlug]/join/[username]/+page.server.ts @@ -0,0 +1,24 @@ +import { fail, redirect } from '@sveltejs/kit'; +import { redeemOtp } from '$lib/server/member-otp'; +import { setSessionCookie } from '$lib/server/session'; + +export const actions = { + default: async (event) => { + const famSlug = event.params.famSlug; + const username = event.params.username; + const fd = await event.request.formData(); + const otp = (fd.get('otp') || '').toString().trim(); + + if (!otp) return fail(400, { error: 'Enter the code shown by your parent.' }); + + try { + const token = await redeemOtp({ famSlug, username, otp }); + event.cookies.delete('device_token', { path: '/' }); + setSessionCookie(event.cookies, token); + } catch (e) { + return fail(400, { error: e instanceof Error ? e.message : 'Join failed' }); + } + + throw redirect(303, `/${famSlug}/${encodeURIComponent(username)}`); + } +}; \ No newline at end of file diff --git a/frontend/src/routes/[famSlug]/join/[username]/+page.svelte b/frontend/src/routes/[famSlug]/join/[username]/+page.svelte new file mode 100644 index 0000000..27dc511 --- /dev/null +++ b/frontend/src/routes/[famSlug]/join/[username]/+page.svelte @@ -0,0 +1,46 @@ + + +Join {famSlug} + +
+
+
+ 🏠 +
+

Welcome to {famSlug}!

+

+ Hi {username} — enter the code your parent + gave you to get started. +

+ +
({})}> + + {#if form?.error} +

{form.error}

+ {/if} + +
+ +

+ Code is valid for 20 minutes. Ask your parent for a new one if it expires. +

+
+
\ No newline at end of file