160 lines
4.1 KiB
TypeScript
160 lines
4.1 KiB
TypeScript
'use client';
|
|
|
|
import Cookies from 'js-cookie';
|
|
import { createContext, ReactNode, useContext, useEffect, useState } from 'react';
|
|
|
|
// Define cookie categories and their default state
|
|
export const COOKIE_CATEGORIES = {
|
|
NECESSARY: 'necessary',
|
|
ANALYTICS: 'analytics',
|
|
MARKETING: 'marketing',
|
|
PREFERENCES: 'preferences'
|
|
} as const;
|
|
|
|
export type CookieCategory = typeof COOKIE_CATEGORIES[keyof typeof COOKIE_CATEGORIES];
|
|
|
|
export interface CookiePreferences {
|
|
necessary: boolean; // Always true, can't be disabled
|
|
analytics: boolean;
|
|
marketing: boolean;
|
|
preferences: boolean;
|
|
}
|
|
|
|
export const DEFAULT_PREFERENCES: CookiePreferences = {
|
|
necessary: true, // Always true
|
|
analytics: false,
|
|
marketing: false,
|
|
preferences: false
|
|
};
|
|
|
|
const CONSENT_COOKIE_NAME = 'cookie-consent';
|
|
const COOKIE_EXPIRY_DAYS = 365;
|
|
|
|
interface CookieContextType {
|
|
preferences: CookiePreferences;
|
|
hasConsent: boolean;
|
|
showBanner: boolean;
|
|
showModal: boolean;
|
|
acceptAll: () => void;
|
|
savePreferences: (newPrefs: CookiePreferences) => void;
|
|
openModal: () => void;
|
|
closeModal: () => void;
|
|
resetConsent: () => void;
|
|
}
|
|
|
|
const CookieContext = createContext<CookieContextType | undefined>(undefined);
|
|
|
|
export function CookieProvider({ children }: { children: ReactNode }) {
|
|
const [preferences, setPreferences] = useState<CookiePreferences>(DEFAULT_PREFERENCES);
|
|
const [hasConsent, setHasConsent] = useState<boolean>(false);
|
|
const [showBanner, setShowBanner] = useState<boolean>(false);
|
|
const [showModal, setShowModal] = useState<boolean>(false);
|
|
|
|
// Load stored consent preferences on mount (client-side only)
|
|
useEffect(() => {
|
|
const storedConsent = Cookies.get(CONSENT_COOKIE_NAME);
|
|
|
|
if (storedConsent) {
|
|
try {
|
|
const parsedPreferences = JSON.parse(storedConsent);
|
|
setPreferences({
|
|
...DEFAULT_PREFERENCES,
|
|
...parsedPreferences,
|
|
// Ensure necessary cookies are always enabled
|
|
necessary: true
|
|
});
|
|
setHasConsent(true);
|
|
setShowBanner(false);
|
|
} catch (error) {
|
|
console.error('Failed to parse cookie consent', error);
|
|
setShowBanner(true);
|
|
}
|
|
} else {
|
|
// No stored consent, show the banner
|
|
setShowBanner(true);
|
|
}
|
|
}, []);
|
|
|
|
const savePreferences = (newPrefs: CookiePreferences) => {
|
|
const updatedPrefs = {
|
|
...newPrefs,
|
|
necessary: true
|
|
};
|
|
|
|
// Update state
|
|
setPreferences(updatedPrefs);
|
|
setHasConsent(true);
|
|
setShowBanner(false);
|
|
setShowModal(false);
|
|
|
|
// Save to cookie
|
|
Cookies.set(CONSENT_COOKIE_NAME, JSON.stringify(updatedPrefs), {
|
|
expires: COOKIE_EXPIRY_DAYS,
|
|
path: '/',
|
|
sameSite: 'strict'
|
|
});
|
|
|
|
applyPreferences(updatedPrefs);
|
|
};
|
|
|
|
// Accept all cookies
|
|
const acceptAll = () => {
|
|
const allAccepted = {
|
|
necessary: true,
|
|
analytics: true,
|
|
marketing: true,
|
|
preferences: true
|
|
};
|
|
|
|
savePreferences(allAccepted);
|
|
};
|
|
|
|
// Reset consent (for testing)
|
|
const resetConsent = () => {
|
|
Cookies.remove(CONSENT_COOKIE_NAME);
|
|
setPreferences(DEFAULT_PREFERENCES);
|
|
setHasConsent(false);
|
|
setShowBanner(true);
|
|
};
|
|
|
|
const openModal = () => setShowModal(true);
|
|
const closeModal = () => setShowModal(false);
|
|
|
|
// Apply preferences based on consent
|
|
const applyPreferences = (prefs: CookiePreferences) => {
|
|
// Apply analytics preference (without console logs)
|
|
if (prefs.analytics) {
|
|
// Enable analytics tracking
|
|
// Add analytics initialization code here if needed
|
|
} else {
|
|
// Disable analytics tracking
|
|
// Add analytics disabling code here if needed
|
|
}
|
|
};
|
|
|
|
const value = {
|
|
preferences,
|
|
hasConsent,
|
|
showBanner,
|
|
showModal,
|
|
acceptAll,
|
|
savePreferences,
|
|
openModal,
|
|
closeModal,
|
|
resetConsent
|
|
};
|
|
|
|
return (
|
|
<CookieContext.Provider value={value}>
|
|
{children}
|
|
</CookieContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useCookieConsent() {
|
|
const context = useContext(CookieContext);
|
|
if (context === undefined) {
|
|
throw new Error('useCookieConsent must be used within a CookieProvider');
|
|
}
|
|
return context;
|
|
}
|