372183cd96
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
30 lines
769 B
TypeScript
30 lines
769 B
TypeScript
import client from "./client";
|
|
import type { User } from "../types/models";
|
|
|
|
interface TokenResponse {
|
|
access_token: string;
|
|
token_type: string;
|
|
}
|
|
|
|
/** Authenticate and return the access token. */
|
|
export async function login(
|
|
username: string,
|
|
password: string,
|
|
): Promise<string> {
|
|
const params = new URLSearchParams();
|
|
params.append("username", username);
|
|
params.append("password", password);
|
|
|
|
const { data } = await client.post<TokenResponse>("/auth/login", params, {
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
});
|
|
|
|
return data.access_token;
|
|
}
|
|
|
|
/** Fetch the currently authenticated user profile. */
|
|
export async function getMe(): Promise<User> {
|
|
const { data } = await client.get<User>("/auth/me");
|
|
return data;
|
|
}
|