"use client"; import { useEffect, useId, useRef, useState, useSyncExternalStore } from "react"; import { createPortal } from "react-dom"; import Link from "next/link"; import { Button } from "@/components/ui/Button"; import { allAccepted, allRejected, CONSENT_OPEN_EVENT, CONSENT_VERSION, type Consent, type OptionalCategory, } from "@/lib/consent"; import { getServerSnapshot, getSnapshot, subscribe, writeConsent } from "./consent-store"; export type CookieTexts = { title: string; description: string; acceptAll: string; rejectAll: string; customize: string; save: string; back: string; policyLabel: string; policyHref: string; categories: { id: "necessary" | OptionalCategory; label: string; description: string }[]; }; export function CookieConsent({ texts }: { texts: CookieTexts }) { const consent = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); const [prefsOpen, setPrefsOpen] = useState(false); const [forcedOpen, setForcedOpen] = useState(false); const [draft, setDraft] = useState>({ analytics: false, marketing: false, }); const headingId = useId(); const descId = useId(); const panelRef = useRef(null); // Réouverture depuis le pied de page (« Gérer les témoins »). useEffect(() => { const onOpen = () => { const current = getSnapshot(); if (current) setDraft({ analytics: current.analytics, marketing: current.marketing }); setForcedOpen(true); setPrefsOpen(true); }; window.addEventListener(CONSENT_OPEN_EVENT, onOpen); return () => window.removeEventListener(CONSENT_OPEN_EVENT, onOpen); }, []); useEffect(() => { if (prefsOpen) panelRef.current?.focus(); }, [prefsOpen]); if (consent === null) return null; // rendu serveur / hydratation : rien const visible = consent === undefined || forcedOpen; if (!visible) return null; const openPrefs = () => { if (consent) setDraft({ analytics: consent.analytics, marketing: consent.marketing }); setPrefsOpen(true); }; const decide = (c: Consent) => { writeConsent(c); setPrefsOpen(false); setForcedOpen(false); }; const saveDraft = () => decide({ version: CONSENT_VERSION, date: new Date().toISOString(), necessary: true, ...draft }); const panel = (
{ if (e.key === "Escape" && prefsOpen) { if (consent) { setPrefsOpen(false); setForcedOpen(false); } else setPrefsOpen(false); } }} >

{texts.title}

{texts.description}{" "} {texts.policyLabel}

{prefsOpen ? (
    {texts.categories.map((cat) => { const required = cat.id === "necessary"; const checked = required ? true : draft[cat.id as OptionalCategory]; const inputId = `${headingId}-${cat.id}`; return (
  • !required && setDraft((d) => ({ ...d, [cat.id]: e.target.checked })) } />

    {cat.description}

  • ); })}
) : null}
{prefsOpen ? ( <> ) : ( <> )}
); return createPortal(panel, document.body); } export function ManageCookiesButton({ label, className = "", }: { label: string; className?: string; }) { return ( ); }