hMarket Trae ilk versiyon

This commit is contained in:
hOLOlu
2026-02-03 01:22:08 +03:00
commit 2b861156fe
74 changed files with 42127 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
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<void>;
register: (userData: RegisterData) => Promise<void>;
logout: () => void;
updateProfile: (userData: Partial<User>) => Promise<void>;
changePassword: (currentPassword: string, newPassword: string) => Promise<void>;
handleGoogleCallback: (token: string) => Promise<void>;
}
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<User> };
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<AuthContextType | undefined>(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<AuthProviderProps> = ({ 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<User>) => {
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 <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};