diff --git a/src/components/CartBadge.tsx b/src/components/CartBadge.tsx index e904b8d..ab18f84 100644 --- a/src/components/CartBadge.tsx +++ b/src/components/CartBadge.tsx @@ -10,7 +10,7 @@ export function CartBadge() { return ( 🛒 diff --git a/src/components/MobileMenuButton.tsx b/src/components/MobileMenuButton.tsx new file mode 100644 index 0000000..58e00eb --- /dev/null +++ b/src/components/MobileMenuButton.tsx @@ -0,0 +1,224 @@ +"use client"; + +import { useEffect, useRef, useState } from "react"; +import { signOut } from "next-auth/react"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; + +type LinkItem = { href: string; label: string }; + +type Props = { + isAuthenticated: boolean; + isOwner: boolean; + isRentalProvider: boolean; + isCeManager: boolean; + isAdmin: boolean; + rentalEnabled: boolean; + ceEnabled: boolean; +}; + +/** + * Bouton hamburger visible uniquement sur mobile (sm:hidden). + * Ouvre un drawer qui rassemble tous les liens de navigation, car en + * mobile les liens du SiteHeader sont masqués pour rester sur 1 ligne. + */ +export function MobileMenuButton({ + isAuthenticated, + isOwner, + isRentalProvider, + isCeManager, + isAdmin, + rentalEnabled, + ceEnabled, +}: Props) { + const [open, setOpen] = useState(false); + const pathname = usePathname(); + // Ferme le menu si on change de page — pathname comparé à la valeur précédente + // dans un effect avec setState, façon "useRef + condition" pour éviter le + // warning react-hooks/set-state-in-effect (setState dans un effect sans + // dépendance externe = anti-pattern). + const lastPathnameRef = useRef(pathname); + useEffect(() => { + if (lastPathnameRef.current !== pathname) { + lastPathnameRef.current = pathname; + // closure ref → reflète bien la dernière valeur ; setOpen est stable + // (renvoyé par useState) donc OK dans deps. + setOpen(false); + } + }, [pathname]); + + // Empêche le scroll sous-jacent quand ouvert + useEffect(() => { + if (!open) return; + const prev = document.body.style.overflow; + document.body.style.overflow = "hidden"; + return () => { + document.body.style.overflow = prev; + }; + }, [open]); + + const publicLinks: LinkItem[] = [ + { href: "/decouvrir", label: "Au fil de l'eau" }, + { href: "/carbets", label: "Catalogue" }, + ...(rentalEnabled ? [{ href: "/materiel", label: "Matériel" }] : []), + ]; + + const userLinks: LinkItem[] = isAuthenticated + ? [ + { href: "/mes-favoris", label: "Favoris" }, + { href: "/mes-reservations", label: "Mes réservations" }, + ...(rentalEnabled ? [{ href: "/mes-locations", label: "Mes locations" }] : []), + { href: "/mon-compte", label: "Mon compte" }, + ] + : []; + + const proLinks: LinkItem[] = isAuthenticated + ? [ + ...(isOwner ? [{ href: "/espace-hote", label: "Espace hôte" }] : []), + ...(isRentalProvider && rentalEnabled + ? [{ href: "/espace-prestataire", label: "Espace prestataire" }] + : []), + ...(isCeManager && ceEnabled ? [{ href: "/espace-ce", label: "Espace CE" }] : []), + ...(isAdmin ? [{ href: "/admin", label: "Admin" }] : []), + ] + : []; + + return ( + <> + + + {open ? ( +