| import React, { createContext, useContext, useEffect, useState } from 'react'; |
| import { UserProfile } from './types'; |
| import { AuthService } from './services/AuthService'; |
|
|
| interface AuthContextType { |
| user: any | null; |
| profile: UserProfile | null; |
| loading: boolean; |
| login: (id: string, pin: string) => Promise<void>; |
| logout: () => Promise<void>; |
| registerStudent: (data: any) => Promise<UserProfile>; |
| registerTeacher: (data: any) => Promise<UserProfile>; |
| } |
|
|
| const AuthContext = createContext<AuthContextType | undefined>(undefined); |
|
|
| export function AuthProvider({ children }: { children: React.ReactNode }) { |
| const [profile, setProfile] = useState<UserProfile | null>(() => { |
| const saved = localStorage.getItem('local_user_profile'); |
| try { |
| return saved ? JSON.parse(saved) : null; |
| } catch { |
| return null; |
| } |
| }); |
| const [loading, setLoading] = useState(true); |
|
|
| useEffect(() => { |
| async function checkSession() { |
| try { |
| const token = localStorage.getItem('local_user_token'); |
| const headers: Record<string, string> = {}; |
| if (token) { |
| headers['Authorization'] = `Bearer ${token}`; |
| } |
| const response = await fetch('/api/auth/me', { headers }); |
| if (response.ok) { |
| const profileData = await response.json(); |
| setProfile(profileData); |
| localStorage.setItem('local_user_profile', JSON.stringify(profileData)); |
| } else { |
| setProfile(null); |
| localStorage.removeItem('local_user_profile'); |
| localStorage.removeItem('local_user_token'); |
| } |
| } catch (err) { |
| console.warn("Failed to retrieve user session during refresh:", err); |
| } finally { |
| setLoading(false); |
| } |
| } |
| checkSession(); |
| }, []); |
|
|
| const login = async (idOrEmail: string, pinOrPassword: string) => { |
| const isEmail = idOrEmail.includes('@'); |
| const { user: profileData, customToken } = isEmail |
| ? await AuthService.loginWithEmail(idOrEmail, pinOrPassword) |
| : await AuthService.login(idOrEmail, pinOrPassword); |
| setProfile(profileData); |
| localStorage.setItem('local_user_profile', JSON.stringify(profileData)); |
| if (customToken) { |
| localStorage.setItem('local_user_token', customToken); |
| } |
| }; |
|
|
| const logout = async () => { |
| const token = localStorage.getItem('local_user_token'); |
| const headers: Record<string, string> = {}; |
| if (token) { |
| headers['Authorization'] = `Bearer ${token}`; |
| } |
| await fetch('/api/auth/logout', { method: 'POST', headers }).catch(() => {}); |
| setProfile(null); |
| localStorage.removeItem('local_user_profile'); |
| localStorage.removeItem('local_user_token'); |
| }; |
|
|
| const registerStudent = async (data: any) => { |
| const { user: profileData, customToken } = data.email && data.password |
| ? await AuthService.registerStudentWithEmail(data) |
| : await AuthService.registerStudent(data); |
| setProfile(profileData); |
| localStorage.setItem('local_user_profile', JSON.stringify(profileData)); |
| if (customToken) { |
| localStorage.setItem('local_user_token', customToken); |
| } |
| return profileData; |
| }; |
|
|
| const registerTeacher = async (data: any) => { |
| const { user: profileData, customToken } = data.email && data.password |
| ? await AuthService.registerTeacherWithEmail(data) |
| : await AuthService.registerTeacher(data); |
| setProfile(profileData); |
| localStorage.setItem('local_user_profile', JSON.stringify(profileData)); |
| if (customToken) { |
| localStorage.setItem('local_user_token', customToken); |
| } |
| return profileData; |
| }; |
|
|
| return ( |
| <AuthContext.Provider value={{ user: profile, profile, loading, login, logout, registerStudent, registerTeacher }}> |
| {children} |
| </AuthContext.Provider> |
| ); |
| } |
|
|
| export function useAuth() { |
| const context = useContext(AuthContext); |
| if (context === undefined) { |
| throw new Error('useAuth must be used within an AuthProvider'); |
| } |
| return context; |
| } |
|
|