diff --git a/components/dashboard/DashboardShell.tsx b/components/dashboard/DashboardShell.tsx index 76d023c..a128f29 100644 --- a/components/dashboard/DashboardShell.tsx +++ b/components/dashboard/DashboardShell.tsx @@ -3,12 +3,13 @@ import { useState, useCallback, useEffect, useRef } from 'react' import dynamic from 'next/dynamic' import Link from 'next/link' -import { usePathname } from 'next/navigation' +import { usePathname, useRouter } from 'next/navigation' import { formatUpdatedAgo } from '@ciphera-net/ui' -import { CaretRight, SidebarSimple } from '@phosphor-icons/react' +import { CaretDown, CaretRight, SidebarSimple } from '@phosphor-icons/react' import { SidebarProvider, useSidebar } from '@/lib/sidebar-context' import { useRealtime } from '@/lib/swr/dashboard' -import { getSite } from '@/lib/api/sites' +import { getSite, listSites, type Site } from '@/lib/api/sites' +import { FAVICON_SERVICE_URL } from '@/lib/utils/favicon' import ContentHeader from './ContentHeader' const PAGE_TITLES: Record = { @@ -55,6 +56,74 @@ const Sidebar = dynamic(() => import('./Sidebar'), { ), }) +// ─── Breadcrumb Site Picker ──────────────────────────────── + +function BreadcrumbSitePicker({ currentSiteId, currentSiteName }: { currentSiteId: string; currentSiteName: string }) { + const [open, setOpen] = useState(false) + const [sites, setSites] = useState([]) + const ref = useRef(null) + const pathname = usePathname() + const router = useRouter() + + useEffect(() => { + if (open && sites.length === 0) { + listSites().then(setSites).catch(() => {}) + } + }, [open, sites.length]) + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) + } + document.addEventListener('mousedown', handler) + return () => document.removeEventListener('mousedown', handler) + }, []) + + const switchSite = (id: string) => { + // Navigate to same section on the new site + router.push(`/sites/${id}${pathname.replace(/^\/sites\/[^/]+/, '')}`) + setOpen(false) + } + + return ( +
+ + {open && ( +
+
+ {sites.map((site) => ( + + ))} +
+
+ )} +
+ ) +} + +// ─── Glass Top Bar ───────────────────────────────────────── + function GlassTopBar({ siteId }: { siteId: string | null }) { const { collapsed, toggle } = useSidebar() const { data: realtime } = useRealtime(siteId ?? '') @@ -96,7 +165,7 @@ function GlassTopBar({ siteId }: { siteId: string | null }) {