// frontend/src/api/hooks/useAuth.ts /** * Authentication Hooks * React hooks for authentication operations */ import { useState, useEffect, useCallback } from 'react'; import { authService } from '../services'; import type { LoginRequest, LoginResponse, RegisterRequest, UserResponse, PasswordResetRequest, } from '../types'; // Token management const TOKEN_KEY = 'auth_token'; const REFRESH_TOKEN_KEY = 'refresh_token'; const USER_KEY = 'user_data'; export const useAuth = () => { const [user, setUser] = useState(null); const [isAuthenticated, setIsAuthenticated] = useState(false); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // Initialize auth state from localStorage useEffect(() => { const initializeAuth = async () => { try { const token = localStorage.getItem(TOKEN_KEY); const userData = localStorage.getItem(USER_KEY); if (token && userData) { setUser(JSON.parse(userData)); setIsAuthenticated(true); // Verify token is still valid try { const currentUser = await authService.getCurrentUser(); setUser(currentUser); } catch (error) { // Token expired or invalid, clear auth state logout(); } } } catch (error) { console.error('Auth initialization error:', error); logout(); } finally { setIsLoading(false); } }; initializeAuth(); }, []); const login = useCallback(async (credentials: LoginRequest): Promise => { try { setIsLoading(true); setError(null); const response = await authService.login(credentials); // Store tokens and user data localStorage.setItem(TOKEN_KEY, response.access_token); if (response.refresh_token) { localStorage.setItem(REFRESH_TOKEN_KEY, response.refresh_token); } if (response.user) { localStorage.setItem(USER_KEY, JSON.stringify(response.user)); setUser(response.user); } setIsAuthenticated(true); } catch (error) { const message = error instanceof Error ? error.message : 'Login failed'; setError(message); throw error; } finally { setIsLoading(false); } }, []); const register = useCallback(async (data: RegisterRequest): Promise => { try { setIsLoading(true); setError(null); const response = await authService.register(data); // Auto-login after successful registration if (response.user) { await login({ email: data.email, password: data.password }); } } catch (error) { const message = error instanceof Error ? error.message : 'Registration failed'; setError(message); throw error; } finally { setIsLoading(false); } }, [login]); const logout = useCallback(async (): Promise => { try { // Call logout endpoint if authenticated if (isAuthenticated) { await authService.logout(); } } catch (error) { console.error('Logout error:', error); } finally { // Clear local state regardless of API call success localStorage.removeItem(TOKEN_KEY); localStorage.removeItem(REFRESH_TOKEN_KEY); localStorage.removeItem(USER_KEY); setUser(null); setIsAuthenticated(false); setError(null); } }, [isAuthenticated]); const updateProfile = useCallback(async (data: Partial): Promise => { try { setIsLoading(true); setError(null); const updatedUser = await authService.updateProfile(data); setUser(updatedUser); localStorage.setItem(USER_KEY, JSON.stringify(updatedUser)); } catch (error) { const message = error instanceof Error ? error.message : 'Profile update failed'; setError(message); throw error; } finally { setIsLoading(false); } }, []); const requestPasswordReset = useCallback(async (data: PasswordResetRequest): Promise => { try { setIsLoading(true); setError(null); await authService.requestPasswordReset(data); } catch (error) { const message = error instanceof Error ? error.message : 'Password reset request failed'; setError(message); throw error; } finally { setIsLoading(false); } }, []); const changePassword = useCallback(async (currentPassword: string, newPassword: string): Promise => { try { setIsLoading(true); setError(null); await authService.changePassword(currentPassword, newPassword); } catch (error) { const message = error instanceof Error ? error.message : 'Password change failed'; setError(message); throw error; } finally { setIsLoading(false); } }, []); return { user, isAuthenticated, isLoading, error, login, register, logout, updateProfile, requestPasswordReset, changePassword, clearError: () => setError(null), }; }; // Hook for getting authentication headers export const useAuthHeaders = () => { const getAuthHeaders = useCallback(() => { const token = localStorage.getItem(TOKEN_KEY); return token ? { Authorization: `Bearer ${token}` } : {}; }, []); return { getAuthHeaders }; };