Initial Claude Run

This commit is contained in:
Jake Kasper
2025-08-21 07:06:36 -05:00
parent 5ead64afcd
commit 2a46f7261e
53 changed files with 7633 additions and 2 deletions

View File

@@ -0,0 +1,232 @@
import React, { createContext, useContext, useReducer, useEffect } from 'react';
import { authAPI } from '../services/api';
import toast from 'react-hot-toast';
// Initial state
const initialState = {
user: null,
token: localStorage.getItem('authToken'),
loading: true,
error: null,
};
// Action types
const actionTypes = {
SET_LOADING: 'SET_LOADING',
LOGIN_SUCCESS: 'LOGIN_SUCCESS',
LOGOUT: 'LOGOUT',
SET_ERROR: 'SET_ERROR',
CLEAR_ERROR: 'CLEAR_ERROR',
UPDATE_USER: 'UPDATE_USER',
};
// Reducer
const authReducer = (state, action) => {
switch (action.type) {
case actionTypes.SET_LOADING:
return {
...state,
loading: action.payload,
error: null,
};
case actionTypes.LOGIN_SUCCESS:
localStorage.setItem('authToken', action.payload.token);
return {
...state,
user: action.payload.user,
token: action.payload.token,
loading: false,
error: null,
};
case actionTypes.LOGOUT:
localStorage.removeItem('authToken');
return {
...state,
user: null,
token: null,
loading: false,
error: null,
};
case actionTypes.SET_ERROR:
return {
...state,
error: action.payload,
loading: false,
};
case actionTypes.CLEAR_ERROR:
return {
...state,
error: null,
};
case actionTypes.UPDATE_USER:
return {
...state,
user: { ...state.user, ...action.payload },
};
default:
return state;
}
};
// Create context
const AuthContext = createContext();
// Custom hook to use auth context
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
// Auth provider component
export const AuthProvider = ({ children }) => {
const [state, dispatch] = useReducer(authReducer, initialState);
// Check if user is authenticated on app load
useEffect(() => {
const checkAuth = async () => {
const token = localStorage.getItem('authToken');
if (!token) {
dispatch({ type: actionTypes.SET_LOADING, payload: false });
return;
}
try {
const response = await authAPI.getCurrentUser();
dispatch({
type: actionTypes.LOGIN_SUCCESS,
payload: {
user: response.data.user,
token,
},
});
} catch (error) {
console.error('Auth check failed:', error);
localStorage.removeItem('authToken');
dispatch({ type: actionTypes.LOGOUT });
}
};
checkAuth();
}, []);
// Login function
const login = async (credentials) => {
try {
dispatch({ type: actionTypes.SET_LOADING, payload: true });
dispatch({ type: actionTypes.CLEAR_ERROR });
const response = await authAPI.login(credentials);
dispatch({
type: actionTypes.LOGIN_SUCCESS,
payload: response.data,
});
toast.success('Welcome back!');
return { success: true };
} catch (error) {
const errorMessage = error.response?.data?.message || 'Login failed. Please try again.';
dispatch({ type: actionTypes.SET_ERROR, payload: errorMessage });
toast.error(errorMessage);
return { success: false, error: errorMessage };
}
};
// Register function
const register = async (userData) => {
try {
dispatch({ type: actionTypes.SET_LOADING, payload: true });
dispatch({ type: actionTypes.CLEAR_ERROR });
const response = await authAPI.register(userData);
dispatch({
type: actionTypes.LOGIN_SUCCESS,
payload: response.data,
});
toast.success('Account created successfully!');
return { success: true };
} catch (error) {
const errorMessage = error.response?.data?.message || 'Registration failed. Please try again.';
dispatch({ type: actionTypes.SET_ERROR, payload: errorMessage });
toast.error(errorMessage);
return { success: false, error: errorMessage };
}
};
// Logout function
const logout = () => {
dispatch({ type: actionTypes.LOGOUT });
toast.success('Logged out successfully');
};
// Update user profile
const updateUser = (userData) => {
dispatch({ type: actionTypes.UPDATE_USER, payload: userData });
};
// Change password
const changePassword = async (passwordData) => {
try {
await authAPI.changePassword(passwordData);
toast.success('Password changed successfully');
return { success: true };
} catch (error) {
const errorMessage = error.response?.data?.message || 'Failed to change password';
toast.error(errorMessage);
return { success: false, error: errorMessage };
}
};
// Forgot password
const forgotPassword = async (email) => {
try {
await authAPI.forgotPassword(email);
toast.success('Password reset instructions sent to your email');
return { success: true };
} catch (error) {
const errorMessage = error.response?.data?.message || 'Failed to send reset email';
toast.error(errorMessage);
return { success: false, error: errorMessage };
}
};
// Clear error
const clearError = () => {
dispatch({ type: actionTypes.CLEAR_ERROR });
};
// Context value
const value = {
user: state.user,
token: state.token,
loading: state.loading,
error: state.error,
isAuthenticated: !!state.user,
isAdmin: state.user?.role === 'admin',
login,
register,
logout,
updateUser,
changePassword,
forgotPassword,
clearError,
};
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
);
};