import React, { createContext, useState, useContext, useEffect } from 'react'; import axios from 'axios'; // Create context const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Initialize auth state from localStorage on app load useEffect(() => { const initializeAuth = async () => { try { const token = localStorage.getItem('token'); if (token) { // Set default auth header axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; // Validate token and get user data const response = await axios.get('/api/v1/user'); setUser(response.data.data); } } catch (err) { console.error('Error initializing auth:', err); // Clear invalid token localStorage.removeItem('token'); delete axios.defaults.headers.common['Authorization']; } finally { setLoading(false); } }; initializeAuth(); }, []); // Login user const login = async (email, password, rememberMe = false) => { setError(null); try { const response = await axios.post('/api/v1/auth/login', { email, password, remember_me: rememberMe }); // Store token const { access_token, user } = response.data; localStorage.setItem('token', access_token); // Set default auth header for future requests axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`; // Set user state setUser(user); return { success: true }; } catch (err) { console.error('Login error:', err); setError(err.response?.data?.message || 'Login failed. Please try again.'); return { success: false, message: err.response?.data?.message || 'Login failed. Please try again.' }; } }; // Register user const register = async (userData) => { setError(null); try { const response = await axios.post('/api/v1/auth/register', userData); // Store token const { access_token, user } = response.data; localStorage.setItem('token', access_token); // Set default auth header for future requests axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`; // Set user state setUser(user); return { success: true }; } catch (err) { console.error('Registration error:', err); setError(err.response?.data?.message || 'Registration failed. Please try again.'); return { success: false, message: err.response?.data?.message, errors: err.response?.data?.errors }; } }; // Logout user const logout = async () => { try { // Call logout API if (user) { await axios.post('/api/v1/auth/logout'); } } catch (err) { console.error('Logout error:', err); } finally { // Clear token and user data regardless of API success localStorage.removeItem('token'); delete axios.defaults.headers.common['Authorization']; setUser(null); } }; // Request password reset const forgotPassword = async (email) => { setError(null); try { const response = await axios.post('/api/v1/auth/forgot-password', { email }); return { success: true, message: response.data.message }; } catch (err) { console.error('Password reset request error:', err); setError(err.response?.data?.message || 'Failed to send password reset email. Please try again.'); return { success: false, message: err.response?.data?.message, errors: err.response?.data?.errors }; } }; // Reset password with token const resetPassword = async (email, password, password_confirmation, token) => { setError(null); try { const response = await axios.post('/api/v1/auth/reset-password', { email, password, password_confirmation, token }); return { success: true, message: response.data.message }; } catch (err) { console.error('Password reset error:', err); setError(err.response?.data?.message || 'Failed to reset password. Please try again.'); return { success: false, message: err.response?.data?.message, errors: err.response?.data?.errors }; } }; // Update user profile const updateProfile = async (userData) => { setError(null); try { const response = await axios.put('/api/v1/user', userData); setUser(response.data.data); return { success: true, message: 'Profile updated successfully' }; } catch (err) { console.error('Profile update error:', err); setError(err.response?.data?.message || 'Failed to update profile. Please try again.'); return { success: false, message: err.response?.data?.message, errors: err.response?.data?.errors }; } }; // Check if user has a specific role const hasRole = (role) => { if (!user) return false; return user.user_type === role; }; // Check if user is a homeowner const isHomeowner = () => hasRole('homeowner'); // Check if user is a technician const isTechnician = () => hasRole('technician'); // Check if user is an admin const isAdmin = () => hasRole('admin'); // Refresh token const refreshToken = async () => { try { const response = await axios.post('/api/v1/auth/refresh'); const { access_token } = response.data; // Store new token localStorage.setItem('token', access_token); // Update auth header axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`; return true; } catch (err) { console.error('Token refresh error:', err); // If refresh fails, log out user logout(); return false; } }; // Context value const value = { user, loading, error, login, register, logout, forgotPassword, resetPassword, updateProfile, hasRole, isHomeowner, isTechnician, isAdmin, refreshToken }; return {children}; }; // 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; }; export default AuthContext;