From ebe82c74818dc022a0c00769c9429f8eb3045eb1 Mon Sep 17 00:00:00 2001 From: Sanju Sivalingam Date: Tue, 17 Feb 2026 14:32:26 +0530 Subject: [PATCH] feat: add dashboard layout with navigation and auth guard Co-Authored-By: Claude Opus 4.6 --- web/src/lib/api/auth.remote.ts | 29 +++++++++++++++++++++ web/src/routes/+layout.server.ts | 7 +++++ web/src/routes/+page.server.ts | 9 +++++++ web/src/routes/+page.svelte | 1 + web/src/routes/dashboard/+layout.server.ts | 11 ++++++++ web/src/routes/dashboard/+layout.svelte | 29 +++++++++++++++++++++ web/src/routes/dashboard/+page.svelte | 30 ++++++++++++++++++++++ 7 files changed, 116 insertions(+) create mode 100644 web/src/lib/api/auth.remote.ts create mode 100644 web/src/routes/+layout.server.ts create mode 100644 web/src/routes/+page.server.ts create mode 100644 web/src/routes/+page.svelte create mode 100644 web/src/routes/dashboard/+layout.server.ts create mode 100644 web/src/routes/dashboard/+layout.svelte create mode 100644 web/src/routes/dashboard/+page.svelte diff --git a/web/src/lib/api/auth.remote.ts b/web/src/lib/api/auth.remote.ts new file mode 100644 index 0000000..a627a64 --- /dev/null +++ b/web/src/lib/api/auth.remote.ts @@ -0,0 +1,29 @@ +import { redirect } from '@sveltejs/kit'; +import { form, getRequestEvent, query } from '$app/server'; +import { auth } from '$lib/server/auth'; +import { signupSchema, loginSchema } from '$lib/schema/auth'; + +export const signup = form(signupSchema, async (user) => { + await auth.api.signUpEmail({ body: user }); + redirect(307, '/dashboard'); +}); + +export const login = form(loginSchema, async (user) => { + const { request } = getRequestEvent(); + await auth.api.signInEmail({ body: user, headers: request.headers }); + redirect(303, '/dashboard'); +}); + +export const signout = form(async () => { + const { request } = getRequestEvent(); + await auth.api.signOut({ headers: request.headers }); + redirect(303, '/login'); +}); + +export const getUser = query(async () => { + const { locals } = getRequestEvent(); + if (!locals.user) { + redirect(307, '/login'); + } + return locals.user; +}); diff --git a/web/src/routes/+layout.server.ts b/web/src/routes/+layout.server.ts new file mode 100644 index 0000000..c9d39ee --- /dev/null +++ b/web/src/routes/+layout.server.ts @@ -0,0 +1,7 @@ +import type { LayoutServerLoad } from './$types'; + +export const load: LayoutServerLoad = async ({ locals }) => { + return { + user: locals.user ?? null + }; +}; diff --git a/web/src/routes/+page.server.ts b/web/src/routes/+page.server.ts new file mode 100644 index 0000000..3715571 --- /dev/null +++ b/web/src/routes/+page.server.ts @@ -0,0 +1,9 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ locals }) => { + if (locals.user) { + redirect(307, '/dashboard'); + } + redirect(307, '/login'); +}; diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte new file mode 100644 index 0000000..1ef0183 --- /dev/null +++ b/web/src/routes/+page.svelte @@ -0,0 +1 @@ +

Redirecting...

diff --git a/web/src/routes/dashboard/+layout.server.ts b/web/src/routes/dashboard/+layout.server.ts new file mode 100644 index 0000000..097109b --- /dev/null +++ b/web/src/routes/dashboard/+layout.server.ts @@ -0,0 +1,11 @@ +import { redirect } from '@sveltejs/kit'; +import type { LayoutServerLoad } from './$types'; + +export const load: LayoutServerLoad = async ({ locals }) => { + if (!locals.user) { + redirect(307, '/login'); + } + return { + user: locals.user + }; +}; diff --git a/web/src/routes/dashboard/+layout.svelte b/web/src/routes/dashboard/+layout.svelte new file mode 100644 index 0000000..2dc91b7 --- /dev/null +++ b/web/src/routes/dashboard/+layout.svelte @@ -0,0 +1,29 @@ + + +
+ + +
+ {@render children?.()} +
+
diff --git a/web/src/routes/dashboard/+page.svelte b/web/src/routes/dashboard/+page.svelte new file mode 100644 index 0000000..6e55430 --- /dev/null +++ b/web/src/routes/dashboard/+page.svelte @@ -0,0 +1,30 @@ + + +

Dashboard

+

Welcome back, {data.user.name}.

+ +