'use client' import { useState, useEffect, useRef } from 'react' import Link from 'next/link' import { usePathname, useRouter } from 'next/navigation' import { motion } from 'framer-motion' import { listSites, type Site } from '@/lib/api/sites' import { useAuth } from '@/lib/auth/context' import { Sidebar as SidebarPrimitive, SidebarBody, SidebarLink, useSidebar, } from '@/components/ui/sidebar' import { LayoutDashboardIcon, PathIcon, FunnelIcon, CursorClickIcon, SearchIcon, CloudUploadIcon, HeartbeatIcon, SettingsIcon, ChevronUpDownIcon, PlusIcon, } from '@ciphera-net/ui' interface NavItem { label: string href: (siteId: string) => string icon: React.ComponentType<{ className?: string; weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone' }> matchPrefix?: boolean } interface NavGroup { label: string items: NavItem[] } const NAV_GROUPS: NavGroup[] = [ { label: 'Analytics', items: [ { label: 'Dashboard', href: (id) => `/sites/${id}`, icon: LayoutDashboardIcon }, { label: 'Journeys', href: (id) => `/sites/${id}/journeys`, icon: PathIcon, matchPrefix: true }, { label: 'Funnels', href: (id) => `/sites/${id}/funnels`, icon: FunnelIcon, matchPrefix: true }, { label: 'Behavior', href: (id) => `/sites/${id}/behavior`, icon: CursorClickIcon, matchPrefix: true }, { label: 'Search', href: (id) => `/sites/${id}/search`, icon: SearchIcon, matchPrefix: true }, ], }, { label: 'Infrastructure', items: [ { label: 'CDN', href: (id) => `/sites/${id}/cdn`, icon: CloudUploadIcon, matchPrefix: true }, { label: 'Uptime', href: (id) => `/sites/${id}/uptime`, icon: HeartbeatIcon, matchPrefix: true }, ], }, ] const SETTINGS_ITEM: NavItem = { label: 'Settings', href: (id) => `/sites/${id}/settings`, icon: SettingsIcon, matchPrefix: true, } function SitePicker({ sites, siteId }: { sites: Site[]; siteId: string }) { const { open: sidebarOpen } = useSidebar() const [open, setOpen] = useState(false) const [search, setSearch] = useState('') const ref = useRef(null) const pathname = usePathname() const router = useRouter() const currentSite = sites.find((s) => s.id === siteId) useEffect(() => { const handleClickOutside = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false) setSearch('') } } document.addEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside) }, []) const filtered = sites.filter( (s) => s.name.toLowerCase().includes(search.toLowerCase()) || s.domain.toLowerCase().includes(search.toLowerCase()) ) const switchSite = (id: string) => { const currentPageType = pathname.replace(/^\/sites\/[^/]+/, '') router.push(`/sites/${id}${currentPageType}`) setOpen(false) setSearch('') } const initial = currentSite?.name?.charAt(0)?.toUpperCase() || '?' return (
{open && (
setSearch(e.target.value)} className="w-full px-3 py-1.5 text-sm bg-neutral-50 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 rounded-lg outline-none focus:ring-2 focus:ring-brand-orange/40 text-neutral-900 dark:text-white placeholder:text-neutral-400" autoFocus />
{filtered.map((site) => ( ))} {filtered.length === 0 && (

No sites found

)}
setOpen(false)} className="flex items-center gap-2 px-3 py-1.5 text-sm text-brand-orange hover:bg-neutral-50 dark:hover:bg-neutral-800 rounded-lg" > Add new site
)}
) } function SidebarContent({ siteId }: { siteId: string }) { const { user } = useAuth() const { open } = useSidebar() const pathname = usePathname() const canEdit = user?.role === 'owner' || user?.role === 'admin' const [sites, setSites] = useState([]) useEffect(() => { listSites().then(setSites).catch(() => {}) }, []) const isActive = (item: NavItem) => { const href = item.href(siteId) return item.matchPrefix ? pathname.startsWith(href) : pathname === href } return ( <>
{/* Site Picker */} {/* Nav Groups */} {NAV_GROUPS.map((group) => (
{open && ( {group.label} )}
{group.items.map((item) => ( ), }} className={ isActive(item) ? 'bg-brand-orange/10 text-brand-orange rounded-lg px-1' : 'rounded-lg px-1' } /> ))}
))}
{/* Bottom: Settings */}
{canEdit && ( ), }} className={ isActive(SETTINGS_ITEM) ? 'bg-brand-orange/10 text-brand-orange rounded-lg px-1' : 'rounded-lg px-1' } /> )}
) } export default function PulseSidebar({ siteId }: { siteId: string }) { const [open, setOpen] = useState(false) return ( ) }