import { useState, useEffect, useCallback } from 'react' import { GDPRNoticeSettings, CookieCategory } from '../types' // Get API URL and nonce from WordPress const getApiUrl = () => (window as any).swiftCommerceData?.apiUrl || '/wp-json/swift-commerce/v1' const getNonce = () => (window as any).swiftCommerceData?.restNonce || '' // Default settings matching PHP defaults const defaultSettings: GDPRNoticeSettings = { enabled: false, content: { title: 'We Value Your Privacy', message: 'We use cookies to enhance your browsing experience, serve personalized ads or content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies.', acceptButtonText: 'Accept All', declineButtonText: 'Decline', settingsButtonText: 'Cookie Settings', privacyPolicyText: 'Privacy Policy', privacyPolicySource: 'custom', privacyPolicyPageId: 0, privacyPolicyUrl: '', showDeclineButton: true, showSettingsButton: true, showPrivacyLink: true, }, categories: [ { id: 'necessary', name: 'Necessary', description: 'Essential cookies required for the website to function properly.', required: true, enabled: true, }, { id: 'analytics', name: 'Analytics', description: 'Cookies that help us understand how visitors interact with our website.', required: false, enabled: false, }, { id: 'marketing', name: 'Marketing', description: 'Cookies used to deliver personalized advertisements.', required: false, enabled: false, }, { id: 'functional', name: 'Functional', description: 'Cookies that enable enhanced functionality and personalization.', required: false, enabled: false, }, ], appearance: { template: 'default', position: 'bottom', layout: 'full', boxedWidth: 80, theme: 'light', primaryColor: '', backgroundColor: '', textColor: '', borderRadius: 8, showIcon: true, animation: 'slide', blur: false, overlay: false, overlayColor: '#000000', overlayOpacity: 30, overlayBlur: false, fontFamily: 'inherit', titleFontSize: '16', bodyFontSize: '14', fontWeight: '400', buttonStyle: 'filled', buttonSize: 'md', acceptButtonColor: '', acceptButtonTextColor: '#ffffff', declineButtonColor: '', declineButtonStyle: 'outlined', settingsButtonStyle: 'link', }, behavior: { showDelay: 0, reopenMethod: 'floating-button', floatingButtonPosition: 'bottom-left', respectDoNotTrack: false, cookieExpiry: 365, reaskAfterUpdate: false, reaskAfterDecline: false, reaskAfterDeclineDays: 7, policyVersion: '1.0', blockPageScroll: false, }, integrations: { googleAnalytics: { enabled: false, trackingId: '', category: 'analytics', }, googleTagManager: { enabled: false, containerId: '', category: 'analytics', }, facebookPixel: { enabled: false, pixelId: '', category: 'marketing', }, hotjar: { enabled: false, siteId: '', category: 'analytics', }, microsoftClarity: { enabled: false, projectId: '', category: 'analytics', }, googleAds: { enabled: false, conversionId: '', category: 'marketing', }, linkedinInsightTag: { enabled: false, partnerId: '', category: 'marketing', }, tiktokPixel: { enabled: false, pixelId: '', category: 'marketing', }, pinterestTag: { enabled: false, tagId: '', category: 'marketing', }, snapchatPixel: { enabled: false, pixelId: '', category: 'marketing', }, }, geo: { enabled: false, showOnlyInEU: false, showOnlyInGDPRCountries: false, }, logging: { enabled: false, retention: 365, }, } /** * Deep-merge server response with client defaults so newly-added keys * are always present even if the stored option lacks them. */ function mergeWithDefaults(data: Partial): GDPRNoticeSettings { return { ...defaultSettings, ...data, content: { ...defaultSettings.content, ...data.content }, appearance: { ...defaultSettings.appearance, ...data.appearance }, behavior: { ...defaultSettings.behavior, ...data.behavior }, integrations: { googleAnalytics: { ...defaultSettings.integrations.googleAnalytics, ...data.integrations?.googleAnalytics }, googleTagManager: { ...defaultSettings.integrations.googleTagManager, ...data.integrations?.googleTagManager }, facebookPixel: { ...defaultSettings.integrations.facebookPixel, ...data.integrations?.facebookPixel }, hotjar: { ...defaultSettings.integrations.hotjar, ...data.integrations?.hotjar }, microsoftClarity: { ...defaultSettings.integrations.microsoftClarity, ...data.integrations?.microsoftClarity }, googleAds: { ...defaultSettings.integrations.googleAds, ...data.integrations?.googleAds }, linkedinInsightTag: { ...defaultSettings.integrations.linkedinInsightTag, ...data.integrations?.linkedinInsightTag }, tiktokPixel: { ...defaultSettings.integrations.tiktokPixel, ...data.integrations?.tiktokPixel }, pinterestTag: { ...defaultSettings.integrations.pinterestTag, ...data.integrations?.pinterestTag }, snapchatPixel: { ...defaultSettings.integrations.snapchatPixel, ...data.integrations?.snapchatPixel }, }, geo: { ...defaultSettings.geo, ...data.geo }, logging: { ...defaultSettings.logging, ...data.logging }, categories: data.categories || defaultSettings.categories, } } export function useCookieConsent() { const [settings, setSettings] = useState(defaultSettings) const [originalSettings, setOriginalSettings] = useState(defaultSettings) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [error, setError] = useState(null) // Check if there are unsaved changes const hasChanges = JSON.stringify(settings) !== JSON.stringify(originalSettings) // Fetch settings const fetchSettings = useCallback(async () => { try { setLoading(true) setError(null) const response = await fetch(getApiUrl() + '/cookie-consent/settings', { headers: { 'X-WP-Nonce': getNonce(), }, }) if (!response.ok) { throw new Error('Failed to fetch settings') } const data = await response.json() if (data.success && data.settings) { const merged = mergeWithDefaults(data.settings) setSettings(merged) setOriginalSettings(merged) } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch settings') console.error('Error fetching cookie consent settings:', err) } finally { setLoading(false) } }, []) // Save settings const saveSettings = useCallback(async () => { try { setSaving(true) setError(null) const response = await fetch(getApiUrl() + '/cookie-consent/settings', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': getNonce(), }, body: JSON.stringify(settings), }) if (!response.ok) { throw new Error('Failed to save settings') } const data = await response.json() if (data.success && data.settings) { const merged = mergeWithDefaults(data.settings) setSettings(merged) setOriginalSettings(merged) } return { success: true } } catch (err) { const message = err instanceof Error ? err.message : 'Failed to save settings' setError(message) return { success: false, error: message } } finally { setSaving(false) } }, [settings]) // Update root settings const updateSettings = useCallback(( key: K, value: GDPRNoticeSettings[K] ) => { setSettings(prev => ({ ...prev, [key]: value })) }, []) // Update content settings const updateContentSettings = useCallback(( key: K, value: GDPRNoticeSettings['content'][K] ) => { setSettings(prev => ({ ...prev, content: { ...prev.content, [key]: value } })) }, []) // Update appearance settings const updateAppearanceSettings = useCallback(( key: K, value: GDPRNoticeSettings['appearance'][K] ) => { setSettings(prev => ({ ...prev, appearance: { ...prev.appearance, [key]: value } })) }, []) // Update behavior settings const updateBehaviorSettings = useCallback(( key: K, value: GDPRNoticeSettings['behavior'][K] ) => { setSettings(prev => ({ ...prev, behavior: { ...prev.behavior, [key]: value } })) }, []) // Update integration settings const updateIntegrationSettings = useCallback(( key: K, value: GDPRNoticeSettings['integrations'][K] ) => { setSettings(prev => ({ ...prev, integrations: { ...prev.integrations, [key]: value } })) }, []) // Update geo settings const updateGeoSettings = useCallback(( key: K, value: GDPRNoticeSettings['geo'][K] ) => { setSettings(prev => ({ ...prev, geo: { ...prev.geo, [key]: value } })) }, []) // Update logging settings const updateLoggingSettings = useCallback(( key: K, value: GDPRNoticeSettings['logging'][K] ) => { setSettings(prev => ({ ...prev, logging: { ...prev.logging, [key]: value } })) }, []) // Cookie category management const addCategory = useCallback((category: CookieCategory) => { setSettings(prev => ({ ...prev, categories: [...prev.categories, category] })) }, []) const updateCategory = useCallback((id: string, updates: Partial) => { setSettings(prev => ({ ...prev, categories: prev.categories.map(cat => cat.id === id ? { ...cat, ...updates } : cat ) })) }, []) const removeCategory = useCallback((id: string) => { setSettings(prev => ({ ...prev, categories: prev.categories.filter(cat => cat.id !== id) })) }, []) // Reset to default settings const resetToDefaults = useCallback(() => { setSettings(defaultSettings) }, []) // Load settings on mount useEffect(() => { fetchSettings() }, [fetchSettings]) return { settings, loading, saving, error, hasChanges, updateSettings, updateContentSettings, updateAppearanceSettings, updateBehaviorSettings, updateIntegrationSettings, updateGeoSettings, updateLoggingSettings, addCategory, updateCategory, removeCategory, saveSettings, resetToDefaults, refetch: fetchSettings, } }