import { useState, useMemo } from 'react'; import { Outlet, useNavigate, useLocation } from 'react-router'; import { LayoutDashboard, ShieldCheck, Building, Activity } from 'lucide-react'; import { AppShell, Sidebar, TopBar, } from '@cameleer/design-system'; import { useAuth } from '../auth/useAuth'; import { useScopes } from '../auth/useScopes'; import { useOrgStore } from '../auth/useOrganization'; import cameleerLogo from '@cameleer/design-system/assets/cameleer3-logo.svg'; function CameleerLogo() { return ( ); } export function Layout() { const navigate = useNavigate(); const location = useLocation(); const { logout } = useAuth(); const scopes = useScopes(); const { username } = useOrgStore(); const [collapsed, setCollapsed] = useState(false); const breadcrumb = useMemo(() => { if (location.pathname.startsWith('/admin')) return [{ label: 'Admin' }, { label: 'Tenants' }]; if (location.pathname.startsWith('/license')) return [{ label: 'License' }]; return [{ label: 'Dashboard' }]; }, [location.pathname]); const sidebar = ( setCollapsed(c => !c)}> } title="Cameleer SaaS" onClick={() => navigate('/')} /> {/* Dashboard */} } label="Dashboard" open={false} active={location.pathname === '/' || location.pathname === ''} onToggle={() => navigate('/')} > {null} {/* License */} } label="License" open={false} active={location.pathname.startsWith('/license')} onToggle={() => navigate('/license')} > {null} {/* Platform Admin section */} {scopes.has('platform:admin') && ( } label="Platform" open={false} active={location.pathname.startsWith('/admin')} onToggle={() => navigate('/admin/tenants')} > {null} )} {/* Link to the server observability dashboard */} } label="Open Server Dashboard" onClick={() => window.open('/server/', '_blank', 'noopener')} /> ); return ( {/* * TopBar always renders status filters, time range pills, auto-refresh, and * command palette search via useGlobalFilters() / useCommandPalette(). Both * hooks throw if their providers are absent, so GlobalFilterProvider and * CommandPaletteProvider cannot be removed from main.tsx without crashing the * app. The TopBar API has no props to suppress these server-oriented controls. * Hiding them on platform pages would require a DS change. */} ); }