import { useState } from 'react' import { NavLink } from 'react-router-dom' import { Command, Activity, FolderKanban, Monitor, Settings, Menu, X, Wifi, WifiOff, Loader } from 'lucide-react' import { useSSEContext } from '../contexts/SSEContext' import type { SSEStatus } from '../hooks/useSSE' const navItems = [ { to: '/', icon: Command, label: 'Hub' }, { to: '/logs', icon: Activity, label: 'Logs' }, { to: '/projects', icon: FolderKanban, label: 'Projects' }, { to: '/sessions', icon: Monitor, label: 'Sessions' }, { to: '/settings', icon: Settings, label: 'Settings' }, ] /** Small status pill shown in the sidebar footer and mobile header. */ function SSEStatusBadge({ status, showLabel = false }: { status: SSEStatus; showLabel?: boolean }) { const cfg = { connected: { icon: Wifi, color: 'text-green-500', label: 'Live' }, connecting: { icon: Loader, color: 'text-yellow-500 animate-spin', label: 'Connecting' }, reconnecting: { icon: Loader, color: 'text-yellow-500 animate-spin', label: 'Reconnecting' }, error: { icon: WifiOff, color: 'text-red-500', label: 'Disconnected' }, }[status] const Icon = cfg.icon return (
{showLabel && {cfg.label}}
) } export default function Layout({ children }: { children: React.ReactNode }) { const [expanded, setExpanded] = useState(false) const [mobileOpen, setMobileOpen] = useState(false) const { sseStatus } = useSSEContext() return (
{/* Desktop Nav Rail */} {/* Mobile Header + Bottom Nav */}
Control Center
{/* Mobile drawer */} {mobileOpen && (
{navItems.map((item) => ( setMobileOpen(false)} className={({ isActive }) => `flex items-center gap-3 px-4 py-3 rounded-lg ${ isActive ? 'bg-primary/10 text-primary' : 'text-on-surface-variant' }` } > {item.label} ))}
)}
{children}
{/* Mobile Bottom Nav */}
) }