349 lines
15 KiB
TypeScript
349 lines
15 KiB
TypeScript
'use client';
|
|
|
|
import Link from 'next/link';
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
import Button from './Button';
|
|
import Logo from './Logo';
|
|
import { ROUTES } from '@/utils/constants';
|
|
import { useState, useRef, useEffect } from 'react';
|
|
|
|
export default function Header() {
|
|
const { user, isAuthenticated, logout } = useAuth();
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
const [isParticiperDropdownOpen, setIsParticiperDropdownOpen] = useState(false);
|
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
|
|
const toggleMobileMenu = () => {
|
|
setIsMobileMenuOpen(!isMobileMenuOpen);
|
|
};
|
|
|
|
// Close dropdown when clicking outside
|
|
useEffect(() => {
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
|
setIsParticiperDropdownOpen(false);
|
|
}
|
|
};
|
|
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
return () => {
|
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
};
|
|
}, []);
|
|
|
|
const getDashboardRoute = () => {
|
|
if (!user) return ROUTES.HOME;
|
|
switch (user.role) {
|
|
case 'ADMIN':
|
|
return ROUTES.ADMIN_DASHBOARD;
|
|
case 'EMPLOYEE':
|
|
return ROUTES.EMPLOYEE_DASHBOARD;
|
|
default:
|
|
return ROUTES.CLIENT_DASHBOARD;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<header className="bg-gradient-to-r from-[#f5f5f0] to-[#faf9f5] sticky top-0 z-50 shadow-lg border-b-2 border-[#e5e4dc]">
|
|
{/* Main Header */}
|
|
<div className="container mx-auto px-4">
|
|
<div className="flex items-center justify-between h-18">
|
|
{/* Logo */}
|
|
<Link href={ROUTES.HOME} className="group flex items-center gap-3">
|
|
<Logo size="md" showText={false} className="group-hover:scale-105 transition-transform" />
|
|
</Link>
|
|
|
|
{/* Desktop Navigation */}
|
|
<nav className="hidden md:flex items-center gap-6">
|
|
<Link
|
|
href={ROUTES.HOME}
|
|
className="text-[#5a5a4e] hover:text-[#d4a574] font-medium transition-colors"
|
|
>
|
|
Accueil
|
|
</Link>
|
|
<Link
|
|
href={ROUTES.LOTS}
|
|
className="text-[#5a5a4e] hover:text-[#d4a574] font-medium transition-colors"
|
|
>
|
|
Lots à gagner
|
|
</Link>
|
|
<Link
|
|
href="/rules"
|
|
className="text-[#5a5a4e] hover:text-[#d4a574] font-medium transition-colors"
|
|
>
|
|
Règlement
|
|
</Link>
|
|
<Link
|
|
href="/faq"
|
|
className="text-[#5a5a4e] hover:text-[#d4a574] font-medium transition-colors"
|
|
>
|
|
FAQ
|
|
</Link>
|
|
<Link
|
|
href="/contact"
|
|
className="text-[#5a5a4e] hover:text-[#d4a574] font-medium transition-colors"
|
|
>
|
|
Contact
|
|
</Link>
|
|
|
|
{/* Participer with Dropdown - Doré Button */}
|
|
{isAuthenticated ? (
|
|
<Link
|
|
href={ROUTES.GAME}
|
|
className="bg-gradient-to-r from-[#d4a574] to-[#c4956a] hover:from-[#e5b685] hover:to-[#d4a574] text-white font-bold px-6 py-2 rounded-lg transition-all duration-300 hover:shadow-[0_0_20px_rgba(212,165,116,0.6)] hover:scale-105 shadow-lg"
|
|
>
|
|
Participer
|
|
</Link>
|
|
) : (
|
|
<div className="relative" ref={dropdownRef}>
|
|
<button
|
|
onClick={() => setIsParticiperDropdownOpen(!isParticiperDropdownOpen)}
|
|
className="bg-gradient-to-r from-[#d4a574] to-[#c4956a] hover:from-[#e5b685] hover:to-[#d4a574] text-white font-bold px-6 py-2 rounded-lg transition-all duration-300 hover:shadow-[0_0_20px_rgba(212,165,116,0.6)] hover:scale-105 shadow-lg flex items-center gap-2"
|
|
>
|
|
Participer
|
|
<svg
|
|
className={`w-4 h-4 transition-transform duration-300 ${isParticiperDropdownOpen ? 'rotate-180' : ''}`}
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
</svg>
|
|
</button>
|
|
|
|
{isParticiperDropdownOpen && (
|
|
<div className="absolute right-0 mt-2 w-56 bg-white rounded-xl shadow-2xl border-2 border-[#d4a574]/30 py-2 z-50 animate-fadeIn overflow-hidden">
|
|
<Link
|
|
href={ROUTES.LOGIN}
|
|
onClick={() => setIsParticiperDropdownOpen(false)}
|
|
className="block px-4 py-3 text-gray-700 hover:bg-gradient-to-r hover:from-[#d4a574]/10 hover:to-[#c4956a]/10 hover:text-[#c4956a] transition-all duration-300 hover:pl-6 hover:shadow-inner"
|
|
>
|
|
<span className="font-bold block">Connexion</span>
|
|
<p className="text-xs text-gray-500 mt-0.5">J'ai déjà un compte</p>
|
|
</Link>
|
|
<div className="border-t border-[#d4a574]/20 my-1"></div>
|
|
<Link
|
|
href={ROUTES.REGISTER}
|
|
onClick={() => setIsParticiperDropdownOpen(false)}
|
|
className="block px-4 py-3 text-gray-700 hover:bg-gradient-to-r hover:from-[#d4a574]/10 hover:to-[#c4956a]/10 hover:text-[#c4956a] transition-all duration-300 hover:pl-6 hover:shadow-inner"
|
|
>
|
|
<span className="font-bold block">Inscription</span>
|
|
<p className="text-xs text-gray-500 mt-0.5">Créer un nouveau compte</p>
|
|
</Link>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</nav>
|
|
|
|
{/* Desktop Auth Buttons */}
|
|
<div className="hidden md:flex items-center gap-3">
|
|
{isAuthenticated && (
|
|
<>
|
|
<Link href={getDashboardRoute()}>
|
|
<button className="flex flex-col items-center bg-white text-[#5a5a4e] hover:bg-[#d4a574] hover:text-white font-semibold px-4 py-2 rounded-lg transition-all border border-[#e5e4dc]">
|
|
<span className="text-sm">{user?.firstName} {user?.lastName}</span>
|
|
<span className="text-xs font-normal opacity-80">{user?.email}</span>
|
|
</button>
|
|
</Link>
|
|
<Link href={ROUTES.PROFILE}>
|
|
<button className="flex items-center gap-2 bg-white text-[#5a5a4e] hover:bg-[#d4a574] hover:text-white font-semibold px-4 py-2 rounded-lg transition-all border border-[#e5e4dc]">
|
|
Profil
|
|
</button>
|
|
</Link>
|
|
{user?.role === 'CLIENT' && (
|
|
<Link href={ROUTES.HISTORY}>
|
|
<button className="flex items-center gap-2 bg-white text-[#5a5a4e] hover:bg-[#d4a574] hover:text-white font-semibold px-4 py-2 rounded-lg transition-all border border-[#e5e4dc]">
|
|
Mes gains
|
|
</button>
|
|
</Link>
|
|
)}
|
|
<button
|
|
onClick={logout}
|
|
className="flex items-center gap-2 bg-white text-[#5a5a4e] hover:bg-red-600 hover:text-white font-semibold px-4 py-2 rounded-lg transition-all border border-[#e5e4dc]"
|
|
>
|
|
Déconnexion
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
{/* Mobile Menu Button */}
|
|
<button
|
|
onClick={toggleMobileMenu}
|
|
className="md:hidden p-2 text-[#5a5a4e] hover:text-[#d4a574] focus:outline-none"
|
|
aria-label="Toggle menu"
|
|
>
|
|
{isMobileMenuOpen ? (
|
|
<svg
|
|
className="w-6 h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M6 18L18 6M6 6l12 12"
|
|
/>
|
|
</svg>
|
|
) : (
|
|
<svg
|
|
className="w-6 h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M4 6h16M4 12h16M4 18h16"
|
|
/>
|
|
</svg>
|
|
)}
|
|
</button>
|
|
</div>
|
|
|
|
{/* Mobile Menu */}
|
|
{isMobileMenuOpen && (
|
|
<div className="md:hidden py-4 border-t border-gray-200 animate-fadeIn">
|
|
<nav className="flex flex-col gap-3">
|
|
<Link
|
|
href={ROUTES.HOME}
|
|
className="text-gray-700 hover:text-primary-600 font-medium py-2 transition-colors"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
Accueil
|
|
</Link>
|
|
<Link
|
|
href={ROUTES.GAME}
|
|
className="text-gray-700 hover:text-primary-600 font-medium py-2 transition-colors"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
Jeu
|
|
</Link>
|
|
<Link
|
|
href={ROUTES.LOTS}
|
|
className="text-gray-700 hover:text-primary-600 font-medium py-2 transition-colors"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
Lots
|
|
</Link>
|
|
<Link
|
|
href="/about"
|
|
className="text-gray-700 hover:text-primary-600 font-medium py-2 transition-colors"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
À propos
|
|
</Link>
|
|
<Link
|
|
href="/contact"
|
|
className="text-gray-700 hover:text-primary-600 font-medium py-2 transition-colors"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
Contact
|
|
</Link>
|
|
|
|
{/* Participer Mobile - Green Button */}
|
|
{isAuthenticated ? (
|
|
<Link
|
|
href={ROUTES.GAME}
|
|
className="bg-green-600 hover:bg-green-700 text-white font-semibold px-4 py-3 rounded-lg transition-all hover:shadow-lg text-center block"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
🎯 Participer
|
|
</Link>
|
|
) : (
|
|
<div>
|
|
<button
|
|
onClick={() => setIsParticiperDropdownOpen(!isParticiperDropdownOpen)}
|
|
className="bg-green-600 hover:bg-green-700 text-white font-semibold px-4 py-3 rounded-lg transition-all hover:shadow-lg flex items-center justify-center gap-2 w-full"
|
|
>
|
|
🎯 Participer
|
|
<svg
|
|
className={`w-4 h-4 transition-transform ${isParticiperDropdownOpen ? 'rotate-180' : ''}`}
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
</svg>
|
|
</button>
|
|
|
|
{isParticiperDropdownOpen && (
|
|
<div className="mt-2 space-y-2 animate-fadeIn bg-green-50 rounded-lg p-3">
|
|
<Link
|
|
href={ROUTES.LOGIN}
|
|
onClick={() => {
|
|
setIsMobileMenuOpen(false);
|
|
setIsParticiperDropdownOpen(false);
|
|
}}
|
|
className="block text-green-800 hover:text-green-900 font-medium py-2 px-3 bg-white rounded-md hover:bg-green-100 transition-colors"
|
|
>
|
|
→ Connexion
|
|
</Link>
|
|
<Link
|
|
href={ROUTES.REGISTER}
|
|
onClick={() => {
|
|
setIsMobileMenuOpen(false);
|
|
setIsParticiperDropdownOpen(false);
|
|
}}
|
|
className="block text-green-800 hover:text-green-900 font-medium py-2 px-3 bg-white rounded-md hover:bg-green-100 transition-colors"
|
|
>
|
|
→ Inscription
|
|
</Link>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{isAuthenticated && (
|
|
<div className="border-t border-white/20 pt-3 mt-3 space-y-2">
|
|
<Link
|
|
href={getDashboardRoute()}
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
<button className="w-full flex flex-col items-center bg-white text-[#1a4d2e] hover:bg-[#f59e0b] hover:text-white font-semibold px-4 py-3 rounded-lg transition-all">
|
|
<span className="text-sm">{user?.firstName} {user?.lastName}</span>
|
|
<span className="text-xs font-normal opacity-80">{user?.email}</span>
|
|
</button>
|
|
</Link>
|
|
<Link
|
|
href={ROUTES.PROFILE}
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
<button className="w-full flex items-center justify-center gap-2 bg-white text-[#1a4d2e] hover:bg-[#f59e0b] hover:text-white font-semibold px-4 py-3 rounded-lg transition-all">
|
|
Profil
|
|
</button>
|
|
</Link>
|
|
{user?.role === 'CLIENT' && (
|
|
<Link
|
|
href={ROUTES.HISTORY}
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
<button className="w-full flex items-center justify-center gap-2 bg-white text-[#1a4d2e] hover:bg-[#f59e0b] hover:text-white font-semibold px-4 py-3 rounded-lg transition-all">
|
|
Mes gains
|
|
</button>
|
|
</Link>
|
|
)}
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
setIsMobileMenuOpen(false);
|
|
}}
|
|
className="w-full flex items-center justify-center gap-2 bg-white text-[#1a4d2e] hover:bg-red-600 hover:text-white font-semibold px-4 py-3 rounded-lg transition-all"
|
|
>
|
|
Déconnexion
|
|
</button>
|
|
</div>
|
|
)}
|
|
</nav>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|