import { createContext, ReactNode, useCallback, useContext, useEffect, useState } from "react"; import * as api from "./api"; import { HTTPError } from "./api"; import type { User } from "./types"; interface AuthCtx { user: User | null; loading: boolean; login: (username: string, password: string) => Promise; register: (username: string, password: string, displayName: string) => Promise; logout: () => Promise; setUser: (u: User | null) => void; } const Ctx = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { api .getMe() .then(setUser) .catch((e) => { if (!(e instanceof HTTPError) || e.status !== 401) { console.warn("getMe failed", e); } }) .finally(() => setLoading(false)); }, []); const login = useCallback(async (username: string, password: string) => { const u = await api.login(username, password); setUser(u); }, []); const register = useCallback(async (username: string, password: string, displayName: string) => { await api.register(username, password, displayName); const u = await api.login(username, password); setUser(u); }, []); const logout = useCallback(async () => { await api.logout(); setUser(null); }, []); return {children}; } export function useAuth(): AuthCtx { const v = useContext(Ctx); if (!v) throw new Error("useAuth: missing AuthProvider"); return v; }