import { useState, useRef, useEffect, useMemo } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import { Search, Bell, ChevronDown, User, Palette, LogOut, Shield, HelpCircle, Server, Bookmark as BookmarkIcon, LayoutGrid } from 'lucide-react' import { useAuth } from '../lib/AuthContext' import { api } from '../lib/api' const pageTitles: Record = { '/': 'Glance', '/infrastructure': 'Infrastructure', '/booknest': 'BookNest', '/terminal': 'Terminal', '/tunnels': 'Tunnels', '/files': 'Files', '/containers': 'Containers', '/remote-desktop': 'Remote Desktop', '/host-metrics': 'Host Metrics', '/settings': 'Settings', '/help': 'Help', } const pageSubtitles: Record = { '/booknest': 'Your Digital Library', } const staticPages: { name: string; path: string }[] = [ { name: 'Glance', path: '/' }, { name: 'Infrastructure', path: '/infrastructure' }, { name: 'BookNest', path: '/booknest' }, { name: 'Terminal', path: '/terminal' }, { name: 'Tunnels', path: '/tunnels' }, { name: 'Files', path: '/files' }, { name: 'Containers', path: '/containers' }, { name: 'Remote Desktop', path: '/remote-desktop' }, { name: 'Host Metrics', path: '/host-metrics' }, { name: 'Settings', path: '/settings' }, { name: 'Help', path: '/help' }, ] type SearchResult = | { kind: 'page'; key: string; label: string; sublabel?: string; path: string } | { kind: 'integration'; key: string; label: string; sublabel?: string; path: string } | { kind: 'bookmark'; key: string; label: string; sublabel?: string; path: string } export default function TopBar() { const { logout, user } = useAuth() const [userMenuOpen, setUserMenuOpen] = useState(false) const menuRef = useRef(null) const location = useLocation() const navigate = useNavigate() const title = pageTitles[location.pathname] ?? 'Glance' const subtitle = pageSubtitles[location.pathname] const [query, setQuery] = useState('') const [searchOpen, setSearchOpen] = useState(false) const [integrations, setIntegrations] = useState<{ id: number; name: string; type: string }[]>([]) const [bookmarks, setBookmarks] = useState<{ id: number; title: string; url: string }[]>([]) const searchRef = useRef(null) useEffect(() => { api.listIntegrations().then(({ integrations }) => setIntegrations(integrations)).catch(() => {}) api.listBookmarks().then(({ bookmarks }) => setBookmarks(bookmarks)).catch(() => {}) }, []) useEffect(() => { function handleClick(e: MouseEvent) { if (searchRef.current && !searchRef.current.contains(e.target as Node)) { setSearchOpen(false) } } document.addEventListener('mousedown', handleClick) return () => document.removeEventListener('mousedown', handleClick) }, []) const results = useMemo(() => { const q = query.trim().toLowerCase() if (!q) return [] const pageMatches: SearchResult[] = staticPages .filter((p) => p.name.toLowerCase().includes(q)) .map((p) => ({ kind: 'page', key: `page-${p.path}`, label: p.name, path: p.path })) const integrationMatches: SearchResult[] = integrations .filter((i) => i.name.toLowerCase().includes(q) || i.type.toLowerCase().includes(q)) .map((i) => ({ kind: 'integration', key: `int-${i.id}`, label: i.name, sublabel: i.type, path: '/infrastructure' })) const bookmarkMatches: SearchResult[] = bookmarks .filter((b) => b.title.toLowerCase().includes(q) || b.url.toLowerCase().includes(q)) .map((b) => ({ kind: 'bookmark', key: `bm-${b.id}`, label: b.title, sublabel: b.url, path: '/booknest' })) return [...pageMatches, ...integrationMatches, ...bookmarkMatches].slice(0, 8) }, [query, integrations, bookmarks]) function handleSelectResult(r: SearchResult) { navigate(r.path) setQuery('') setSearchOpen(false) } const displayName = user?.display_name || user?.username || '' const initials = displayName .split(/\s+/) .map((p) => p[0]) .join('') .slice(0, 2) .toUpperCase() useEffect(() => { function handleClick(e: MouseEvent) { if (menuRef.current && !menuRef.current.contains(e.target as Node)) { setUserMenuOpen(false) } } document.addEventListener('mousedown', handleClick) return () => document.removeEventListener('mousedown', handleClick) }, []) return (
{/* Page Title — pushed away from sidebar edge */}

{title}

{subtitle && (

{subtitle}

)}
{/* Center section — Search bar */}
{ setQuery(e.target.value) setSearchOpen(true) }} onFocus={() => setSearchOpen(true)} onKeyDown={(e) => { if (e.key === 'Enter' && results.length > 0) { handleSelectResult(results[0]) } else if (e.key === 'Escape') { setSearchOpen(false) } }} className="w-[300px] h-8 rounded-full border border-border text-[12px] text-text-primary placeholder:text-text-secondary focus:outline-none focus:border-gold transition-colors" style={{ paddingLeft: '36px', paddingRight: '16px', backgroundColor: 'rgba(255,255,255,0.04)', backdropFilter: 'blur(6px)' }} /> {searchOpen && query.trim() && (
{results.length === 0 ? (
No matches for "{query}"
) : (
{results.map((r) => ( ))}
)}
)}
{/* Right section — Bell + Avatar, moved toward center (away from window edge) */}
{/* Notifications */} {/* User Avatar + Dropdown */}
{userMenuOpen && (

{displayName}

{user?.email || user?.username}

Profile Appearance Security
)}
) }