import React, { createContext, useContext, useState, useEffect } from 'react';
import ApiService from '../services/api';
const AuthContext = createContext();
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
const AuthProvider = ({ children }) => {
/**
* @typedef {object} User - Represents the authenticated user.
* @property {number} id - The user's ID.
* @property {string} username - The user's username.
* @property {boolean} is_superuser - True if the user is a superuser.
* @property {boolean} is_staff - True if the user is a staff member.
* @property {boolean} is_creator - True if the user has creator permissions.
* @property {boolean} is_approver - True if the user has approver permissions.
* @property {boolean} is_responder - True if the user has responder permissions.
* @property {boolean} is_raiser - True if the user has raiser permissions.
* @property {number} hospital_id - The ID of the hospital the user belongs to.
*/
/** @type {[User | null, React.Dispatch<React.SetStateAction<User | null>>]} */
const [user, setUser] = useState(null);
/** @type {[object | null, React.Dispatch<React.SetStateAction<object | null>>]} */
const [hospital, setHospital] = useState(null);
const [loading, setLoading] = useState(true);
const [apiService] = useState(new ApiService());
// Initialize authentication state on component mount
useEffect(() => {
initializeAuth();
}, []);
const initializeAuth = async () => {
try {
const token = localStorage.getItem('authToken');
const storedUser = JSON.parse(localStorage.getItem('user') || 'null');
const storedHospital = JSON.parse(localStorage.getItem('hospital') || 'null');
if (token && storedUser && storedHospital) {
setUser(storedUser);
setHospital(storedHospital);
}
} catch (error) {
console.error('Failed to initialize auth:', error);
logout();
} finally {
setLoading(false);
}
};
/**
* Handles user login.
* @param {string} phoneNumber - The user's phone number.
* @param {string} password - The user's password.
* @param {string} fcmToken - The Firebase Cloud Messaging token for the device.
* @returns {Promise<{success: boolean, error?: string}>} - An object indicating the success of the login and an optional error message.
*/
const login = async (phoneNumber, password,fcmToken) => {
try {
// Login API returns: { token, user: {..., hospital_id: 123}, hospital: {...} }
const response = await apiService.login(phoneNumber, password,fcmToken);
const { token, user: userData, hospital: hospitalData } = response;
// Store auth data
console.log(response);
localStorage.setItem('authToken', token);
localStorage.setItem('user', JSON.stringify(userData));
localStorage.setItem('hospital', JSON.stringify(hospitalData));
setUser(userData);
setHospital(hospitalData);
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
};
/**
* Handles user logout.
*/
const logout = async () => {
await apiService.logout();
localStorage.removeItem('authToken');
localStorage.removeItem('user');
localStorage.removeItem('hospital');
setUser(null);
setHospital(null);
};
/**
* Updates the authenticated user, hospital, and token.
* @param {User | null} newUser - The new user data.
* @param {object | null} newHospital - The new hospital data.
* @param {string | null} newToken - The new authentication token.
*/
const updateAuth = (newUser, newHospital, newToken) => {
setUser(newUser);
setHospital(newHospital);
localStorage.setItem('user', JSON.stringify(newUser));
localStorage.setItem('hospital', JSON.stringify(newHospital));
localStorage.setItem('authToken', newToken);
};
/**
* Sets a new password for the user.
* @param {string} phoneNumber - The user's phone number.
* @param {string} newPassword - The new password.
*/
const setPasswordfunc = async (phoneNumber, newPassword) => {
return await apiService.setPassword(phoneNumber, newPassword);
};
const value = {
user,
hospital,
loading,
login,
logout,
updateAuth,
setPasswordfunc,
/**
* @type {ApiService} - An instance of the ApiService for making API calls.
*/
apiService,
isAuthenticated: !!user,
isSuperuser: user?.is_superuser || user?.is_staff || (user?.is_creator && user?.is_approver && user?.is_responder) || false,
isApprover: user?.is_approver || false,
isResponder: user?.is_responder || false,
isCreator: user?.is_creator || false,
isRaiser: user?.is_raiser || false,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
export { AuthContext, AuthProvider };
Source