import { useState } from 'react'; import { NavLink, useLocation } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { LayoutDashboard, Router, Users, Bell, GitBranch, HardDrive, Settings, Network, ChevronLeft, ChevronRight, Layers, ChevronDown, SlidersHorizontal, X, Wifi, Server, Globe, Clock, Shield, FileText, Activity, BarChart3, } from 'lucide-react'; import clsx from 'clsx'; import { APP_VERSION } from '../../version'; import { devicesApi } from '../../services/api'; const navItems = [ { to: '/dashboard', icon: LayoutDashboard, label: 'Dashboard' }, { to: '/devices', icon: Router, label: 'Devices' }, { to: '/clients', icon: Users, label: 'Clients' }, { to: '/traffic', icon: Activity, label: 'Traffic' }, { to: '/security', icon: Shield, label: 'Security' }, { to: '/events', icon: Bell, label: 'Events' }, { to: '/topology', icon: GitBranch, label: 'Topology' }, { to: '/backups', icon: HardDrive, label: 'Backups' }, ]; const switchSubItems = [ { to: '/switches', icon: Layers, label: 'Overview' }, { to: '/switches/settings', icon: SlidersHorizontal, label: 'Settings' }, ]; const routerSubItems = [ { to: '/routers', icon: Router, label: 'Overview' }, { to: '/routers/settings', icon: SlidersHorizontal, label: 'Settings' }, ]; const wirelessSubItems = [ { to: '/wireless', icon: Wifi, label: 'Overview' }, { to: '/wireless/clients', icon: Users, label: 'Clients' }, { to: '/wireless/settings', icon: SlidersHorizontal, label: 'Settings' }, ]; const networkServicesSubItems = [ { to: '/network-services', icon: Network, label: 'Overview' }, { to: '/network-services/dhcp', icon: Server, label: 'DHCP' }, { to: '/network-services/dns', icon: Globe, label: 'DNS' }, { to: '/network-services/ntp', icon: Clock, label: 'NTP' }, { to: '/network-services/wireguard', icon: Shield, label: 'WireGuard' }, { to: '/network-services/syslog', icon: FileText, label: 'Syslog' }, { to: '/network-services/netflow', icon: BarChart3, label: 'NetFlow' }, ]; interface SidebarProps { mobileOpen: boolean; onMobileClose: () => void; } function NavItem({ to, icon: Icon, label, isCollapsed, onClick, end, }: { to: string; icon: React.ElementType; label: string; isCollapsed: boolean; onClick: () => void; end?: boolean; }) { return ( clsx( 'flex items-center gap-[10px] rounded-[6px] text-[13px] font-medium transition-colors duration-150 relative', isCollapsed ? 'md:justify-center md:px-2 px-[10px] py-[7px]' : 'px-[10px] py-[7px]', isActive ? 'bg-surface-3 text-ink font-semibold border-l-2 border-accent pl-[8px]' : 'text-ink-2 hover:bg-surface-3 hover:text-ink border-l-2 border-transparent' ) } > {label} ); } function GroupHeader({ icon: Icon, label, isActive, isOpen, onToggle, }: { icon: React.ElementType; label: string; isActive: boolean; isOpen: boolean; onToggle: () => void; }) { return ( ); } export default function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) { const [collapsed, setCollapsed] = useState(false); const location = useLocation(); const { data: devices = [] } = useQuery({ queryKey: ['devices'], queryFn: () => devicesApi.list().then(r => r.data), staleTime: 60_000, }); const hasSwitches = devices.some(d => d.device_type === 'switch'); const hasRouters = devices.some(d => d.device_type === 'router'); const hasWireless = devices.some(d => d.device_type === 'wireless_ap'); const onlineCount = devices.filter(d => d.status === 'online').length; const switchesActive = location.pathname.startsWith('/switches'); const [switchesOpen, setSwitchesOpen] = useState(switchesActive); const effectiveSwitchesOpen = switchesOpen || switchesActive; const routersActive = location.pathname.startsWith('/routers'); const [routersOpen, setRoutersOpen] = useState(routersActive); const effectiveRoutersOpen = routersOpen || routersActive; const wirelessActive = location.pathname.startsWith('/wireless'); const [wirelessOpen, setWirelessOpen] = useState(wirelessActive); const effectiveWirelessOpen = wirelessOpen || wirelessActive; const networkServicesActive = location.pathname.startsWith('/network-services'); const [networkServicesOpen, setNetworkServicesOpen] = useState(networkServicesActive); const effectiveNetworkServicesOpen = networkServicesOpen || networkServicesActive; const isCollapsed = collapsed; const handleNavClick = () => { onMobileClose(); }; return ( ); }