"use client"; import { createContext, useCallback, useEffect, useMemo, useState, } from "react"; import { api, setAccessToken } from "@/utils/api"; import { AUTH_ENDPOINTS } from "@/utils/api-endpoints"; export interface AuthUser { id: string; name: string; email: string; role: string; created_at: string; } interface AuthContextValue { user: AuthUser | null; isLoading: boolean; isAdmin: boolean; login: (email: string, password: string) => Promise; register: (name: string, email: string, password: string) => Promise; logout: () => Promise; refreshUser: () => Promise; } export const AuthContext = createContext({ user: null, isLoading: true, isAdmin: false, login: async () => {}, register: async () => {}, logout: async () => {}, refreshUser: async () => {}, }); async function storeRefreshToken(refreshToken: string) { await fetch("/api/auth/refresh", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ refresh_token: refreshToken }), }); } async function clearRefreshToken() { await fetch("/api/auth/refresh", { method: "DELETE" }); } async function refreshSession(): Promise { const res = await fetch("/api/auth/refresh", { method: "POST", credentials: "include", }); if (!res.ok) return false; const data = await res.json(); setAccessToken(data.access_token); return true; } export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const loadUser = useCallback(async () => { const res = await api.get(AUTH_ENDPOINTS.ME); setUser(res.data); }, []); useEffect(() => { let active = true; (async () => { try { const ok = await refreshSession(); if (ok && active) await loadUser(); } catch { if (active) setUser(null); } finally { if (active) setIsLoading(false); } })(); return () => { active = false; }; }, [loadUser]); const login = useCallback( async (email: string, password: string) => { const res = await api.post(AUTH_ENDPOINTS.LOGIN, { email, password }); setAccessToken(res.data.access_token); await storeRefreshToken(res.data.refresh_token); await loadUser(); }, [loadUser], ); const register = useCallback( async (name: string, email: string, password: string) => { const res = await api.post(AUTH_ENDPOINTS.REGISTER, { name, email, password, }); setAccessToken(res.data.access_token); await storeRefreshToken(res.data.refresh_token); await loadUser(); }, [loadUser], ); const logout = useCallback(async () => { await clearRefreshToken(); setAccessToken(null); setUser(null); if (typeof window !== "undefined") window.location.href = "/login"; }, []); const value = useMemo( () => ({ user, isLoading, isAdmin: user?.role === "admin", login, register, logout, refreshUser: loadUser, }), [user, isLoading, login, register, logout, loadUser], ); return {children}; }