'use client'
import { useEffect, useState, useRef } from 'react'
import { useRouter } from 'next/navigation'
import { useStore } from '@/lib/store'
import { Sidebar } from './Sidebar'
import { KeyboardShortcutsProvider, useUserShortcuts } from '@/hooks/useKeyboardShortcuts'
import { Bell, Search, X, Command } from 'lucide-react'
import Link from 'next/link'
import clsx from 'clsx'
interface CommandCenterLayoutProps {
children: React.ReactNode
title?: string
subtitle?: string
actions?: React.ReactNode
}
export function CommandCenterLayout({
children,
title,
subtitle,
actions
}: CommandCenterLayoutProps) {
const router = useRouter()
const { isAuthenticated, isLoading, checkAuth, domains } = useStore()
const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
const [notificationsOpen, setNotificationsOpen] = useState(false)
const [searchOpen, setSearchOpen] = useState(false)
const [searchQuery, setSearchQuery] = useState('')
const [mounted, setMounted] = useState(false)
const authCheckedRef = useRef(false)
// Ensure component is mounted before rendering
useEffect(() => {
setMounted(true)
}, [])
// Load sidebar state from localStorage
useEffect(() => {
if (mounted) {
const saved = localStorage.getItem('sidebar-collapsed')
if (saved) {
setSidebarCollapsed(saved === 'true')
}
}
}, [mounted])
// Check auth only once on mount
useEffect(() => {
if (!authCheckedRef.current) {
authCheckedRef.current = true
checkAuth()
}
}, [checkAuth])
useEffect(() => {
if (!isLoading && !isAuthenticated) {
router.push('/login')
}
}, [isLoading, isAuthenticated, router])
// Available domains for notifications
const availableDomains = domains?.filter(d => d.is_available) || []
const hasNotifications = availableDomains.length > 0
// Show loading only if we're still checking auth
if (!mounted || isLoading) {
return (
Loading Command Center...
)
}
if (!isAuthenticated) {
return null
}
return (
{/* Background Effects */}
{/* Sidebar */}
{/* Main Content Area */}
{/* Top Bar */}
{/* Left: Title */}
{title && (
{title}
)}
{subtitle && (
{subtitle}
)}
{/* Right: Actions */}
{/* Quick Search */}
{/* Mobile Search */}
{/* Notifications */}
{/* Notifications Dropdown */}
{notificationsOpen && (
Notifications
{availableDomains.length > 0 ? (
{availableDomains.slice(0, 5).map((domain) => (
setNotificationsOpen(false)}
className="flex items-start gap-3 p-3 hover:bg-foreground/5 rounded-lg transition-colors"
>
{domain.name}
Available now!
))}
) : (
No notifications
We'll notify you when domains become available
)}
)}
{/* Keyboard Shortcuts Hint */}
{/* Custom Actions */}
{actions}
{/* Page Content */}
{children}
{/* Quick Search Modal */}
{searchOpen && (
setSearchOpen(false)}
>
e.stopPropagation()}
>
setSearchQuery(e.target.value)}
className="flex-1 bg-transparent text-foreground placeholder:text-foreground-subtle
outline-none text-lg"
autoFocus
/>
Start typing to search...
)}
{/* Keyboard shortcut for search */}
setSearchOpen(true)} keys={['Meta', 'k']} />
)
}
// Keyboard shortcut component
function KeyboardShortcut({ onTrigger, keys }: { onTrigger: () => void, keys: string[] }) {
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if (keys.includes('Meta') && e.metaKey && e.key === 'k') {
e.preventDefault()
onTrigger()
}
}
document.addEventListener('keydown', handler)
return () => document.removeEventListener('keydown', handler)
}, [onTrigger, keys])
return null
}
// User shortcuts wrapper
function UserShortcutsWrapper() {
useUserShortcuts()
return null
}