'use client'
import { useState, useCallback, useEffect, useRef } from 'react'
import dynamic from 'next/dynamic'
import { formatUpdatedAgo } from '@ciphera-net/ui'
import { SidebarSimple } from '@phosphor-icons/react'
import { SidebarProvider, useSidebar } from '@/lib/sidebar-context'
import { useRealtime } from '@/lib/swr/dashboard'
import ContentHeader from './ContentHeader'
// Load sidebar only on the client โ prevents SSR flash
const Sidebar = dynamic(() => import('./Sidebar'), {
ssr: false,
loading: () => (
),
})
function GlassTopBar({ siteId }: { siteId: string }) {
const { collapsed, toggle } = useSidebar()
const { data: realtime } = useRealtime(siteId)
const lastUpdatedRef = useRef(null)
const [, setTick] = useState(0)
useEffect(() => {
if (realtime) lastUpdatedRef.current = Date.now()
}, [realtime])
useEffect(() => {
if (lastUpdatedRef.current == null) return
const timer = setInterval(() => setTick((t) => t + 1), 1000)
return () => clearInterval(timer)
}, [realtime])
return (
{/* Collapse toggle โ negative margin to align with sidebar icons */}
{/* Realtime indicator */}
{lastUpdatedRef.current != null && (
Live ยท {formatUpdatedAgo(lastUpdatedRef.current)}
)}
)
}
export default function DashboardShell({
siteId,
children,
}: {
siteId: string
children: React.ReactNode
}) {
const [mobileOpen, setMobileOpen] = useState(false)
const closeMobile = useCallback(() => setMobileOpen(false), [])
const openMobile = useCallback(() => setMobileOpen(true), [])
return (
{/* Glass top bar โ above content only, collapse icon reaches back into sidebar column */}
{/* Content panel */}
{children}
)
}