80 lines
2.0 KiB
TypeScript
80 lines
2.0 KiB
TypeScript
"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<ConsentState>;
|
|
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;
|
|
setConsent: (next: ConsentState) => void;
|
|
resetConsent: () => void;
|
|
}>({
|
|
consent: null,
|
|
setConsent: () => {},
|
|
resetConsent: () => {},
|
|
});
|
|
|
|
export function ConsentProvider({ children }: { children: React.ReactNode }) {
|
|
const [consent, setConsentState] = useState<ConsentState | null>(null);
|
|
|
|
useEffect(() => {
|
|
setConsentState(readConsentFromCookie());
|
|
}, []);
|
|
|
|
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, setConsent, resetConsent }),
|
|
[consent, setConsent, resetConsent],
|
|
);
|
|
|
|
return <ConsentContext.Provider value={value}>{children}</ConsentContext.Provider>;
|
|
}
|
|
|
|
export function useConsent() {
|
|
return useContext(ConsentContext);
|
|
}
|
|
|
|
export const consentCookieName = COOKIE_NAME;
|
|
|