mcq-test / frontend /src /App.jsx
trung.le
feat: introduce initial frontend application with user dashboard, admin, and login pages.
1fe7da5
Raw
History Blame Contribute Delete
4.11 kB
import { useState, useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, NavLink, Navigate } from 'react-router-dom';
import { ThemeProvider } from './context/ThemeContext';
import Login from './pages/Login';
import AdminDashboard from './pages/AdminDashboard';
import UserDashboard from './pages/UserDashboard';
import ThemeSettings from './components/ThemeSettings';
import api from './api';
import { LogOut, Home, Shield, BookOpen } from 'lucide-react';
function AppContent() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchUser = async () => {
const token = localStorage.getItem('token');
if (token) {
try {
const res = await api.get('/auth/me');
setUser(res.data);
} catch (err) {
localStorage.removeItem('token');
}
}
setLoading(false);
};
fetchUser();
}, []);
const logout = () => {
localStorage.removeItem('token');
setUser(null);
};
if (loading) {
return (
<div className="loading-container">
<div className="loading-spinner"></div>
</div>
);
}
return (
<Router>
<header className="app-header glass-container">
{/* Brand */}
<div className="header-brand">
<div className="header-logo">
<BookOpen size={22} />
</div>
<span className="header-title">MCQ Portal</span>
</div>
{/* Navigation */}
{user && (
<nav className="header-nav">
<NavLink
to="/"
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
>
<Home size={18} />
<span>Dashboard</span>
</NavLink>
{user?.is_admin && (
<NavLink
to="/admin"
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
>
<Shield size={18} />
<span>Admin</span>
</NavLink>
)}
</nav>
)}
{/* Actions */}
<div className="header-actions">
<ThemeSettings />
{user ? (
<div className="user-info">
<div className="user-avatar">
{user.username.charAt(0).toUpperCase()}
</div>
<span className="user-name">{user.username}</span>
<button onClick={logout} className="danger" title="Logout">
<LogOut size={18} />
</button>
</div>
) : (
<NavLink to="/login" className="nav-link">
Login
</NavLink>
)}
</div>
</header>
<main className="main-content">
<Routes>
<Route path="/" element={user ? <UserDashboard /> : <Navigate to="/login" />} />
<Route path="/login" element={!user ? <Login setUser={setUser} /> : <Navigate to="/" />} />
<Route path="/admin" element={user?.is_admin ? <AdminDashboard /> : <Navigate to="/" />} />
</Routes>
</main>
</Router>
);
}
export default function App() {
return (
<ThemeProvider>
<AppContent />
</ThemeProvider>
);
}