91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import React, { createContext, useContext, useState, useEffect } from 'react';
|
|
import { User, UserRole } from '../types';
|
|
import { authApi, clearSession, getSession, saveSession } from '../services/api';
|
|
|
|
interface AuthContextType {
|
|
user: User | null;
|
|
login: (email: string, password: string) => Promise<User | null>;
|
|
register: (name: string, email: string, password: string) => Promise<User | null>;
|
|
logout: () => void;
|
|
isLoading: boolean;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const restoreSession = async () => {
|
|
const session = getSession();
|
|
if (!session) {
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const { user: apiUser } = await authApi.me();
|
|
const restoredUser = toFrontendUser(apiUser);
|
|
saveSession({ ...session, user: apiUser });
|
|
setUser(restoredUser);
|
|
} catch {
|
|
clearSession();
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
void restoreSession();
|
|
}, []);
|
|
|
|
const login = async (email: string, password: string): Promise<User | null> => {
|
|
try {
|
|
const session = await authApi.login(email, password);
|
|
const signedInUser = toFrontendUser(session.user);
|
|
saveSession(session);
|
|
setUser(signedInUser);
|
|
return signedInUser;
|
|
} catch {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const register = async (name: string, email: string, password: string): Promise<User | null> => {
|
|
try {
|
|
const session = await authApi.register(name, email, password);
|
|
const signedInUser = toFrontendUser(session.user);
|
|
saveSession(session);
|
|
setUser(signedInUser);
|
|
return signedInUser;
|
|
} catch {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const logout = () => {
|
|
setUser(null);
|
|
clearSession();
|
|
};
|
|
|
|
return (
|
|
<AuthContext.Provider value={{ user, login, register, logout, isLoading }}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
};
|
|
|
|
const toFrontendUser = (user: { id: string; email: string; name: string; role: string }): User => ({
|
|
id: user.id,
|
|
email: user.email,
|
|
name: user.name,
|
|
role: user.role === 'admin' ? 'superadmin' : user.role === 'instructor' ? 'professor' : 'student',
|
|
});
|
|
|
|
export const useAuth = () => {
|
|
const context = useContext(AuthContext);
|
|
if (context === undefined) {
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
}
|
|
return context;
|
|
};
|