e21d0ef67b
Rewrites auth store with typed AuthUser shape (id, name, isAdmin) and localStorage persistence. Adds login page with tanabata decorative images, centered form, purple primary button matching the reference design. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
34 lines
817 B
TypeScript
34 lines
817 B
TypeScript
import { writable, derived } from 'svelte/store';
|
|
|
|
export interface AuthUser {
|
|
id: number;
|
|
name: string;
|
|
isAdmin: boolean;
|
|
}
|
|
|
|
export interface AuthState {
|
|
accessToken: string | null;
|
|
refreshToken: string | null;
|
|
user: AuthUser | null;
|
|
}
|
|
|
|
const initial: AuthState = { accessToken: null, refreshToken: null, user: null };
|
|
|
|
function loadStored(): AuthState {
|
|
if (typeof localStorage === 'undefined') return initial;
|
|
try {
|
|
return JSON.parse(localStorage.getItem('auth') ?? 'null') ?? initial;
|
|
} catch {
|
|
return initial;
|
|
}
|
|
}
|
|
|
|
export const authStore = writable<AuthState>(loadStored());
|
|
|
|
authStore.subscribe((state) => {
|
|
if (typeof localStorage !== 'undefined') {
|
|
localStorage.setItem('auth', JSON.stringify(state));
|
|
}
|
|
});
|
|
|
|
export const isAuthenticated = derived(authStore, ($auth) => !!$auth.accessToken); |