import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from 'react'; import { clearTokens, getToken } from '../api/http'; import * as permApi from '../api/permission'; interface AuthState { ready: boolean; token: string; uid: string; roles: string[]; isAdmin: boolean; syncSession: () => void; refreshRoles: () => Promise; signOut: () => void; } const AuthContext = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [ready, setReady] = useState(false); const [token, setToken] = useState(getToken); const [uid, setUid] = useState(() => localStorage.getItem('uid') ?? ''); const [roles, setRoles] = useState(() => { try { return JSON.parse(localStorage.getItem('roles') ?? '[]') as string[]; } catch { return []; } }); const syncSession = useCallback(() => { setToken(getToken()); setUid(localStorage.getItem('uid') ?? ''); }, []); const refreshRoles = useCallback(async () => { if (!getToken()) { setRoles([]); return; } try { const me = await permApi.getMyPermissions(); setRoles(me.roles ?? []); localStorage.setItem('roles', JSON.stringify(me.roles ?? [])); if (me.uid) { setUid(me.uid); localStorage.setItem('uid', me.uid); } } catch { setRoles([]); } }, []); useEffect(() => { (async () => { if (getToken()) await refreshRoles(); setReady(true); })(); }, [refreshRoles]); const signOut = useCallback(() => { clearTokens(); setToken(''); setUid(''); setRoles([]); }, []); const value = useMemo( () => ({ ready, token, uid, roles, isAdmin: permApi.isAdminRole(roles), syncSession, refreshRoles, signOut, }), [ready, token, uid, roles, syncSession, refreshRoles, signOut], ); return {children}; } export function useAuth() { const ctx = useContext(AuthContext); if (!ctx) throw new Error('useAuth 需在 AuthProvider 內'); return ctx; }