/** * Authentication Context * Manages user authentication state globally */ "use client" import React, { createContext, useContext, useState, useEffect, ReactNode } from "react" import { authApi, getAuthToken, setAuthToken, clearAuthToken, VoterProfile } from "./api" interface AuthContextType { user: VoterProfile | null isLoading: boolean isAuthenticated: boolean error: string | null login: (email: string, password: string) => Promise register: (email: string, password: string, firstName: string, lastName: string, citizenId: string) => Promise logout: () => void refreshProfile: () => Promise } const AuthContext = createContext(undefined) export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null) const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) // Check if user is already logged in on mount useEffect(() => { const checkAuth = async () => { const token = getAuthToken() if (token) { try { const response = await authApi.getProfile() if (response.data) { setUser(response.data) } else { clearAuthToken() } } catch (err) { clearAuthToken() } } setIsLoading(false) } checkAuth() }, []) const login = async (email: string, password: string) => { setIsLoading(true) setError(null) try { const response = await authApi.login(email, password) if (response.error) { throw new Error(response.error) } if (response.data) { setAuthToken(response.data.access_token) setUser({ id: response.data.id, email: response.data.email, first_name: response.data.first_name, last_name: response.data.last_name, has_voted: false, created_at: new Date().toISOString(), }) } } catch (err) { const message = err instanceof Error ? err.message : "Login failed" setError(message) throw err } finally { setIsLoading(false) } } const register = async (email: string, password: string, firstName: string, lastName: string, citizenId: string) => { setIsLoading(true) setError(null) try { const response = await authApi.register(email, password, firstName, lastName, citizenId) if (response.error) { throw new Error(response.error) } if (response.data) { setAuthToken(response.data.access_token) setUser({ id: response.data.id, email: response.data.email, first_name: response.data.first_name, last_name: response.data.last_name, has_voted: false, created_at: new Date().toISOString(), }) } } catch (err) { const message = err instanceof Error ? err.message : "Registration failed" setError(message) throw err } finally { setIsLoading(false) } } const logout = () => { authApi.logout() setUser(null) setError(null) } const refreshProfile = async () => { try { const response = await authApi.getProfile() if (response.data) { setUser(response.data) } else { clearAuthToken() setUser(null) } } catch (err) { clearAuthToken() setUser(null) } } const value: AuthContextType = { user, isLoading, isAuthenticated: user !== null, error, login, register, logout, refreshProfile, } return {children} } /** * Hook to use authentication context */ export function useAuth() { const context = useContext(AuthContext) if (context === undefined) { throw new Error("useAuth must be used within an AuthProvider") } return context }