/** * Authentication Context for Redirect Intelligence v2 * * Manages user authentication state and API interactions */ import { createContext, useContext, useEffect, useState, ReactNode } from 'react'; import { useToast } from '@chakra-ui/react'; import { authApi, AuthUser, LoginRequest, RegisterRequest } from '../services/api'; interface AuthContextType { user: AuthUser | null; isLoading: boolean; isAuthenticated: boolean; login: (credentials: LoginRequest) => Promise; register: (userData: RegisterRequest) => Promise; logout: () => void; refreshUser: () => Promise; } const AuthContext = createContext(undefined); interface AuthProviderProps { children: ReactNode; } export function AuthProvider({ children }: AuthProviderProps) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const toast = useToast(); const isAuthenticated = !!user; // Check for existing session on mount useEffect(() => { checkExistingSession(); }, []); const checkExistingSession = async () => { try { // Check if auth endpoints are available first const userData = await authApi.getCurrentUser(); setUser(userData); } catch (error: any) { // No existing session, session expired, or auth endpoints not available console.log('Authentication not available or no existing session:', error.message); setUser(null); } finally { setIsLoading(false); } }; const login = async (credentials: LoginRequest) => { try { setIsLoading(true); const response = await authApi.login(credentials); setUser(response.user); toast({ title: 'Login successful', description: `Welcome back, ${response.user.name}!`, status: 'success', duration: 3000, isClosable: true, }); } catch (error: any) { const message = error.response?.data?.message || 'Login failed'; toast({ title: 'Login failed', description: message, status: 'error', duration: 5000, isClosable: true, }); throw error; } finally { setIsLoading(false); } }; const register = async (userData: RegisterRequest) => { try { setIsLoading(true); const response = await authApi.register(userData); toast({ title: 'Registration successful', description: `Welcome, ${response.user.name}! Please log in to continue.`, status: 'success', duration: 5000, isClosable: true, }); } catch (error: any) { const message = error.response?.data?.message || 'Registration failed'; toast({ title: 'Registration failed', description: message, status: 'error', duration: 5000, isClosable: true, }); throw error; } finally { setIsLoading(false); } }; const logout = () => { authApi.logout(); setUser(null); toast({ title: 'Logged out', description: 'You have been successfully logged out.', status: 'info', duration: 3000, isClosable: true, }); }; const refreshUser = async () => { try { const userData = await authApi.getCurrentUser(); setUser(userData); } catch (error) { // Session expired or invalid setUser(null); } }; const value: AuthContextType = { user, isLoading, isAuthenticated, login, register, logout, refreshUser, }; return ( {children} ); } export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }