"use client"; import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react"; interface AuthState { loading: boolean; authEnabled: boolean; loggedIn: boolean; username?: string; refresh: () => Promise; logout: () => Promise; } const AuthContext = createContext(null); export function AuthProvider({ children }: { children: React.ReactNode }) { const [loading, setLoading] = useState(true); const [authEnabled, setAuthEnabled] = useState(false); const [loggedIn, setLoggedIn] = useState(true); const [username, setUsername] = useState(); const refresh = useCallback(async () => { try { const res = await fetch("/api/auth/me", { cache: "no-store" }); const data = await res.json(); setAuthEnabled(!!data.authEnabled); setLoggedIn(!!data.loggedIn); setUsername(data.username); } catch { setAuthEnabled(false); setLoggedIn(true); } finally { setLoading(false); } }, []); useEffect(() => { refresh(); }, [refresh]); const logout = useCallback(async () => { await fetch("/api/auth/logout", { method: "POST" }); await refresh(); window.location.href = "/"; }, [refresh]); const value = useMemo( () => ({ loading, authEnabled, loggedIn, username, refresh, logout }), [loading, authEnabled, loggedIn, username, refresh, logout], ); return {children}; } export function useAuth() { const ctx = useContext(AuthContext); if (!ctx) { throw new Error("useAuth must be used within AuthProvider"); } return ctx; } export function useRequireAuthForPath(path: string): boolean { const { authEnabled, loggedIn } = useAuth(); if (!authEnabled) { return true; } const protectedPaths = ["/liuyao", "/bazi", "/combined", "/history"]; if (!protectedPaths.some((p) => path === p || path.startsWith(`${p}/`))) { return true; } return loggedIn; }