'use client'; import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; // Types for cookie consent export interface CookiePreferences { necessary: boolean; functional: boolean; } export interface ConsentAuditLog { timestamp: string; action: 'consent_given' | 'consent_updated' | 'consent_withdrawn' | 'settings_opened'; preferences: CookiePreferences; userAgent: string; ipAddress?: string; sessionId: string; } export interface CookieConsentConfig { version: string; companyName: string; privacyPolicyUrl: string; cookiePolicyUrl: string; dataControllerEmail: string; retentionPeriod: number; // days enableAuditLog: boolean; enableDetailedSettings: boolean; showPrivacyNotice: boolean; } export interface CookieConsentState { hasConsented: boolean; preferences: CookiePreferences; showBanner: boolean; showSettings: boolean; consentDate?: string; lastUpdated?: string; auditLog: ConsentAuditLog[]; } export interface CookieConsentContextType { state: CookieConsentState; config: CookieConsentConfig; acceptAll: () => void; acceptNecessary: () => void; acceptSelected: (preferences: Partial) => void; showSettings: () => void; hideSettings: () => void; updatePreferences: (preferences: Partial) => void; resetConsent: () => void; withdrawConsent: () => void; exportConsentData: () => string; getConsentSummary: () => any; } // Default cookie preferences const defaultPreferences: CookiePreferences = { necessary: true, // Always true, cannot be disabled functional: false, }; // Enterprise configuration const defaultConfig: CookieConsentConfig = { version: '2.0', companyName: 'Your Company Name', privacyPolicyUrl: '/policy?type=privacy', cookiePolicyUrl: '/policy?type=privacy', dataControllerEmail: 'privacy@yourcompany.com', retentionPeriod: 365, // 1 year enableAuditLog: true, enableDetailedSettings: true, showPrivacyNotice: true, }; // Default state const defaultState: CookieConsentState = { hasConsented: false, preferences: defaultPreferences, showBanner: false, showSettings: false, auditLog: [], }; // Create context const CookieConsentContext = createContext(undefined); // Storage keys const CONSENT_STORAGE_KEY = 'cookie-consent-preferences'; const CONSENT_VERSION = '2.0'; // Utility functions const generateSessionId = (): string => { return Math.random().toString(36).substring(2) + Date.now().toString(36); }; const createAuditLogEntry = ( action: ConsentAuditLog['action'], preferences: CookiePreferences ): ConsentAuditLog => { return { timestamp: new Date().toISOString(), action, preferences, userAgent: typeof window !== 'undefined' ? window.navigator.userAgent : '', sessionId: generateSessionId(), }; }; // Provider component export const CookieConsentProvider: React.FC<{ children: ReactNode; config?: Partial; }> = ({ children, config: customConfig }) => { const [state, setState] = useState(defaultState); const config = { ...defaultConfig, ...customConfig }; // Load saved preferences on mount useEffect(() => { const loadSavedPreferences = () => { try { const saved = localStorage.getItem(CONSENT_STORAGE_KEY); if (saved) { const parsed = JSON.parse(saved); // Check if saved version matches current version if (parsed.version === CONSENT_VERSION) { setState({ hasConsented: true, preferences: parsed.preferences, showBanner: false, showSettings: false, consentDate: parsed.consentDate, lastUpdated: parsed.lastUpdated, auditLog: parsed.auditLog || [], }); return; } } } catch (error) { } // Show banner if no valid consent found setState(prev => ({ ...prev, showBanner: true })); }; loadSavedPreferences(); }, []); // Save preferences to localStorage with audit logging const savePreferences = (preferences: CookiePreferences, action: ConsentAuditLog['action'] = 'consent_given') => { try { const auditEntry = config.enableAuditLog ? createAuditLogEntry(action, preferences) : null; const data = { version: CONSENT_VERSION, preferences, timestamp: new Date().toISOString(), consentDate: state.consentDate || new Date().toISOString(), lastUpdated: new Date().toISOString(), auditLog: auditEntry ? [...state.auditLog, auditEntry] : state.auditLog, }; localStorage.setItem(CONSENT_STORAGE_KEY, JSON.stringify(data)); // Update state with audit log if (auditEntry) { setState(prev => ({ ...prev, auditLog: [...prev.auditLog, auditEntry], })); } } catch (error) { } }; // Accept all cookies const acceptAll = () => { const allAccepted: CookiePreferences = { necessary: true, functional: true, }; setState(prev => ({ ...prev, hasConsented: true, preferences: allAccepted, showBanner: false, showSettings: false, consentDate: prev.consentDate || new Date().toISOString(), lastUpdated: new Date().toISOString(), })); savePreferences(allAccepted, 'consent_given'); }; // Accept only necessary cookies const acceptNecessary = () => { const necessaryOnly: CookiePreferences = { necessary: true, functional: false, }; setState(prev => ({ ...prev, hasConsented: true, preferences: necessaryOnly, showBanner: false, showSettings: false, consentDate: prev.consentDate || new Date().toISOString(), lastUpdated: new Date().toISOString(), })); savePreferences(necessaryOnly, 'consent_given'); }; // Accept selected cookies const acceptSelected = (preferences: Partial) => { const newPreferences: CookiePreferences = { necessary: true, // Always true functional: preferences.functional ?? false, }; setState(prev => ({ ...prev, hasConsented: true, preferences: newPreferences, showBanner: false, showSettings: false, consentDate: prev.consentDate || new Date().toISOString(), lastUpdated: new Date().toISOString(), })); savePreferences(newPreferences, 'consent_updated'); }; // Show settings modal const showSettings = () => { setState(prev => ({ ...prev, showSettings: true })); // Log settings opened if (config.enableAuditLog) { const auditEntry = createAuditLogEntry('settings_opened', state.preferences); setState(prev => ({ ...prev, auditLog: [...prev.auditLog, auditEntry], })); } }; // Hide settings modal const hideSettings = () => { setState(prev => ({ ...prev, showSettings: false })); }; // Update preferences (for settings modal) const updatePreferences = (preferences: Partial) => { setState(prev => ({ ...prev, preferences: { ...prev.preferences, ...preferences, necessary: true, // Always keep necessary as true }, })); }; // Reset consent (for testing or user request) const resetConsent = () => { try { localStorage.removeItem(CONSENT_STORAGE_KEY); } catch (error) { } setState({ hasConsented: false, preferences: defaultPreferences, showBanner: true, showSettings: false, auditLog: [], }); }; // Withdraw consent (GDPR compliance) const withdrawConsent = () => { try { localStorage.removeItem(CONSENT_STORAGE_KEY); } catch (error) { } const auditEntry = config.enableAuditLog ? createAuditLogEntry('consent_withdrawn', defaultPreferences) : null; setState({ hasConsented: false, preferences: defaultPreferences, showBanner: true, showSettings: false, auditLog: auditEntry ? [...state.auditLog, auditEntry] : state.auditLog, }); }; // Export consent data (GDPR compliance) const exportConsentData = (): string => { const exportData = { consentData: { hasConsented: state.hasConsented, preferences: state.preferences, consentDate: state.consentDate, lastUpdated: state.lastUpdated, auditLog: state.auditLog, }, config: { version: config.version, companyName: config.companyName, retentionPeriod: config.retentionPeriod, }, exportDate: new Date().toISOString(), }; return JSON.stringify(exportData, null, 2); }; // Get consent summary const getConsentSummary = () => { return { hasConsented: state.hasConsented, preferences: state.preferences, consentDate: state.consentDate, lastUpdated: state.lastUpdated, auditLogCount: state.auditLog.length, config: { version: config.version, companyName: config.companyName, retentionPeriod: config.retentionPeriod, }, }; }; const contextValue: CookieConsentContextType = { state, config, acceptAll, acceptNecessary, acceptSelected, showSettings, hideSettings, updatePreferences, resetConsent, withdrawConsent, exportConsentData, getConsentSummary, }; return ( {children} ); }; // Hook to use cookie consent context export const useCookieConsent = (): CookieConsentContextType => { const context = useContext(CookieConsentContext); if (context === undefined) { throw new Error('useCookieConsent must be used within a CookieConsentProvider'); } return context; }; // Hook to check if specific cookie type is allowed export const useCookiePermission = (type: keyof CookiePreferences): boolean => { const { state } = useCookieConsent(); return state.preferences[type]; }; // Hook for functional features (only runs if functional cookies are allowed) export const useFunctional = () => { const { state } = useCookieConsent(); const isEnabled = state.preferences.functional && state.hasConsented; const saveUserPreference = (key: string, value: any) => { if (isEnabled && typeof window !== 'undefined') { try { localStorage.setItem(`user-preference-${key}`, JSON.stringify(value)); } catch (error) { } } }; const loadUserPreference = (key: string, defaultValue?: any) => { if (isEnabled && typeof window !== 'undefined') { try { const saved = localStorage.getItem(`user-preference-${key}`); return saved ? JSON.parse(saved) : defaultValue; } catch (error) { return defaultValue; } } return defaultValue; }; const rememberUserAction = (action: string, data?: any) => { if (isEnabled) { // Implement your user action tracking logic here } }; return { saveUserPreference, loadUserPreference, rememberUserAction, isEnabled, }; };