diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index e499baa..a6c88b2 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,22 +1,67 @@
- + {#if authChecked} + {#if userProfile && page.url.pathname !== '/login'} + + {/if} -
- {@render children()} -
- - +
+ {@render children()} +
+ {/if}
diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte new file mode 100644 index 0000000..76582b7 --- /dev/null +++ b/frontend/src/routes/login/+page.svelte @@ -0,0 +1,166 @@ + + + + Login + + +
+
+

GameStream

+
+
+ + +
+
+ + +
+ {#if error} +
{error}
+ {/if} + +
+
+
+ + diff --git a/frontend/src/routes/stores/authStore.svelte.ts b/frontend/src/routes/stores/authStore.svelte.ts new file mode 100644 index 0000000..041654c --- /dev/null +++ b/frontend/src/routes/stores/authStore.svelte.ts @@ -0,0 +1,43 @@ +import { goto } from '$app/navigation'; + +interface AuthState { + token: string | null; +} + +function loadToken(): string | null { + if (typeof window === 'undefined') return null; + return localStorage.getItem('auth_token'); +} + +export const authStore: AuthState = $state({ + token: loadToken() +}); + +export function getToken(): string | null { + return authStore.token; +} + +export function setToken(token: string) { + authStore.token = token; + localStorage.setItem('auth_token', token); +} + +export function clearToken() { + authStore.token = null; + localStorage.removeItem('auth_token'); +} + +export function isAuthenticated(): boolean { + return authStore.token !== null; +} + +export function requireAuth() { + if (!isAuthenticated()) { + goto('/login'); + } +} + +export function handleUnauthorized() { + clearToken(); + goto('/login'); +}