import { useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { useAuthStore } from '@/features/auth/store/authStore'; import { useUIStore } from '@/stores/ui'; import { useTranslation } from '@/hooks/useTranslation'; import { EmailVerificationBadge } from '@/features/auth/components/EmailVerificationBadge'; import { NotificationMenu } from '@/components/notifications/NotificationMenu'; import { GlobalSearchBar } from '@/components/search/GlobalSearchBar'; import { Button } from '@/components/ui/button'; import { FocusTrap } from '@/components/ui/focus-trap'; import { Tooltip } from '@/components/ui/tooltip'; import { Menu, X, User, Settings, LogOut, Moon, Sun, Monitor, Search, } from 'lucide-react'; import type { BaseComponentProps } from '../types'; /** * Props for Header component * FE-TYPE-013: Fully typed component props */ export interface HeaderProps extends BaseComponentProps { // No additional props needed - uses global stores } export function Header({ className: _className }: HeaderProps = {}) { const [isUserMenuOpen, setIsUserMenuOpen] = useState(false); const [isMobileSearchOpen, setIsMobileSearchOpen] = useState(false); const { user, logout } = useAuthStore(); const { theme, setTheme, sidebarOpen, setSidebarOpen } = useUIStore(); const { t } = useTranslation(); const navigate = useNavigate(); const handleLogout = async () => { await logout(); navigate('/login'); }; const toggleTheme = () => { const newTheme = theme === 'light' ? 'dark' : theme === 'dark' ? 'system' : 'light'; setTheme(newTheme); }; const getThemeIcon = () => { switch (theme) { case 'light': return ; case 'dark': return ; default: return ; } }; return ( {/* Main header row */} {/* Logo et menu mobile */} setSidebarOpen(!sidebarOpen)} aria-label={ sidebarOpen ? t('navigation.close') : t('navigation.menu') } aria-expanded={sidebarOpen} > {sidebarOpen ? ( ) : ( )} V Veza {/* Barre de recherche (desktop) */} {/* Mobile search button */} setIsMobileSearchOpen(!isMobileSearchOpen)} aria-label={t('common.search')} aria-expanded={isMobileSearchOpen} > {/* Actions utilisateur */} {/* Notifications */} {/* Thème */} {getThemeIcon()} {/* Menu utilisateur */} setIsUserMenuOpen(!isUserMenuOpen)} aria-label={t('common.userMenu')} aria-expanded={isUserMenuOpen} aria-haspopup="menu" aria-controls="user-menu" // CRITIQUE FIX #67: Associer le bouton au menu > {isUserMenuOpen && ( setIsUserMenuOpen(false)} > {user?.username} {/* T0190: Afficher badge si email non vérifié */} {user && !user.is_verified && ( )} setIsUserMenuOpen(false)} role="menuitem" > {t('navigation.profile')} setIsUserMenuOpen(false)} role="menuitem" > {t('navigation.settings')} { handleLogout(); setIsUserMenuOpen(false); }} className="flex items-center w-full px-3 py-2 text-sm text-foreground hover:bg-accent rounded-sm focus:outline-none focus:ring-2 focus:ring-ring" role="menuitem" > {t('common.logout')} )} {/* Mobile search bar */} {isMobileSearchOpen && ( setIsMobileSearchOpen(false)} /> )} ); }