"use client"; import { useRouter } from "next/navigation"; import * as React from "react"; import { toast } from "sonner"; import { AuthService } from "@/services/auth.service"; import { UserService } from "@/services/user.service"; import type { LoginResponse, RegisterPayload } from "@/types/auth"; import type { User } from "@/types/user"; interface AuthContextType { user: User | null; isLoading: boolean; isAuthenticated: boolean; login: (email: string, password: string) => Promise; verify2fa: (userId: string, token: string) => Promise; register: (payload: RegisterPayload) => Promise; logout: () => Promise; refreshUser: () => Promise; } const AuthContext = React.createContext(null); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = React.useState(null); const [isLoading, setIsLoading] = React.useState(true); const router = useRouter(); const refreshUser = React.useCallback(async () => { // Éviter de lancer plusieurs refresh en même temps if (!isLoading) setIsLoading(true); try { const userData = await UserService.getMe(); setUser(userData); } catch (_error) { setUser(null); } finally { setIsLoading(false); } }, [isLoading]); React.useEffect(() => { let isMounted = true; const initAuth = async () => { try { const userData = await UserService.getMe(); if (isMounted) setUser(userData); } catch (_error) { if (isMounted) setUser(null); } finally { if (isMounted) setIsLoading(false); } }; initAuth(); return () => { isMounted = false; }; }, []); const login = async (email: string, password: string) => { try { const response = await AuthService.login(email, password); if (response.userId && response.message === "Please provide 2FA token") { return response; } await refreshUser(); toast.success("Connexion réussie !"); router.push("/"); return response; } catch (error: unknown) { let errorMessage = "Erreur de connexion"; if ( error && typeof error === "object" && "response" in error && error.response && typeof error.response === "object" && "data" in error.response && error.response.data && typeof error.response.data === "object" && "message" in error.response.data && typeof error.response.data.message === "string" ) { errorMessage = error.response.data.message; } toast.error(errorMessage); throw error; } }; const verify2fa = async (userId: string, token: string) => { try { await AuthService.verify2fa(userId, token); await refreshUser(); toast.success("Connexion réussie !"); router.push("/"); } catch (error: unknown) { let errorMessage = "Code 2FA invalide"; if ( error && typeof error === "object" && "response" in error && error.response && typeof error.response === "object" && "data" in error.response && error.response.data && typeof error.response.data === "object" && "message" in error.response.data && typeof error.response.data.message === "string" ) { errorMessage = error.response.data.message; } toast.error(errorMessage); throw error; } }; const register = async (payload: RegisterPayload) => { try { await AuthService.register(payload); toast.success( "Inscription réussie ! Vous pouvez maintenant vous connecter.", ); router.push("/login"); } catch (error: unknown) { let errorMessage = "Erreur d'inscription"; if ( error && typeof error === "object" && "response" in error && error.response && typeof error.response === "object" && "data" in error.response && error.response.data && typeof error.response.data === "object" && "message" in error.response.data && typeof error.response.data.message === "string" ) { errorMessage = error.response.data.message; } toast.error(errorMessage); throw error; } }; const logout = async () => { try { await AuthService.logout(); setUser(null); toast.success("Déconnexion réussie"); router.push("/"); } catch (_error) { toast.error("Erreur lors de la déconnexion"); } }; return ( {children} ); } export const useAuth = () => { const context = React.useContext(AuthContext); if (!context) { throw new Error("useAuth must be used within an AuthProvider"); } return context; };