import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import { User, AuthTokens, LoginCredentials, RegisterData } from '../types'; import { apiClient } from '../utils/api'; import { API_ENDPOINTS } from '../config/api'; interface AuthContextType { user: User | null; loading: boolean; login: (credentials: LoginCredentials) => Promise; register: (data: RegisterData) => Promise; logout: () => Promise; updateProfile: (data: Partial) => Promise; } const AuthContext = createContext(undefined); export const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }; interface AuthProviderProps { children: ReactNode; } export const AuthProvider: React.FC = ({ children }) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { checkAuth(); }, []); const checkAuth = async () => { try { const token = localStorage.getItem('access_token'); if (token) { const userData = await apiClient.get(API_ENDPOINTS.auth.me); setUser(userData); } } catch (error) { localStorage.removeItem('access_token'); } finally { setLoading(false); } }; const login = async (credentials: LoginCredentials) => { try { const tokens = await apiClient.postForm( API_ENDPOINTS.auth.login, { grant_type: "password", username: credentials.email, password: credentials.password } ); localStorage.setItem('access_token', tokens.access_token); const userData = await apiClient.get(API_ENDPOINTS.auth.me); setUser(userData); } catch (error) { throw new Error('Invalid credentials'); } }; const register = async (data: RegisterData) => { try { await apiClient.post(API_ENDPOINTS.auth.register, data); // Auto-login after registration await login({ email: data.email, password: data.password }); } catch (error) { throw new Error('Registration failed'); } }; const logout = async () => { try { await apiClient.post(API_ENDPOINTS.auth.logout); } catch (error) { // Continue with logout even if API call fails } finally { localStorage.removeItem('access_token'); setUser(null); } }; const updateProfile = async (data: Partial) => { try { const updatedUser = await apiClient.put(API_ENDPOINTS.users.update, data); setUser(updatedUser); } catch (error) { throw new Error('Failed to update profile'); } }; return ( {children} ); };