import { useCallback, useContext, useEffect, useMemo, useState, type ReactNode, createContext } from 'react'; import { getAuthMe, loginCurator, logoutCurator, type AuthRole, type StaffPermission, } from '../api/client'; interface AuthContextValue { role: AuthRole; username?: string; permissions: StaffPermission[]; isCurator: boolean; isAdmin: boolean; loading: boolean; can: (permission: StaffPermission) => boolean; login: (username: string, password: string) => Promise; logout: () => Promise; refresh: () => Promise; } const AuthContext = createContext(null); function applyAuthState( me: { role: AuthRole; username?: string; permissions?: StaffPermission[] }, setRole: (r: AuthRole) => void, setUsername: (u: string | undefined) => void, setPermissions: (p: StaffPermission[]) => void ) { setRole(me.role); setUsername(me.username); setPermissions(me.role === 'user' ? [] : me.permissions ?? []); } export function AuthProvider({ children }: { children: ReactNode }) { const [role, setRole] = useState('user'); const [username, setUsername] = useState(); const [permissions, setPermissions] = useState([]); const [loading, setLoading] = useState(true); const refresh = useCallback(async () => { const me = await getAuthMe(); applyAuthState(me, setRole, setUsername, setPermissions); }, []); useEffect(() => { refresh().finally(() => setLoading(false)); }, [refresh]); const login = useCallback(async (user: string, password: string) => { const me = await loginCurator(user, password); applyAuthState(me, setRole, setUsername, setPermissions); }, []); const logout = useCallback(async () => { await logoutCurator(); setRole('user'); setUsername(undefined); setPermissions([]); }, []); const can = useCallback( (permission: StaffPermission) => { if (role === 'admin') return true; if (role !== 'curator') return false; return permissions.includes(permission); }, [role, permissions] ); const value = useMemo( () => ({ role, username, permissions, isCurator: role === 'admin' || role === 'curator', isAdmin: role === 'admin', loading, can, login, logout, refresh, }), [role, username, permissions, loading, can, login, logout, refresh] ); return {children}; } export function useAuth(): AuthContextValue { const ctx = useContext(AuthContext); if (!ctx) { throw new Error('useAuth must be used within AuthProvider'); } return ctx; }