Files
drb-frontend/src/context/AuthContext.tsx
2025-05-25 23:20:48 -04:00

89 lines
2.9 KiB
TypeScript

"use client";
import React, { useState, useEffect, createContext, useContext, ReactNode } from 'react';
import { API_BASE_URL } from '@/constants/api';
import { UserDetails, UserRoles, ErrorResponse, AuthContextType } from '@/types'; // Import types
export const AuthContext = createContext<AuthContextType | null>(null);
interface AuthProviderProps {
children: ReactNode;
}
export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
const [token, setToken] = useState<string | null>(null);
const [user, setUser] = useState<UserDetails | null>(null);
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
const storedToken = localStorage.getItem('jwt_token');
const storedUser = localStorage.getItem('user_data');
if (storedToken && storedUser) {
setToken(storedToken);
try {
setUser(JSON.parse(storedUser));
} catch (error) {
console.error("Failed to parse stored user data:", error);
localStorage.removeItem('user_data');
}
}
setLoading(false);
}, []);
const login = async (username: string, password: string): Promise<boolean> => {
try {
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
const data = await response.json();
if (response.ok) {
setToken(data.access_token);
const tempUser: UserDetails = { id: data.user_id || 'some-id', username: data.username, role: data.role || UserRoles.USER };
setUser(tempUser);
localStorage.setItem('jwt_token', data.access_token);
localStorage.setItem('user_data', JSON.stringify(tempUser));
return true;
} else {
const errorData = data as ErrorResponse;
console.error('Login failed:', errorData.message || errorData.detail || response.statusText);
return false;
}
} catch (error) {
console.error('Network error during login:', error);
return false;
}
};
const logout = () => {
setToken(null);
setUser(null);
localStorage.removeItem('jwt_token');
localStorage.removeItem('user_data');
};
const hasPermission = (requiredRole: UserRoles): boolean => {
if (!user || !user.role) return false;
const roleOrder: Record<UserRoles, number> = {
[UserRoles.USER]: 0,
[UserRoles.MOD]: 1,
[UserRoles.ADMIN]: 2
};
return roleOrder[user.role] >= roleOrder[requiredRole];
};
return (
<AuthContext.Provider value={{ token, user, loading, login, logout, hasPermission }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = (): AuthContextType => {
const context = useContext(AuthContext);
if (context === null) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};