/** * Admin layout with sidebar navigation. * Desktop: persistent sidebar. Mobile (<768px): hamburger + slide-in drawer. * Used by all /admin/* pages. * @see specs/prd-web.md Section 4 (AdminLayout) */ 'use client' import { useState, useCallback } from 'react' import Link from 'next/link' import { usePathname } from 'next/navigation' import * as Dialog from '@radix-ui/react-dialog' import { Article, ChartBar, FolderSimple, ShieldCheck, Gear, PaintBrush, Tag, Users, PuzzlePiece, ClipboardText, ArrowLeft, ShieldWarning, SealCheck, List, ListNumbers, X, } from '@phosphor-icons/react' import { cn } from '@/lib/utils' interface AdminLayoutProps { children: React.ReactNode } const NAV_ITEMS = [ { href: '/admin', label: 'Dashboard', icon: ChartBar }, { href: '/admin/categories', label: 'Categories', icon: FolderSimple }, { href: '/admin/pages', label: 'Pages', icon: Article }, { href: '/admin/moderation', label: 'Moderation', icon: ShieldCheck }, { href: '/admin/rules', label: 'Rules', icon: ListNumbers }, { href: '/admin/sybil-detection', label: 'Sybil Detection', icon: ShieldWarning }, { href: '/admin/trust-seeds', label: 'Trust Seeds', icon: SealCheck }, { href: '/admin/settings', label: 'Settings', icon: Gear }, { href: '/admin/design', label: 'Design', icon: PaintBrush }, { href: '/admin/content-ratings', label: 'Content Ratings', icon: Tag }, { href: '/admin/onboarding', label: 'Onboarding', icon: ClipboardText }, { href: '/admin/users', label: 'Users', icon: Users }, { href: '/admin/plugins', label: 'Plugins', icon: PuzzlePiece }, ] function AdminNav({ pathname, onLinkClick }: { pathname: string; onLinkClick?: () => void }) { return ( <>
) } export function AdminLayout({ children }: AdminLayoutProps) { const pathname = usePathname() const [drawerOpen, setDrawerOpen] = useState(false) const closeDrawer = useCallback(() => setDrawerOpen(false), []) return (
{/* Mobile top bar */}
Admin menu
Admin
{/* Desktop sidebar */} {/* Main content - add top padding on mobile for the fixed bar */}
{children}
) }