import { ReactNode, useState, useEffect } from 'react' import { Link, useLocation } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' import { ThemeToggle } from './ThemeToggle' import { Button } from './ui/Button' import { useAuth } from '../hooks/useAuth' import { checkHealth } from '../api/health' import { getFeatureFlags } from '../api/featureFlags' import NotificationCenter from './NotificationCenter' import SystemStatus from './SystemStatus' import { Menu, ChevronDown, ChevronRight } from 'lucide-react' interface LayoutProps { children: ReactNode } type NavItem = { name: string path?: string icon?: string children?: NavItem[] } export default function Layout({ children }: LayoutProps) { const location = useLocation() const { t } = useTranslation() const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false) const [isCollapsed, setIsCollapsed] = useState(() => { const saved = localStorage.getItem('sidebarCollapsed') return saved ? JSON.parse(saved) : false }) const [expandedMenus, setExpandedMenus] = useState([]) const { logout, user } = useAuth() useEffect(() => { localStorage.setItem('sidebarCollapsed', JSON.stringify(isCollapsed)) }, [isCollapsed]) const toggleMenu = (name: string) => { setExpandedMenus(prev => prev.includes(name) ? prev.filter(item => item !== name) : [...prev, name] ) } const { data: health } = useQuery({ queryKey: ['health'], queryFn: checkHealth, staleTime: 1000 * 60 * 60, // 1 hour }) const { data: featureFlags } = useQuery({ queryKey: ['feature-flags'], queryFn: getFeatureFlags, staleTime: 1000 * 60 * 5, // 5 minutes }) const navigation: NavItem[] = [ { name: t('navigation.dashboard'), path: '/', icon: '📊' }, { name: t('navigation.proxyHosts'), path: '/proxy-hosts', icon: '🌐' }, { name: t('navigation.remoteServers'), path: '/remote-servers', icon: '🖥️' }, { name: t('navigation.domains'), path: '/domains', icon: '🌍' }, { name: t('navigation.certificates'), path: '/certificates', icon: '🔒' }, { name: t('navigation.dns'), path: '/dns', icon: '☁️', children: [ { name: t('navigation.dnsProviders'), path: '/dns/providers', icon: '🧭' }, { name: t('navigation.plugins'), path: '/dns/plugins', icon: '🔌' }, ] }, { name: t('navigation.uptime'), path: '/uptime', icon: '📈' }, { name: t('navigation.security'), path: '/security', icon: '🛡️', children: [ { name: t('navigation.dashboard'), path: '/security', icon: '🛡️' }, { name: t('navigation.crowdsec'), path: '/security/crowdsec', icon: '🛡️' }, { name: t('navigation.accessLists'), path: '/security/access-lists', icon: '🔒' }, { name: t('navigation.rateLimiting'), path: '/security/rate-limiting', icon: '⚡' }, { name: t('navigation.waf'), path: '/security/waf', icon: '🛡️' }, { name: t('navigation.securityHeaders'), path: '/security/headers', icon: '🔐' }, { name: t('navigation.encryption'), path: '/security/encryption', icon: '🔑' }, ]}, { name: t('navigation.settings'), path: '/settings', icon: '⚙️', children: [ { name: t('navigation.system'), path: '/settings/system', icon: '⚙️' }, { name: t('navigation.notifications'), path: '/settings/notifications', icon: '🔔' }, { name: t('navigation.email'), path: '/settings/smtp', icon: '📧' }, { name: t('navigation.adminAccount'), path: '/settings/account', icon: '🛡️' }, { name: t('navigation.accountManagement'), path: '/settings/account-management', icon: '👥' }, ] }, { name: t('navigation.tasks'), path: '/tasks', icon: '📋', children: [ { name: t('navigation.import'), path: '/tasks/import', children: [ { name: t('navigation.caddyfile'), path: '/tasks/import/caddyfile', icon: '📥' }, { name: t('navigation.crowdsec'), path: '/tasks/import/crowdsec', icon: '🛡️' }, ] }, { name: t('navigation.backups'), path: '/tasks/backups', icon: '💾' }, { name: t('navigation.logs'), path: '/tasks/logs', icon: '📝' }, ] }, ].filter(item => { // Optional Features Logic // Default to visible (true) if flags are loading or undefined if (item.name === t('navigation.uptime')) return featureFlags?.['feature.uptime.enabled'] !== false if (item.name === t('navigation.security')) return featureFlags?.['feature.cerberus.enabled'] !== false return true }) return (
{/* Mobile Header */}
Charon
{/* Sidebar */} {/* Overlay for mobile */} {/* Mobile Overlay */} {mobileSidebarOpen && (
setMobileSidebarOpen(false)} /> )} {/* Main Content */}
{/* Desktop Header */}
{/* Banner moved to sidebar */}
{user && ( {user.name} )}
{children}
) }