import React, { createContext, useContext, useReducer, useEffect, ReactNode } from 'react'; import { authAPI } from '../services/api'; import { User } from '../types'; interface AuthState { user: User | null; token: string | null; isLoading: boolean; isAuthenticated: boolean; } interface AuthContextType extends AuthState { login: (login: string, password: string) => Promise; register: (userData: RegisterData) => Promise; logout: () => void; updateProfile: (userData: Partial) => Promise; changePassword: (currentPassword: string, newPassword: string) => Promise; handleGoogleCallback: (token: string) => Promise; } interface RegisterData { firstName: string; lastName: string; email: string; password: string; confirmPassword: string; } type AuthAction = | { type: 'SET_LOADING'; payload: boolean } | { type: 'SET_USER'; payload: { user: User; token: string } } | { type: 'CLEAR_USER' } | { type: 'UPDATE_USER'; payload: Partial }; const initialState: AuthState = { user: null, token: localStorage.getItem('token'), isLoading: true, isAuthenticated: false, }; const authReducer = (state: AuthState, action: AuthAction): AuthState => { switch (action.type) { case 'SET_LOADING': return { ...state, isLoading: action.payload }; case 'SET_USER': return { ...state, user: action.payload.user, token: action.payload.token, isAuthenticated: true, isLoading: false, }; case 'CLEAR_USER': return { ...state, user: null, token: null, isAuthenticated: false, isLoading: false, }; case 'UPDATE_USER': return { ...state, user: state.user ? { ...state.user, ...action.payload } : null, }; default: return state; } }; const AuthContext = createContext(undefined); export const useAuth = () => { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }; interface AuthProviderProps { children: ReactNode; } export const AuthProvider: React.FC = ({ children }) => { const [state, dispatch] = useReducer(authReducer, initialState); // Backend'ten gelen kullanıcı nesnesini frontend User tipine dönüştür const normalizeUser = (apiUser: any): User => { return { id: apiUser.id, firstName: apiUser.firstName, lastName: apiUser.lastName, email: apiUser.email, role: apiUser.isAdmin ? 'ADMIN' : 'USER', isActive: apiUser.isActive ?? true, avatar: apiUser.avatar ?? undefined, createdAt: apiUser.createdAt, updatedAt: apiUser.updatedAt ?? apiUser.createdAt, settings: apiUser.settings ?? undefined, }; }; // Check if user is authenticated on app load useEffect(() => { const checkAuth = async () => { const token = localStorage.getItem('token'); if (token) { try { const response = await authAPI.getProfile(); dispatch({ type: 'SET_USER', payload: { user: normalizeUser(response.data.data.user), token }, }); } catch (error) { localStorage.removeItem('token'); dispatch({ type: 'CLEAR_USER' }); } } else { dispatch({ type: 'SET_LOADING', payload: false }); } }; checkAuth(); }, []); const login = async (login: string, password: string) => { dispatch({ type: 'SET_LOADING', payload: true }); try { const response = await authAPI.login({ login, password }); const { user, token } = response.data.data; localStorage.setItem('token', token); dispatch({ type: 'SET_USER', payload: { user: normalizeUser(user), token } }); } catch (error) { dispatch({ type: 'SET_LOADING', payload: false }); throw error; } }; const register = async (userData: RegisterData) => { dispatch({ type: 'SET_LOADING', payload: true }); try { const response = await authAPI.register(userData); const { user, token } = response.data.data; localStorage.setItem('token', token); dispatch({ type: 'SET_USER', payload: { user: normalizeUser(user), token } }); } catch (error) { dispatch({ type: 'SET_LOADING', payload: false }); throw error; } }; const logout = () => { localStorage.removeItem('token'); dispatch({ type: 'CLEAR_USER' }); }; const updateProfile = async (userData: Partial) => { try { const response = await authAPI.updateProfile(userData); dispatch({ type: 'UPDATE_USER', payload: normalizeUser(response.data.data.user) }); } catch (error) { throw error; } }; const changePassword = async (currentPassword: string, newPassword: string) => { try { await authAPI.changePassword({ currentPassword, newPassword }); } catch (error) { throw error; } }; const handleGoogleCallback = async (token: string) => { dispatch({ type: 'SET_LOADING', payload: true }); try { localStorage.setItem('token', token); const response = await authAPI.getProfile(); dispatch({ type: 'SET_USER', payload: { user: normalizeUser(response.data.data.user), token }, }); } catch (error) { localStorage.removeItem('token'); dispatch({ type: 'SET_LOADING', payload: false }); throw error; } }; const value: AuthContextType = { ...state, login, register, logout, updateProfile, changePassword, handleGoogleCallback, }; return {children}; };