the-tip-top-frontend/components/Header.tsx

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>
);
}