feat(dashboard): GuruConnect v2 operator console (pass 1)
All checks were successful
All checks were successful
React + Vite + TypeScript SPA: scaffold, operations-terminal design system, Bearer-token auth, and the Machines view. - Design system: OKLCH-tinted dark theme (ink-slate + signal-cyan), Hanken Grotesk + JetBrains Mono, status-color language (online/offline/granted/pending/denied/not_required), motion with prefers-reduced-motion honored. - Auth: token in sessionStorage via ref (never React state), protected routes, 401 session teardown, admin-gated per-agent-key UI. - Machines view: data table (sticky header, keyboard-activated rows, skeleton loading, actionable empty/error states), non-blocking detail drawer, delete confirm, admin key management with copy-once reveal. - UI primitives: Modal (focus trap + inert + portal + dialogStack), Drawer, Table, Badge/StatusDot, toast, states. - Typed API client normalizing the two error-envelope shapes. Passed Code Review (no blockers), impeccable critique-and-polish, and local gates (tsc/lint/build green). Dev-only Vite proxy to :3002. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
41
dashboard/src/App.tsx
Normal file
41
dashboard/src/App.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Navigate, Route, BrowserRouter, Routes } from "react-router-dom";
|
||||
import { AuthProvider } from "./auth/AuthProvider";
|
||||
import { ProtectedRoute } from "./auth/ProtectedRoute";
|
||||
import { AppShell } from "./components/layout/AppShell";
|
||||
import { ToastProvider } from "./components/ui/toast";
|
||||
import { LoginPage } from "./features/auth/LoginPage";
|
||||
import { MachinesPage } from "./features/machines/MachinesPage";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<ToastProvider>
|
||||
<AuthProvider>
|
||||
<Routes>
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route element={<ProtectedRoute />}>
|
||||
<Route element={<AppShell />}>
|
||||
<Route path="/machines" element={<MachinesPage />} />
|
||||
{/* Sessions / Codes / Users land in later passes. */}
|
||||
<Route path="/" element={<Navigate to="/machines" replace />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/machines" replace />} />
|
||||
</Routes>
|
||||
</AuthProvider>
|
||||
</ToastProvider>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user