import React, { useState, useRef, useEffect } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { Hotel, User, LogOut, LogIn, UserPlus, Heart, Phone, Mail, Calendar, Star, Users, AlertCircle, Bell, Shield, } from 'lucide-react'; import { useClickOutside } from '../hooks/useClickOutside'; import { useCompanySettings } from '../contexts/CompanySettingsContext'; import { useTheme } from '../contexts/ThemeContext'; import { useAuthModal } from '../../features/auth/contexts/AuthModalContext'; import { normalizeImageUrl } from '../utils/imageUtils'; import InAppNotificationBell from '../../features/notifications/components/InAppNotificationBell'; import Navbar from './Navbar'; import { getThemeTextClasses } from '../utils/themeUtils'; interface HeaderProps { isAuthenticated?: boolean; userInfo?: { name: string; email: string; avatar?: string; role: string; } | null; onLogout?: () => void; } const Header: React.FC = ({ isAuthenticated = false, userInfo = null, onLogout }) => { const { settings } = useCompanySettings(); const { theme } = useTheme(); const { openModal } = useAuthModal(); const location = useLocation(); const textClasses = getThemeTextClasses(theme.theme_layout_mode); const displayPhone = settings.company_phone || null; const displayEmail = settings.company_email || null; const logoUrl = settings.company_logo_url ? (settings.company_logo_url.startsWith('http') ? settings.company_logo_url : `${import.meta.env.VITE_API_URL || 'http://localhost:8000'}${settings.company_logo_url}`) : null; const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isUserMenuOpen, setIsUserMenuOpen] = useState(false); const userMenuRef = useRef(null); // Track previous pathname to detect actual navigation const prevPathnameRef = useRef(location.pathname); // Close menu when navigation happens useEffect(() => { const prevPathname = prevPathnameRef.current; const currentPathname = location.pathname; // Only close menu if it's an actual navigation (pathname changed) if (prevPathname !== currentPathname && isMobileMenuOpen) { setIsMobileMenuOpen(false); } // Update ref for next comparison prevPathnameRef.current = currentPathname; }, [location.pathname, isMobileMenuOpen]); useClickOutside(userMenuRef, () => { if (isUserMenuOpen) { setIsUserMenuOpen(false); } }); const toggleMobileMenu = () => { setIsMobileMenuOpen(!isMobileMenuOpen); }; const toggleUserMenu = () => { setIsUserMenuOpen(!isUserMenuOpen); }; const handleLogout = () => { if (onLogout) { onLogout(); } setIsUserMenuOpen(false); setIsMobileMenuOpen(false); }; // Mobile menu content with user authentication const mobileMenuContent = ( <> {!isAuthenticated ? ( <> ) : ( <>
Hello, {userInfo?.name}
{ e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className="flex items-center space-x-2 px-4 py-3.5 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.15)] hover:text-[var(--luxury-gold)] rounded-md transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wider text-sm group relative mx-2" style={{ touchAction: 'manipulation' }} > Profile {userInfo?.role !== 'admin' && userInfo?.role !== 'staff' && userInfo?.role !== 'accountant' && userInfo?.role !== 'housekeeping' && ( <> { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Dashboard { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Favorites { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > My Bookings { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Loyalty Program { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Group Bookings { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Complaints { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Guest Requests { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Privacy & Data )} {userInfo?.role === 'admin' && ( { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Admin )} {userInfo?.role === 'staff' && ( { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Staff Dashboard )} {userInfo?.role === 'accountant' && ( { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Accountant Dashboard )} {userInfo?.role === 'housekeeping' && ( { e.stopPropagation(); setTimeout(() => setIsMobileMenuOpen(false), 100); }} onTouchStart={(e) => { e.stopPropagation(); }} className={`flex items-center space-x-2 px-4 py-3 ${textClasses.primary}/90 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] rounded-sm transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] font-light tracking-wide`} style={{ touchAction: 'manipulation' }} > Housekeeping Dashboard )}
)} ); return (
{displayPhone && ( {displayPhone} )} {displayEmail && ( {displayEmail} )}
{/* Logo - Left - Always visible on all screens, flush with left edge */}
{logoUrl ? (
{settings.company_name}
) : (
)}
{settings.company_name} {settings.company_tagline || 'Excellence Redefined'}
{/* Navigation Links - Center */}
setIsMobileMenuOpen(false)} mobileMenuContent={mobileMenuContent} />
{/* Mobile Menu Button - Right (for smaller screens) */}
setIsMobileMenuOpen(false)} mobileMenuContent={mobileMenuContent} />
{/* Login/Register - Right */}
{!isAuthenticated ? ( <> ) : (
{isAuthenticated && }
{isUserMenuOpen && (
setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Profile {userInfo?.role !== 'admin' && userInfo?.role !== 'staff' && userInfo?.role !== 'accountant' && userInfo?.role !== 'housekeeping' && ( <> setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Dashboard setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Favorites setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > My Bookings setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Loyalty Program setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Group Bookings setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Complaints setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Guest Requests setIsUserMenuOpen(false)} className="flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative" > Privacy & Data )} {userInfo?.role === 'admin' && ( setIsUserMenuOpen(false) } className={`flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative`} > Admin )} {userInfo?.role === 'staff' && ( setIsUserMenuOpen(false) } className={`flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative`} > Staff Dashboard )} {userInfo?.role === 'accountant' && ( setIsUserMenuOpen(false) } className={`flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative`} > Accountant Dashboard )} {userInfo?.role === 'housekeeping' && ( setIsUserMenuOpen(false) } className={`flex items-center space-x-3 px-5 py-3 ${textClasses.primary}/95 hover:bg-[rgba(var(--luxury-gold-rgb),0.1)] hover:text-[var(--luxury-gold)] transition-all duration-300 border-l-2 border-transparent hover:border-[var(--luxury-gold)] rounded-md group relative`} > Housekeeping Dashboard )}
)}
)}
); }; export default Header;