-
+ +
{/* Global Breadcrumbs - appears on all pages */} diff --git a/frontend/src/components/aura/Navbar.tsx b/frontend/src/components/aura/Navbar.tsx new file mode 100644 index 0000000..c362c96 --- /dev/null +++ b/frontend/src/components/aura/Navbar.tsx @@ -0,0 +1,280 @@ +import { useState, useRef, useEffect } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { motion, AnimatePresence } from 'framer-motion'; +import { + Menu, + X, + Search, + ChevronDown, + Command, + Bell, + LogOut, + User, + 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'; + +interface NavbarProps { + onOpenMobileMenu?: () => void; +} + +export function Navbar({ onOpenMobileMenu }: NavbarProps) { + const { role } = usePermissions(); + const sections = getFilteredNavSections(role); + const location = useLocation(); + const [scrolled, setScrolled] = useState(false); + + // Handle scroll effect + useEffect(() => { + const handleScroll = () => { + setScrolled(window.scrollY > 20); + }; + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + + return ( +
+
+
+ {/* Left: Logo & Desktop Nav */} +
+ {/* Logo */} + +
+ 777 Wolfpack +
+
+
+

+ 777 Wolfpack +

+

+ Operations +

+
+ + + {/* Desktop Navigation - Sections Dropdowns */} + +
+ + {/* Right: Actions */} +
+ {/* Global Search Trigger */} + + +
+ + + + + +
+ +
+ + {/* Mobile Menu Button */} + +
+
+
+
+ ); +} + +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 ( +
+ + + + {isOpen && ( + +
+

+ {user?.name || 'User'} +

+

+ {user?.email} +

+
+ + setIsOpen(false)} + className="flex items-center gap-2 px-3 py-2 text-sm text-slate-600 hover:text-slate-900 hover:bg-slate-50 rounded-lg dark:text-slate-400 dark:hover:text-white dark:hover:bg-slate-800" + > + + Settings + + + +
+ )} +
+
+ ); +} + +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); + + const handleMouseEnter = () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + setIsOpen(true); + }; + + const handleMouseLeave = () => { + timeoutRef.current = setTimeout(() => setIsOpen(false), 200); + }; + + return ( +
+ + + + {isOpen && ( + +
+ {section.items.map(item => ( + +
+ +
+
+
{item.label}
+ {/* Optional Description if we had it */} +
+ {item.path === currentPath && ( +
+ )} + + ))} +
+ + )} + +
+ ); +} + +export default Navbar;