hku-class/frontend/src/hooks/use-auth.tsx
2026-04-20 21:18:05 +08:00

91 lines
2.4 KiB
TypeScript

"use client";
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
type ReactNode,
} from "react";
import { type AuthUser } from "@/lib/types";
import { postAPI, fetchAPI } from "@/lib/api";
import type { LoginResponse } from "@/lib/types";
interface AuthContextValue {
user: AuthUser | null;
loading: boolean;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
refreshUser: () => Promise<void>;
}
const AuthContext = createContext<AuthContextValue>({
user: null,
loading: true,
login: async () => {},
logout: () => {},
refreshUser: async () => {},
});
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<AuthUser | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem("auth_token");
const storedUser = localStorage.getItem("auth_user");
if (token && storedUser) {
try {
setUser(JSON.parse(storedUser));
} catch {
localStorage.removeItem("auth_token");
localStorage.removeItem("auth_user");
}
}
setLoading(false);
}, []);
const login = useCallback(async (email: string, password: string) => {
const res = await postAPI<LoginResponse>("/api/auth/login", {
email,
password,
});
localStorage.setItem("auth_token", res.token);
// Temporarily set user from login response, then refresh to get full data (enabled_modules etc.)
setUser(res.user);
localStorage.setItem("auth_user", JSON.stringify(res.user));
// Refresh to get complete user data including enabled_modules
const userData = await fetchAPI<AuthUser>("/api/auth/me");
localStorage.setItem("auth_user", JSON.stringify(userData));
setUser(userData);
}, []);
const logout = useCallback(() => {
localStorage.removeItem("auth_token");
localStorage.removeItem("auth_user");
setUser(null);
window.location.href = "/login";
}, []);
const refreshUser = useCallback(async () => {
try {
const userData = await fetchAPI<AuthUser>("/api/auth/me");
localStorage.setItem("auth_user", JSON.stringify(userData));
setUser(userData);
} catch {
// Token might be invalid
}
}, []);
return (
<AuthContext.Provider value={{ user, loading, login, logout, refreshUser }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
return useContext(AuthContext);
}