2026-06-18 08:14:00 -04:00
|
|
|
import { useState, useRef, useEffect } from 'react'
|
2026-06-18 16:15:34 +00:00
|
|
|
import { useLocation } from 'react-router-dom'
|
2026-06-18 08:14:00 -04:00
|
|
|
import { Search, Bell, ChevronDown, User, Palette, LogOut, Shield, HelpCircle } from 'lucide-react'
|
|
|
|
|
|
2026-06-18 16:15:34 +00:00
|
|
|
const pageTitles: Record<string, string> = {
|
|
|
|
|
'/': 'Glance',
|
|
|
|
|
'/infrastructure': 'Infrastructure',
|
|
|
|
|
'/network': 'Network',
|
|
|
|
|
'/booknest': 'BookNest',
|
|
|
|
|
'/terminal': 'Terminal',
|
|
|
|
|
'/settings': 'Settings',
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-18 08:14:00 -04:00
|
|
|
export default function TopBar() {
|
|
|
|
|
const [userMenuOpen, setUserMenuOpen] = useState(false)
|
|
|
|
|
const menuRef = useRef<HTMLDivElement>(null)
|
2026-06-18 16:15:34 +00:00
|
|
|
const location = useLocation()
|
|
|
|
|
const title = pageTitles[location.pathname] ?? 'Glance'
|
2026-06-18 08:14:00 -04:00
|
|
|
|
|
|
|
|
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 (
|
|
|
|
|
<header className="h-14 flex items-center px-6 bg-page sticky top-0 z-40">
|
|
|
|
|
{/* Page Title — pushed away from sidebar edge */}
|
|
|
|
|
<h1 className="text-[18px] font-bold uppercase tracking-wide" style={{ color: '#C8A434', marginLeft: '20px' }}>
|
2026-06-18 16:15:34 +00:00
|
|
|
{title}
|
2026-06-18 08:14:00 -04:00
|
|
|
</h1>
|
|
|
|
|
|
|
|
|
|
{/* Center section — Search bar */}
|
|
|
|
|
<div className="flex-1 flex justify-center">
|
|
|
|
|
<div className="relative">
|
|
|
|
|
<Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2" style={{ color: '#7A7D85' }} />
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="Search resources..."
|
|
|
|
|
className="w-[300px] h-8 rounded-full bg-card 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' }}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Right section — Bell + Avatar, moved toward center (away from window edge) */}
|
|
|
|
|
<div className="flex items-center gap-4" style={{ marginRight: '40px' }}>
|
|
|
|
|
|
|
|
|
|
{/* Notifications */}
|
|
|
|
|
<button className="relative p-1.5 text-text-secondary hover:text-gold transition-colors bg-transparent border-none cursor-pointer">
|
|
|
|
|
<Bell size={17} />
|
|
|
|
|
<span className="absolute -top-0.5 -right-1 w-3.5 h-3.5 bg-danger rounded-full text-[8px] text-white flex items-center justify-center font-bold">
|
|
|
|
|
3
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
{/* User Avatar + Dropdown */}
|
|
|
|
|
<div className="relative" ref={menuRef}>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setUserMenuOpen(!userMenuOpen)}
|
|
|
|
|
className="flex items-center gap-2 bg-transparent border-none cursor-pointer p-0"
|
|
|
|
|
>
|
|
|
|
|
<div className="w-9 h-9 rounded-full border-2 border-gold bg-card flex items-center justify-center text-gold font-bold text-[12px] shadow-[0_0_8px_rgba(200,164,52,0.4)]">
|
|
|
|
|
AO
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col text-left">
|
|
|
|
|
<span className="text-[12px] text-text-primary font-medium leading-tight">ArchNest Ops</span>
|
|
|
|
|
<span className="text-[9px] text-text-secondary leading-tight">Administrator</span>
|
|
|
|
|
</div>
|
|
|
|
|
<ChevronDown size={12} className={`text-text-secondary transition-transform duration-200 ${userMenuOpen ? 'rotate-180' : ''}`} />
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
{userMenuOpen && (
|
|
|
|
|
<div className="absolute right-0 top-full mt-2 w-48 bg-card border border-border rounded-xl overflow-hidden shadow-lg z-50">
|
|
|
|
|
<div className="p-3 border-b border-border">
|
|
|
|
|
<p className="text-[12px] text-text-primary font-medium">ArchNest Ops</p>
|
|
|
|
|
<p className="text-[10px] text-text-secondary">admin@archnest.io</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="py-1">
|
|
|
|
|
<a href="#" className="flex items-center gap-2.5 px-3 py-2 text-[12px] text-text-secondary hover:text-text-primary hover:bg-page transition-colors no-underline">
|
|
|
|
|
<User size={14} />
|
|
|
|
|
<span>Profile</span>
|
|
|
|
|
</a>
|
|
|
|
|
<a href="#" className="flex items-center gap-2.5 px-3 py-2 text-[12px] text-text-secondary hover:text-text-primary hover:bg-page transition-colors no-underline">
|
|
|
|
|
<Palette size={14} />
|
|
|
|
|
<span>Appearance</span>
|
|
|
|
|
</a>
|
|
|
|
|
<a href="#" className="flex items-center gap-2.5 px-3 py-2 text-[12px] text-text-secondary hover:text-text-primary hover:bg-page transition-colors no-underline">
|
|
|
|
|
<Shield size={14} />
|
|
|
|
|
<span>Security</span>
|
|
|
|
|
</a>
|
|
|
|
|
<a href="#" className="flex items-center gap-2.5 px-3 py-2 text-[12px] text-text-secondary hover:text-text-primary hover:bg-page transition-colors no-underline">
|
|
|
|
|
<HelpCircle size={14} />
|
|
|
|
|
<span>Help & Support</span>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="border-t border-border py-1">
|
|
|
|
|
<a href="#" className="flex items-center gap-2.5 px-3 py-2 text-[12px] text-danger hover:bg-page transition-colors no-underline">
|
|
|
|
|
<LogOut size={14} />
|
|
|
|
|
<span>Sign Out</span>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
)
|
|
|
|
|
}
|