diff --git a/src/lib/client/profile.svelte.ts b/src/lib/client/profile.svelte.ts new file mode 100644 index 0000000..d0b8e32 --- /dev/null +++ b/src/lib/client/profile.svelte.ts @@ -0,0 +1,62 @@ +import type { Profile } from '$lib/types'; + +const STORAGE_KEY = 'kochwas.activeProfileId'; + +function loadActiveId(): number | null { + if (typeof localStorage === 'undefined') return null; + const raw = localStorage.getItem(STORAGE_KEY); + if (!raw) return null; + const n = Number(raw); + return Number.isInteger(n) && n > 0 ? n : null; +} + +function saveActiveId(id: number | null): void { + if (typeof localStorage === 'undefined') return; + if (id === null) localStorage.removeItem(STORAGE_KEY); + else localStorage.setItem(STORAGE_KEY, String(id)); +} + +class ProfileStore { + profiles = $state([]); + activeId = $state(null); + loaded = $state(false); + + active = $derived(this.profiles.find((p) => p.id === this.activeId) ?? null); + + async load(): Promise { + const res = await fetch('/api/profiles'); + this.profiles = await res.json(); + const stored = loadActiveId(); + if (stored && this.profiles.some((p) => p.id === stored)) { + this.activeId = stored; + } + this.loaded = true; + } + + select(id: number): void { + this.activeId = id; + saveActiveId(id); + } + + clear(): void { + this.activeId = null; + saveActiveId(null); + } + + async create(name: string, avatar_emoji: string | null): Promise { + const res = await fetch('/api/profiles', { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ name, avatar_emoji }) + }); + if (!res.ok) { + const err = await res.json().catch(() => ({ message: 'unknown error' })); + throw new Error(err.message ?? 'failed to create profile'); + } + const p = (await res.json()) as Profile; + this.profiles = [...this.profiles, p].sort((a, b) => a.name.localeCompare(b.name)); + return p; + } +} + +export const profileStore = new ProfileStore();