feat: Phase 7 - Frontend scaffolding and auth (T-023, T-024, T-025)

T-023: Initialize React project
- Vite + React 19 + TypeScript scaffold
- Tailwind CSS v4 with @tailwindcss/vite plugin
- Dependencies: react-router-dom, axios, @tanstack/react-query, lucide-react
- Project structure: api/, components/, pages/, context/, types/, hooks/, lib/

T-024: API client and auth context
- Axios client with JWT interceptor (auto-attach token, clear on 401)
- login() and getMe() API functions
- AuthContext: user state, login, logout, isAuthenticated, isLoading
- Token persistence via localStorage with hydration on mount
- TypeScript types for all backend models

T-025: Login page and layout
- LoginPage with form, error handling, redirect on success
- Layout with sidebar + header + Outlet
- Sidebar with role-aware navigation (System only for admin)
- ProtectedRoute wrapper with role-based access control
- Routes: /login, /dashboard, /techniques, /tests, /system
This commit is contained in:
2026-02-06 16:09:50 +01:00
parent 52d230628d
commit 591b5df250
26 changed files with 3489 additions and 4 deletions

View File

@@ -0,0 +1,33 @@
import { Outlet } from "react-router-dom";
import { LogOut } from "lucide-react";
import { useAuth } from "../context/AuthContext";
import Sidebar from "./Sidebar";
export default function Layout() {
const { user, logout } = useAuth();
return (
<div className="flex h-screen bg-gray-950 text-gray-100">
<Sidebar />
<div className="flex flex-1 flex-col overflow-hidden">
{/* Header */}
<header className="flex h-16 items-center justify-end gap-4 border-b border-gray-800 bg-gray-900 px-6">
<span className="text-sm text-gray-300">{user?.username}</span>
<button
onClick={logout}
className="flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-gray-400 transition-colors hover:bg-gray-800 hover:text-white"
>
<LogOut className="h-4 w-4" />
Logout
</button>
</header>
{/* Main content */}
<main className="flex-1 overflow-y-auto p-6">
<Outlet />
</main>
</div>
</div>
);
}