TransHub / client /src /contexts /AuthContext.tsx
linguabot's picture
Upload folder using huggingface_hub
4f163ba verified
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { api } from '../services/api';
interface User {
id: string;
username: string;
email: string;
role: 'student' | 'instructor' | 'admin' | 'visitor';
targetCultures: string[];
nativeLanguage?: string;
}
interface AuthContextType {
user: User | null;
loading: boolean;
login: (email: string, password: string) => Promise<void>;
register: (userData: RegisterData) => Promise<void>;
logout: () => void;
updateProfile: (data: Partial<User>) => Promise<void>;
}
interface RegisterData {
username: string;
email: string;
password: string;
role?: 'student' | 'instructor' | 'admin';
targetCultures?: string[];
nativeLanguage?: string;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
interface AuthProviderProps {
children: ReactNode;
}
export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Check for stored token on app load
const token = localStorage.getItem('token');
if (token) {
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
fetchUser();
} else {
// Auto-setup visitor authentication
setupVisitorAuth();
}
}, []);
const setupVisitorAuth = async () => {
try {
const response = await api.post('/api/auth/login', {
email: 'visitor@example.com'
});
const { token, user } = response.data;
localStorage.setItem('token', token);
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
setUser(user);
} catch (error) {
console.error('Failed to setup visitor auth:', error);
// Set a fallback visitor token
const fallbackToken = `visitor_${Date.now()}`;
localStorage.setItem('token', fallbackToken);
api.defaults.headers.common['Authorization'] = `Bearer ${fallbackToken}`;
setUser({
id: 'visitor',
username: 'Visitor',
email: 'visitor@example.com',
role: 'visitor',
targetCultures: []
});
} finally {
setLoading(false);
}
};
const fetchUser = async () => {
try {
const response = await api.get('/api/auth/profile');
setUser(response.data);
} catch (error) {
console.error('Failed to fetch user:', error);
localStorage.removeItem('token');
delete api.defaults.headers.common['Authorization'];
// Try to setup visitor auth as fallback
setupVisitorAuth();
return;
} finally {
setLoading(false);
}
};
const login = async (email: string, password: string) => {
try {
const response = await api.post('/api/auth/login', { email });
const { token, user } = response.data;
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
setUser(user);
} catch (error: any) {
console.error('Login error:', error);
throw new Error(error.response?.data?.error || 'Login failed');
}
};
const register = async (userData: RegisterData) => {
try {
const response = await api.post('/api/auth/register', userData);
const { token, user } = response.data;
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
setUser(user);
} catch (error: any) {
throw new Error(error.response?.data?.error || 'Registration failed');
}
};
const logout = () => {
localStorage.removeItem('token');
delete api.defaults.headers.common['Authorization'];
setUser(null);
// Setup visitor auth after logout
setupVisitorAuth();
};
const updateProfile = async (data: Partial<User>) => {
try {
const response = await api.put('/api/auth/profile', data);
setUser(response.data);
} catch (error: any) {
throw new Error(error.response?.data?.error || 'Profile update failed');
}
};
return (
<AuthContext.Provider value={{
user,
loading,
login,
register,
logout,
updateProfile
}}>
{children}
</AuthContext.Provider>
);
};