/** * ShellLayout — the professional frame around every surface in the repo. * * Collapsible grouped sidebar (all platform surfaces from the nav registry), * top bar with breadcrumb, live platform-status indicator (GET /api/status), * command palette (Ctrl/Cmd-K) for jump-to-surface, and the routed page in a * per-route error boundary + suspense skeleton. Aureon prism identity, shadcn * primitives, zero new dependencies. */ import { Suspense, useCallback, useEffect, useState } from "react"; import { Link, Outlet, useLocation, useNavigate } from "react-router-dom"; import { Search } from "lucide-react"; import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarRail, SidebarTrigger, } from "@/components/ui/sidebar"; import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; import { HASH_REDIRECTS, navItemForPath, navSectionsForPlane, sectionForPath } from "./nav"; import { useIdentity } from "@/hooks/useIdentity"; import { BrandMark } from "./Brand"; import { PageSkeleton, RouteErrorBoundary } from "./Page"; import { BackendStatusBanner } from "@/components/BackendStatusBanner"; import { LiveVitals } from "@/components/LiveVitals"; import { SiteFooter } from "./SiteFooter"; import { RiskDisclaimer } from "@/components/RiskDisclaimer"; import { SupportProjectPrompt } from "@/components/SupportProjectPrompt"; type PlatformHealth = "healthy" | "degraded" | "critical" | "unknown"; function usePlatformStatus(): PlatformHealth { const [health, setHealth] = useState("unknown"); useEffect(() => { let cancelled = false; const poll = async () => { try { const r = await fetch("/api/status", { cache: "no-store" }); if (!r.ok) throw new Error(String(r.status)); const j = (await r.json()) as { status?: string }; if (!cancelled) { const s = String(j.status || "unknown"); setHealth(s === "healthy" || s === "degraded" || s === "critical" ? (s as PlatformHealth) : "unknown"); } } catch { if (!cancelled) setHealth("unknown"); } }; poll(); const t = setInterval(poll, 30_000); return () => { cancelled = true; clearInterval(t); }; }, []); return health; } const STATUS_STYLE: Record = { healthy: { dot: "bg-success", label: "Healthy" }, degraded: { dot: "bg-primary", label: "Degraded" }, critical: { dot: "bg-destructive", label: "Critical" }, unknown: { dot: "bg-muted-foreground", label: "No gateway" }, }; function StatusIndicator() { const health = usePlatformStatus(); const s = STATUS_STYLE[health]; return (
{s.label}
); } function CommandPalette() { // Hide the instance-control surfaces from a signed-in end user: their routes are operator-only, // so offering them here would only lead to a 403. Defaults to the full nav until identity resolves. const { identity } = useIdentity(); const sections = navSectionsForPlane(identity.isAdmin); const [open, setOpen] = useState(false); const navigate = useNavigate(); useEffect(() => { const onKey = (e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); setOpen((v) => !v); } }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, []); const go = useCallback( (path: string) => { setOpen(false); navigate(path); }, [navigate], ); return ( <> No surface found. {sections.map((section) => ( {section.items.map((item) => ( go(item.path)}> {item.label} {item.description} ))} ))} ); } function ShellSidebar() { const { identity } = useIdentity(); const sections = navSectionsForPlane(identity.isAdmin); const location = useLocation(); return (
AUREON Harmonic Nexus Core
{sections.map((section) => ( {section.label} {section.items.map((item) => ( {item.label} ))} ))}
); } function ShellBreadcrumb() { const location = useLocation(); const item = navItemForPath(location.pathname); const section = sectionForPath(location.pathname); return ( Aureon {section && section.label !== "Platform" && ( <> {section.label} )} {item?.label ?? "Not found"} ); } /** Redirect legacy #tab deep links to shell routes (once, on first load). */ function useLegacyHashRedirect() { const navigate = useNavigate(); const location = useLocation(); useEffect(() => { if (location.pathname !== "/") return; const hash = window.location.hash.split("/")[0]; const target = HASH_REDIRECTS[hash]; if (target) { const [path, keepHash] = target.split("#"); navigate(path || "/", { replace: true }); window.location.hash = keepHash ? `#${keepHash}` : ""; } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); } export default function ShellLayout() { useLegacyHashRedirect(); const location = useLocation(); const item = navItemForPath(location.pathname); const section = sectionForPath(location.pathname); const isTrading = section?.label === "Trading"; return (
{item?.live && ( live surface )}
{isTrading && (
)} }>
); }