Files
veille-reglementaire/client/src/App.tsx

186 lines
5.4 KiB
TypeScript

import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { lazy, Suspense } from "react";
import { Route, Switch, Redirect } from "wouter";
import ErrorBoundary from "./components/ErrorBoundary";
import { ThemeProvider } from "./contexts/ThemeContext";
import { LocalAuthProvider, useLocalAuth } from "./contexts/LocalAuthContext";
import { AppLayout } from "./components/AppLayout";
import { Loader2 } from "lucide-react";
// Chaque page est chargée à la demande : la connexion reste rapide et les écrans
// d'administration lourds ne sont téléchargés que lorsqu'ils sont effectivement ouverts.
const NotFound = lazy(() => import("@/pages/NotFound"));
const Login = lazy(() => import("./pages/Login"));
const VeilleDashboard = lazy(() => import("./pages/VeilleDashboard"));
const AAPDashboard = lazy(() => import("./pages/AAPDashboard"));
const Settings = lazy(() => import("./pages/Settings"));
const UsersAdmin = lazy(() => import("./pages/UsersAdmin"));
const ImportLogs = lazy(() => import("./pages/ImportLogs"));
const ClassificationErrors = lazy(() => import("./pages/ClassificationErrors"));
const BoiteAIdees = lazy(() => import("@/pages/BoiteAIdees"));
const RssFeeds = lazy(() => import("@/pages/RssFeeds"));
const AzureCallback = lazy(() => import("@/pages/AzureCallback"));
// ─── Guard d'authentification ─────────────────────────────────────────────────
function AuthGuard({ children }: { children: React.ReactNode }) {
const { user, loading } = useLocalAuth();
if (loading) {
return (
<div className="min-h-screen flex items-center justify-center bg-background">
<Loader2 size={32} className="animate-spin text-primary" />
</div>
);
}
if (!user) {
return <Redirect to="/login" />;
}
return <>{children}</>;
}
// ─── Layout avec sidebar ──────────────────────────────────────────────────────
function DashboardWrapper({ children }: { children: React.ReactNode }) {
const { user, logout } = useLocalAuth();
return (
<AppLayout user={user} onLogout={logout}>
{children}
</AppLayout>
);
}
// ─── Pages protégées ──────────────────────────────────────────────────────────
function VeillePage() {
return (
<AuthGuard>
<DashboardWrapper>
<VeilleDashboard />
</DashboardWrapper>
</AuthGuard>
);
}
function AAPPage() {
return (
<AuthGuard>
<DashboardWrapper>
<AAPDashboard />
</DashboardWrapper>
</AuthGuard>
);
}
function SettingsPage() {
return (
<AuthGuard>
<DashboardWrapper>
<Settings />
</DashboardWrapper>
</AuthGuard>
);
}
function UsersPage() {
return (
<AuthGuard>
<DashboardWrapper>
<UsersAdmin />
</DashboardWrapper>
</AuthGuard>
);
}
function LogsPage() {
return (
<AuthGuard>
<DashboardWrapper>
<ImportLogs />
</DashboardWrapper>
</AuthGuard>
);
}
function ClassificationErrorsPage() {
return (
<AuthGuard>
<DashboardWrapper>
<ClassificationErrors />
</DashboardWrapper>
</AuthGuard>
);
}
function BoiteAIdeesPage() {
return (
<AuthGuard>
<DashboardWrapper>
<BoiteAIdees />
</DashboardWrapper>
</AuthGuard>
);
}
function RssFeedsPage() {
return (
<AuthGuard>
<DashboardWrapper>
<RssFeeds />
</DashboardWrapper>
</AuthGuard>
);
}
// ─── Routeur principal ────────────────────────────────────────────────────────
function Router() {
return (
<Switch>
<Route path="/login" component={Login} />
<Route path="/azure-callback" component={AzureCallback} />
<Route path="/">
<Redirect to="/veille" />
</Route>
<Route path="/veille" component={VeillePage} />
<Route path="/aap" component={AAPPage} />
<Route path="/admin/settings" component={SettingsPage} />
<Route path="/admin/users" component={UsersPage} />
<Route path="/admin/logs" component={LogsPage} />
<Route path="/admin/classification-errors" component={ClassificationErrorsPage} />
<Route path="/boite-a-idees" component={BoiteAIdeesPage} />
<Route path="/admin/rss" component={RssFeedsPage} />
<Route path="/404" component={NotFound} />
<Route component={NotFound} />
</Switch>
);
}
function App() {
return (
<ErrorBoundary>
<ThemeProvider defaultTheme="light">
<LocalAuthProvider>
<TooltipProvider>
<Toaster richColors position="top-right" />
<Suspense
fallback={(
<div className="min-h-screen flex items-center justify-center bg-background">
<Loader2 size={32} className="animate-spin text-primary" />
</div>
)}
>
<Router />
</Suspense>
</TooltipProvider>
</LocalAuthProvider>
</ThemeProvider>
</ErrorBoundary>
);
}
export default App;