Files
zavrsni-rad-otel-app/frontend/src/App.tsx
2026-05-11 10:58:46 +02:00

146 lines
5.2 KiB
TypeScript

import { Navigate, NavLink, Route, Routes } from "react-router-dom";
import { useAuth } from "./auth/AuthContext";
import SalesDashboard from "./pages/aw/SalesDashboard";
import RepScores from "./pages/aw/RepScores";
import ProductDemand from "./pages/aw/ProductDemand";
import AnomalyDetection from "./pages/aw/AnomalyDetection";
import StockDashboard from "./pages/wwi/StockDashboard";
import SupplierScores from "./pages/wwi/SupplierScores";
import WhatIf from "./pages/wwi/WhatIf";
import BusinessEvents from "./pages/wwi/BusinessEvents";
import OperationsPage from "./pages/ops/OperationsPage";
import AuditPage from "./pages/ops/AuditPage";
import ExportsPage from "./pages/ops/ExportsPage";
function NavItem({ to, label }: { to: string; label: string }) {
return (
<NavLink
to={to}
className={({ isActive }) => `nav-link${isActive ? " nav-active" : ""}`}
>
{label}
</NavLink>
);
}
function CenteredShell({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen grid place-items-center text-center p-4 text-[#d6e7ff]">
{children}
</div>
);
}
export default function App() {
const auth = useAuth();
if (auth.loading) {
return <CenteredShell>Initializing OIDC session</CenteredShell>;
}
if (auth.error) {
return <CenteredShell>Authentication error: {auth.error}</CenteredShell>;
}
if (auth.enabled && !auth.authenticated) {
return (
<CenteredShell>
<div className="flex flex-col items-center gap-4">
<p className="m-0 text-lg">Authentication required.</p>
<button className="btn-primary" onClick={() => void auth.login()} type="button">
Sign In with OIDC
</button>
</div>
</CenteredShell>
);
}
return (
<div className="flex min-h-screen">
{/* Sidebar */}
<nav className="
w-[220px] max-[980px]:w-[180px]
shrink-0
bg-[rgba(8,16,28,0.92)]
border-r border-[rgba(186,212,255,0.22)]
flex flex-col
py-5 px-3
sticky top-0 h-screen overflow-y-auto
max-sm:w-full max-sm:h-auto max-sm:static
max-sm:flex-row max-sm:flex-wrap max-sm:gap-2 max-sm:p-3
">
<div className="flex items-center gap-2 font-bold text-[0.95rem] tracking-tight mb-6 px-[0.4rem] max-sm:mb-0">
<span className="text-[#57d4ff] text-[0.7rem]"></span>
<span>OTel BI Platform</span>
</div>
<div className="mb-5">
<div className="text-[0.65rem] uppercase tracking-[0.12em] text-[rgba(233,244,255,0.7)] px-[0.4rem] mb-1">
AdventureWorks DW
</div>
<NavItem to="/aw/sales" label="Sales & Forecast" />
<NavItem to="/aw/reps" label="Rep Scores" />
<NavItem to="/aw/products" label="Product Demand" />
<NavItem to="/aw/anomalies" label="Anomaly Detection" />
</div>
<div className="mb-5">
<div className="text-[0.65rem] uppercase tracking-[0.12em] text-[rgba(233,244,255,0.7)] px-[0.4rem] mb-1">
WideWorldImporters DW
</div>
<NavItem to="/wwi/stock" label="Stock & Reorder" />
<NavItem to="/wwi/suppliers" label="Supplier Scores" />
<NavItem to="/wwi/whatif" label="What-if Scenarios" />
<NavItem to="/wwi/events" label="Business Events" />
</div>
<div className="mb-5">
<div className="text-[0.65rem] uppercase tracking-[0.12em] text-[rgba(233,244,255,0.7)] px-[0.4rem] mb-1">
Platform
</div>
<NavItem to="/ops/jobs" label="Operations" />
<NavItem to="/ops/audit" label="Audit Log" />
<NavItem to="/ops/exports" label="Export History" />
</div>
<div className="mt-auto pt-4 border-t border-[rgba(186,212,255,0.22)] max-sm:mt-0 max-sm:pt-0 max-sm:border-t-0">
{auth.subject && (
<p className="text-[0.78rem] text-[rgba(233,244,255,0.7)] m-0 mb-2 overflow-hidden text-ellipsis whitespace-nowrap">
{auth.subject}
</p>
)}
{auth.enabled && (
<button className="btn-ghost" onClick={() => void auth.logout()} type="button">
Sign Out
</button>
)}
</div>
</nav>
{/* Main content */}
<main className="flex-1 overflow-auto p-6">
<Routes>
<Route index element={<Navigate to="/aw/sales" replace />} />
<Route path="/aw/sales" element={<SalesDashboard />} />
<Route path="/aw/reps" element={<RepScores />} />
<Route path="/aw/products" element={<ProductDemand />} />
<Route path="/aw/anomalies" element={<AnomalyDetection />} />
<Route path="/wwi/stock" element={<StockDashboard />} />
<Route path="/wwi/suppliers" element={<SupplierScores />} />
<Route path="/wwi/whatif" element={<WhatIf />} />
<Route path="/wwi/events" element={<BusinessEvents />} />
<Route path="/ops/jobs" element={<OperationsPage />} />
<Route path="/ops/audit" element={<AuditPage />} />
<Route path="/ops/exports" element={<ExportsPage />} />
<Route path="*" element={<Navigate to="/aw/sales" replace />} />
</Routes>
</main>
</div>
);
}