import { useState, useRef, useEffect } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { Menu, ChevronDown, Command, Bell, LogOut, Search, Settings, } from 'lucide-react'; import { usePermissions } from '../../hooks/usePermissions'; import { getFilteredNavSections, type NavSection } from '../../lib/navigation'; import { useAuth } from '../../context/AuthContext'; import ThemeToggle from '../ThemeToggle'; import { cn } from '../../lib/utils'; interface NavbarProps { onOpenMobileMenu?: () => void; } export function Navbar({ onOpenMobileMenu }: NavbarProps) { const { role } = usePermissions(); const sections = getFilteredNavSections(role); const location = useLocation(); const [scrolled, setScrolled] = useState(false); useEffect(() => { const handleScroll = () => setScrolled(window.scrollY > 20); window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, []); return ( {/* Left: Branding & Navigation */} Veridian Cultivation Platform {/* Desktop Navigation */} {sections.map(section => ( ))} {/* Right: Actions */} {/* Search Mock */} dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }))} className="hidden md:flex items-center gap-3 px-4 py-2 text-xs font-bold text-slate-500 bg-slate-100/50 hover:bg-white dark:bg-slate-900/50 dark:hover:bg-slate-800 transition-all rounded-full border border-slate-200/50 dark:border-slate-800 group" > Search... ⌘K ); } function UserDropdown() { const { user, logout } = useAuth(); const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); return ( setIsOpen(!isOpen)} className="flex items-center gap-2 p-1 rounded-full hover:bg-slate-100 dark:hover:bg-slate-900 transition-colors" > {user?.email?.[0]?.toUpperCase() || 'E'} {isOpen && ( Authenticated {user?.name || 'Administrator'} {user?.email} setIsOpen(false)} className="flex items-center gap-3 px-3 py-2.5 text-xs font-bold uppercase tracking-widest text-slate-600 hover:text-indigo-600 hover:bg-indigo-50 dark:text-slate-400 dark:hover:text-indigo-400 dark:hover:bg-indigo-500/10 rounded-xl transition-all" > Settings { setIsOpen(false); logout(); }} className="w-full flex items-center gap-3 px-3 py-2.5 text-xs font-bold uppercase tracking-widest text-rose-600 hover:bg-rose-50 dark:hover:bg-rose-950/20 rounded-xl transition-all" > Sign Out )} ); } function NavDropdown({ section, currentPath }: { section: NavSection, currentPath: string }) { const [isOpen, setIsOpen] = useState(false); const timeoutRef = useRef(null); const isActive = section.items.some(item => item.path === currentPath); return ( { if (timeoutRef.current) clearTimeout(timeoutRef.current); setIsOpen(true); }} onMouseLeave={() => { timeoutRef.current = setTimeout(() => setIsOpen(false), 150); }} > {section.label} {isOpen && ( {section.label} {section.items.map(item => ( {item.label} {item.path === currentPath && ( )} ))} )} ); } export default Navbar;
Cultivation Platform
Authenticated
{user?.name || 'Administrator'}
{user?.email}
{section.label}