import { useEffect } from 'react'; import { NavLink } from 'react-router-dom'; import { LayoutDashboard, Users, Building2, Ban, Flag, ScrollText, Activity, Megaphone, Upload, ShoppingBag, Gift, KeyRound, Wrench, MessageSquare, HardDrive, Settings, X, } from './Icons'; const groups: Array<{ title: string; items: Array<{ to: string; label: string; icon: React.ReactNode; new?: boolean }>}> = [ { title: 'Overview', items: [ { to: '/', label: 'Dashboard', icon: }, ], }, { title: 'People', items: [ { to: '/players', label: 'Players', icon: }, { to: '/bans', label: 'Bans', icon: }, { to: '/reports', label: 'Reports', icon: }, { to: '/audit', label: 'Audit log', icon: }, { to: '/logs', label: 'Player logs', icon: }, ], }, { title: 'Content', items: [ // Rooms is the unified view — clicking a row opens /rooms/:id // which carries the old RR-Originals edit modal, live Photon // instance list, recent visitors, ownership management, and // per-room leaderboard channels in one tabbed page. { to: '/rooms', label: 'Rooms', icon: }, { to: '/import-room', label: 'Import room', icon: }, { to: '/store', label: 'Store catalog', icon: }, { to: '/community', label: 'Community board', icon: }, { to: '/loading-tips', label: 'Loading screen tips', icon: }, ], }, { title: 'Tools', items: [ { to: '/broadcast', label: 'Broadcast', icon: }, { to: '/gift', label: 'Gift items', icon: , new: true }, { to: '/passwords', label: 'Reset passwords', icon: , new: true }, { to: '/grants', label: 'Grant maker pen', icon: , new: true }, { to: '/storage', label: 'Storage backfill', icon: , new: true }, { to: '/settings', label: 'Server settings', icon: , new: true }, ], }, ]; // Two-mode rendering: // * Desktop (md+): always-visible static rail to the left of
. // * Mobile: hidden by default; opens as a slide-in drawer with a // backdrop scrim, controlled by `open` from . Tapping any // nav link calls `onNavigate()` so the drawer closes automatically // after the user picks a destination. Escape also closes. export function Sidebar({ open, onClose, onNavigate }: { open: boolean; onClose: () => void; onNavigate: () => void }) { // Lock body scroll while the mobile drawer is up so the page behind // doesn't scroll through the backdrop. Skip on desktop where `open` // is irrelevant (the sidebar is always there). useEffect(() => { if (!open) return; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', onKey); const prev = document.body.style.overflow; document.body.style.overflow = 'hidden'; return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = prev; }; }, [open, onClose]); const inner = ( <>
D
DorkNet
admin
); return ( <> {/* Mobile drawer + backdrop */}
{/* Desktop static rail */} ); }