"use client"; import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"; export type ConsentState = { analytics: boolean; chat: boolean; }; const COOKIE_NAME = "dk0_consent_v1"; function readConsentFromCookie(): ConsentState | null { if (typeof document === "undefined") return null; const match = document.cookie .split(";") .map((c) => c.trim()) .find((c) => c.startsWith(`${COOKIE_NAME}=`)); if (!match) return null; const value = decodeURIComponent(match.split("=").slice(1).join("=")); try { const parsed = JSON.parse(value) as Partial; return { analytics: !!parsed.analytics, chat: !!parsed.chat, }; } catch { return null; } } function writeConsentCookie(value: ConsentState) { const encoded = encodeURIComponent(JSON.stringify(value)); // 180 days const maxAge = 60 * 60 * 24 * 180; document.cookie = `${COOKIE_NAME}=${encoded}; path=/; max-age=${maxAge}; samesite=lax`; } const ConsentContext = createContext<{ consent: ConsentState | null; ready: boolean; setConsent: (next: ConsentState) => void; resetConsent: () => void; }>({ consent: null, ready: false, setConsent: () => {}, resetConsent: () => {}, }); export function ConsentProvider({ children }: { children: React.ReactNode }) { // IMPORTANT: // Don't read `document.cookie` during SSR render (document is undefined), otherwise the // server will render the banner while the client immediately hides it -> hydration mismatch. // We resolve consent on the client after mount and only render the banner once `ready=true`. const [consent, setConsentState] = useState(null); const [ready, setReady] = useState(false); useEffect(() => { setConsentState(readConsentFromCookie()); setReady(true); }, []); const setConsent = useCallback((next: ConsentState) => { setConsentState(next); writeConsentCookie(next); }, []); const resetConsent = useCallback(() => { setConsentState(null); // expire cookie document.cookie = `${COOKIE_NAME}=; path=/; max-age=0; samesite=lax`; }, []); const value = useMemo( () => ({ consent, ready, setConsent, resetConsent }), [consent, ready, setConsent, resetConsent], ); return {children}; } export function useConsent() { return useContext(ConsentContext); } export const consentCookieName = COOKIE_NAME;