Files
BanGUI/frontend/src/App.tsx
Lukas 29415da421 Add ErrorBoundary component to catch render-time errors
- Create ErrorBoundary component to handle React render errors
- Wrap App component with ErrorBoundary for global error handling
- Add comprehensive tests for ErrorBoundary functionality
- Show fallback UI with error message when errors occur
2026-03-22 14:24:28 +01:00

96 lines
3.7 KiB
TypeScript

/**
* Application root component.
*
* Wraps the entire application in:
* 1. `FluentProvider` — supplies the Fluent UI theme and design tokens.
* 2. `BrowserRouter` — enables client-side routing via React Router.
* 3. `AuthProvider` — manages session state and exposes `useAuth()`.
*
* Routes:
* - `/setup` — first-run setup wizard (always accessible; redirects to /login if already done)
* - `/login` — master password login (redirects to /setup if not done)
* - `/` — dashboard (protected, inside MainLayout)
* - `/map` — world map (protected)
* - `/jails` — jail list (protected)
* - `/jails/:name` — jail detail (protected)
* - `/config` — configuration editor (protected)
* - `/history` — event history (protected)
* - `/blocklists` — blocklist management (protected)
* All unmatched paths redirect to `/`.
*/
import { FluentProvider } from "@fluentui/react-components";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import { lightTheme } from "./theme/customTheme";
import { AuthProvider } from "./providers/AuthProvider";
import { TimezoneProvider } from "./providers/TimezoneProvider";
import { RequireAuth } from "./components/RequireAuth";
import { SetupGuard } from "./components/SetupGuard";
import { ErrorBoundary } from "./components/ErrorBoundary";
import { MainLayout } from "./layouts/MainLayout";
import { SetupPage } from "./pages/SetupPage";
import { LoginPage } from "./pages/LoginPage";
import { DashboardPage } from "./pages/DashboardPage";
import { MapPage } from "./pages/MapPage";
import { JailsPage } from "./pages/JailsPage";
import { JailDetailPage } from "./pages/JailDetailPage";
import { ConfigPage } from "./pages/ConfigPage";
import { HistoryPage } from "./pages/HistoryPage";
import { BlocklistsPage } from "./pages/BlocklistsPage";
/**
* Root application component — mounts providers and top-level routes.
*/
function App(): React.JSX.Element {
return (
<FluentProvider theme={lightTheme}>
<ErrorBoundary>
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
<AuthProvider>
<Routes>
{/* Setup wizard — always accessible; redirects to /login if already done */}
<Route path="/setup" element={<SetupPage />} />
{/* Login — requires setup to be complete */}
<Route
path="/login"
element={
<SetupGuard>
<LoginPage />
</SetupGuard>
}
/>
{/* Protected routes — require setup AND authentication */}
<Route
element={
<SetupGuard>
<RequireAuth>
<TimezoneProvider>
<MainLayout />
</TimezoneProvider>
</RequireAuth>
</SetupGuard>
}
>
<Route index element={<DashboardPage />} />
<Route path="/map" element={<MapPage />} />
<Route path="/jails" element={<JailsPage />} />
<Route path="/jails/:name" element={<JailDetailPage />} />
<Route path="/config" element={<ConfigPage />} />
<Route path="/history" element={<HistoryPage />} />
<Route path="/blocklists" element={<BlocklistsPage />} />
</Route>
{/* Fallback — redirect unknown paths to dashboard */}
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</AuthProvider>
</BrowserRouter>
</ErrorBoundary>
</FluentProvider>
);
}
export default App;