Files
roxane/resources/js/layouts/nav-guest-layout.tsx

211 lines
11 KiB
TypeScript
Raw Normal View History

2026-03-28 17:35:28 +01:00
import { useEffect, useState } from 'react';
import { Link, router, usePage } from '@inertiajs/react';
import { dashboard, home, login, logout, contact, membership } from '@/routes';
import AppLogoIcon from '@/components/app-logo-icon';
import { Button } from '@/components/ui/button';
import { type SharedData } from '@/types';
import { useMobileNavigation } from '@/hooks/use-mobile-navigation';
import { useAppearance } from '@/hooks/use-appearance';
import { Menu, Moon, Sun, X } from 'lucide-react';
import AppLogo from "@/components/app-logo";
2025-10-22 17:09:48 +02:00
export default function NavGuestLayout() {
2026-03-28 17:35:28 +01:00
const { auth } = usePage<SharedData>().props;
2025-10-22 17:09:48 +02:00
const cleanup = useMobileNavigation();
2026-03-28 17:35:28 +01:00
const { appearance, updateAppearance } = useAppearance();
const [isMenuOpen, setIsMenuOpen] = useState(false);
2025-10-22 17:09:48 +02:00
const handleLogout = () => {
cleanup();
router.flushAll();
};
2026-03-28 17:35:28 +01:00
const toggleAppearance = () => {
updateAppearance(appearance === 'dark' ? 'light' : 'dark');
};
const closeMenu = () => setIsMenuOpen(false);
// Fermer sur navigation Inertia
useEffect(() => {
return router.on('navigate', closeMenu);
}, []);
// Fermer sur touche Escape
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') closeMenu();
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
2026-02-16 17:22:01 +01:00
2026-03-28 17:35:28 +01:00
// Bloquer le scroll quand menu ouvert
2026-02-16 17:22:01 +01:00
useEffect(() => {
2026-03-28 17:35:28 +01:00
document.body.style.overflow = isMenuOpen ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [isMenuOpen]);
2026-02-16 17:22:01 +01:00
2025-10-22 17:09:48 +02:00
return (
<>
2026-03-28 17:35:28 +01:00
<header className="flex justify-between items-center my-6 w-full max-w-[335px] lg:max-w-7xl text-sm">
{/* Logo */}
<Link href={home()} className="flex items-center gap-2 font-medium no-underline text-foreground">
2026-03-28 17:35:28 +01:00
<div className="flex items-center justify-center rounded-md">
<AppLogo className="max-w-[200px] max-h-[42px] w-full h-auto" />
</div>
{/*@todo: gérer l'accessibilité de l'image'*/}
{/*<span className="font-bold text-black dark:text-white">Le Retzien Libre</span>*/}
</Link>
{/* Navigation desktop */}
<nav className="hidden lg:flex items-center gap-1">
<Link href={home()} className="px-5 py-1.5 text-lg text-[#1b1b18] dark:text-[#EDEDEC] no-underline hover:underline">
2025-10-22 17:09:48 +02:00
Accueil
</Link>
2026-03-28 17:35:28 +01:00
<Link href="#services" className="px-5 py-1.5 text-lg text-[#1b1b18] dark:text-[#EDEDEC] no-underline hover:underline">
2025-10-22 17:09:48 +02:00
Nos Services
</Link>
2026-03-28 17:35:28 +01:00
<Link href="#" className="px-5 py-1.5 text-lg text-[#1b1b18] dark:text-[#EDEDEC] no-underline hover:underline">
2025-10-22 17:09:48 +02:00
Le Blog
</Link>
2026-03-28 17:35:28 +01:00
<Link href={contact()} className="px-5 py-1.5 text-lg text-[#1b1b18] dark:text-[#EDEDEC] no-underline hover:underline">
2025-10-22 17:09:48 +02:00
Contact
</Link>
</nav>
2026-03-28 17:35:28 +01:00
{/* Actions desktop */}
<div className="hidden lg:flex items-center gap-3">
2025-10-22 17:09:48 +02:00
{auth.user ? (
<>
<Link href={dashboard()} className="no-underline text-foreground">
2025-10-22 17:09:48 +02:00
<Button variant="outline">Tableau de bord</Button>
</Link>
<Link
href={logout()}
onClick={handleLogout}
className="nb-shadow bg-secondary text-secondary-foreground hover:bg-secondary/80 h-10 px-4 py-2 font-bold no-underline"
2025-10-22 17:09:48 +02:00
data-test="logout-button"
>
2025-10-24 14:38:11 +02:00
Se déconnecter
2025-10-22 17:09:48 +02:00
</Link>
</>
) : (
<>
2026-03-28 17:35:28 +01:00
<Link href={login()} className="no-underline">
2025-10-22 17:09:48 +02:00
<Button variant="outline">Se connecter</Button>
</Link>
2026-03-28 17:35:28 +01:00
<Link href={membership()} className="no-underline">
2026-03-30 18:50:04 +02:00
<Button variant="secondary">Adhérer</Button>
2025-10-22 17:09:48 +02:00
</Link>
</>
)}
2026-03-28 17:35:28 +01:00
<button
onClick={toggleAppearance}
className="nb-shadow bg-primary text-secondary-foreground hover:bg-primary/80 h-10 px-4 py-2 font-bold no-underline"
2026-03-28 17:35:28 +01:00
aria-label="Changer le thème"
>
{appearance === 'dark' ? <Sun className="size-4" /> : <Moon className="size-4" />}
</button>
</div>
{/* Actions mobile : thème + hamburger */}
<div className="flex lg:hidden items-center gap-2">
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="nb-shadow bg-secondary text-secondary-foreground hover:bg-secondary/80 h-10 px-4 py-2 font-bold no-underline"
2026-03-28 17:35:28 +01:00
aria-label={isMenuOpen ? 'Fermer le menu' : 'Ouvrir le menu'}
aria-expanded={isMenuOpen}
>
{isMenuOpen ? <X className="size-5" /> : <Menu className="size-5" />}
</button>
<button
onClick={toggleAppearance}
className="nb-shadow bg-primary text-secondary-foreground hover:bg-primary/80 h-10 px-4 py-2 font-bold no-underline"
2026-03-28 17:35:28 +01:00
aria-label="Changer le thème"
>
{appearance === 'dark' ? <Sun className="size-4" /> : <Moon className="size-4" />}
</button>
</div>
2025-10-22 17:09:48 +02:00
</header>
2026-03-28 17:35:28 +01:00
{/* Menu mobile */}
{isMenuOpen && (
<>
{/* Backdrop */}
<div
className="fixed inset-0 z-40 bg-black/30 lg:hidden"
onClick={closeMenu}
aria-hidden="true"
/>
{/* Panel */}
<div className="fixed inset-x-0 top-0 z-50 lg:hidden bg-[#F5F5F5] dark:bg-[#0a0a0a] border-b-4 border-black flex flex-col gap-6 p-6">
{/* En-tête du panel */}
<div className="flex justify-between items-center">
<Link href={home()} onClick={closeMenu} className="flex items-center gap-2 no-underline">
<AppLogoIcon className="size-8 text-[var(--foreground)] dark:text-white" />
<span className="font-bold text-black dark:text-white">Le Retzien Libre</span>
</Link>
<button
onClick={closeMenu}
className="p-2 rounded-md border border-black/20 dark:border-white/20 hover:bg-black/5 dark:hover:bg-white/5 transition"
aria-label="Fermer le menu"
>
<X className="size-5" />
</button>
</div>
{/* Liens de navigation */}
<nav className="flex flex-col">
<Link href={home()} onClick={closeMenu} className="text-lg py-3 border-b border-black/10 dark:border-white/10 no-underline">
<span className="text-black hover:underline">Accueil</span>
</Link>
<Link href="#services" onClick={closeMenu} className="text-lg py-3 border-b border-black/10 dark:border-white/10 no-underline">
<span className="text-black hover:underline">Nos Services</span>
</Link>
<Link href="#" onClick={closeMenu} className="text-lg py-3 border-b border-black/10 dark:border-white/10 no-underline">
<span className="text-black hover:underline">Le Blog</span>
</Link>
<Link href={contact()} onClick={closeMenu} className="text-lg py-3 no-underline">
<span className="text-black hover:underline">Contact</span>
</Link>
</nav>
{/* Boutons auth */}
<div className="flex flex-col gap-3">
{auth.user ? (
<>
<Link href={dashboard()} onClick={closeMenu} className="no-underline text-foreground mx-auto mb-4">
2026-03-28 17:35:28 +01:00
<Button variant="outline" className="max-w-[150px]">Tableau de bord</Button>
</Link>
<Link
href={logout()}
method="post"
as="button"
onClick={() => { closeMenu(); handleLogout(); }}
className="nb-shadow inline-flex items-center justify-center max-w-[150px] mx-auto gap-2 whitespace-nowrap rounded-md text-sm font-bold cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-secondary text-secondary-foreground hover:bg-secondary/80 h-10 px-4 py-2 w-full no-underline"
2026-03-28 17:35:28 +01:00
data-test="logout-button"
>
Se déconnecter
</Link>
</>
) : (
<>
<Link href={login()} onClick={closeMenu} className="no-underline">
<Button variant="outline" className="w-full">Se connecter</Button>
</Link>
<Link href={membership()} onClick={closeMenu} className="no-underline">
2026-03-30 18:50:04 +02:00
<Button variant="secondary" className="w-full">Adhérer</Button>
2026-03-28 17:35:28 +01:00
</Link>
</>
)}
</div>
</div>
</>
)}
2025-10-22 17:09:48 +02:00
</>
2026-03-28 17:35:28 +01:00
);
2025-10-22 17:09:48 +02:00
}