Cookie Consent
This commit is contained in:
parent
4b1c0293a0
commit
3960853e61
5 changed files with 488 additions and 2 deletions
|
|
@ -7,6 +7,7 @@ import { StripeProvider } from './context/StripeContext';
|
||||||
import useBrandingSettings from '@hooks/brandingHooks';
|
import useBrandingSettings from '@hooks/brandingHooks';
|
||||||
import imageUtils from '@utils/imageUtils';
|
import imageUtils from '@utils/imageUtils';
|
||||||
import Clarity from '@microsoft/clarity';
|
import Clarity from '@microsoft/clarity';
|
||||||
|
import CookieConsentPopup from '@components/CookieConsentPopup';
|
||||||
|
|
||||||
// Import layouts
|
// Import layouts
|
||||||
import MainLayout from './layouts/MainLayout';
|
import MainLayout from './layouts/MainLayout';
|
||||||
|
|
@ -50,7 +51,6 @@ const BrandingPage = lazy(() => import('@pages/Admin/BrandingPage'));
|
||||||
|
|
||||||
const projectId = "rcjhrd0t72"
|
const projectId = "rcjhrd0t72"
|
||||||
|
|
||||||
Clarity.init(projectId);
|
|
||||||
|
|
||||||
|
|
||||||
// Loading component for suspense fallback
|
// Loading component for suspense fallback
|
||||||
|
|
@ -64,6 +64,11 @@ function App() {
|
||||||
// Use the centralized hook to fetch branding settings
|
// Use the centralized hook to fetch branding settings
|
||||||
const { data: brandingSettings, isLoading } = useBrandingSettings();
|
const { data: brandingSettings, isLoading } = useBrandingSettings();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
Clarity.init(projectId);
|
||||||
|
Clarity.consent({ clarity: false });
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Update the document head with branding settings
|
// Update the document head with branding settings
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (brandingSettings) {
|
if (brandingSettings) {
|
||||||
|
|
@ -114,6 +119,7 @@ function App() {
|
||||||
<StripeProvider>
|
<StripeProvider>
|
||||||
<Suspense fallback={<LoadingComponent />}>
|
<Suspense fallback={<LoadingComponent />}>
|
||||||
<Notifications />
|
<Notifications />
|
||||||
|
<CookieConsentPopup />
|
||||||
<Routes>
|
<Routes>
|
||||||
{/* Main routes with MainLayout */}
|
{/* Main routes with MainLayout */}
|
||||||
<Route path="/" element={<MainLayout />}>
|
<Route path="/" element={<MainLayout />}>
|
||||||
|
|
|
||||||
193
frontend/src/components/CookieConsentPopup.jsx
Normal file
193
frontend/src/components/CookieConsentPopup.jsx
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Typography,
|
||||||
|
Button,
|
||||||
|
Box,
|
||||||
|
IconButton,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
FormControlLabel,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Slide,
|
||||||
|
Divider
|
||||||
|
} from '@mui/material';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
import CookieIcon from '@mui/icons-material/Cookie';
|
||||||
|
import consentService, { CONSENT_LEVELS } from '../services/consentService';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie consent popup component
|
||||||
|
* Shows a popup for cookie consent on first visit and manages Clarity tracking
|
||||||
|
*/
|
||||||
|
const CookieConsentPopup = () => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [consentLevel, setConsentLevel] = useState(CONSENT_LEVELS.NECESSARY);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Check if user has already set cookie preferences
|
||||||
|
const storedConsent = consentService.getStoredConsent();
|
||||||
|
|
||||||
|
if (!storedConsent) {
|
||||||
|
// First visit, show the popup
|
||||||
|
setOpen(true);
|
||||||
|
} else {
|
||||||
|
// Apply stored consent settings
|
||||||
|
setConsentLevel(storedConsent.level);
|
||||||
|
consentService.applyConsentSettings(storedConsent.level);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Handle consent level change
|
||||||
|
const handleConsentLevelChange = (event) => {
|
||||||
|
setConsentLevel(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save user preferences and close popup
|
||||||
|
const handleSave = () => {
|
||||||
|
consentService.saveConsent(consentLevel);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Accept all cookies
|
||||||
|
const handleAcceptAll = () => {
|
||||||
|
const allConsent = CONSENT_LEVELS.ALL;
|
||||||
|
setConsentLevel(allConsent);
|
||||||
|
consentService.saveConsent(allConsent);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Accept only necessary cookies
|
||||||
|
const handleNecessaryOnly = () => {
|
||||||
|
const necessaryOnly = CONSENT_LEVELS.NECESSARY;
|
||||||
|
setConsentLevel(necessaryOnly);
|
||||||
|
consentService.saveConsent(necessaryOnly);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reopen the consent popup (for testing or if user wants to change settings)
|
||||||
|
// This function can be exposed via a preferences button somewhere in your app
|
||||||
|
const reopenConsentPopup = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!open) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Slide direction="up" in={open} mountOnEnter unmountOnExit>
|
||||||
|
<Card
|
||||||
|
sx={{
|
||||||
|
position: 'fixed',
|
||||||
|
bottom: 20,
|
||||||
|
right: 20,
|
||||||
|
maxWidth: 400,
|
||||||
|
boxShadow: 4,
|
||||||
|
zIndex: 9999
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardContent>
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||||
|
<CookieIcon color="primary" fontSize="small" sx={{ mr: 1 }} />
|
||||||
|
<Typography variant="h6">Cookie Settings</Typography>
|
||||||
|
</Box>
|
||||||
|
<IconButton size="small" onClick={() => setOpen(false)}>
|
||||||
|
<CloseIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Typography variant="body2" color="text.secondary" paragraph>
|
||||||
|
We use cookies to enhance your browsing experience, provide personalized content,
|
||||||
|
and analyze our traffic. Please choose your privacy settings below.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<FormControl component="fieldset" sx={{ my: 2 }}>
|
||||||
|
<FormLabel component="legend">Privacy Settings</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
value={consentLevel}
|
||||||
|
onChange={handleConsentLevelChange}
|
||||||
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.NECESSARY}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Typography variant="body2">
|
||||||
|
<strong>Necessary Cookies Only</strong> - Essential for website functionality
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.FUNCTIONAL}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Typography variant="body2">
|
||||||
|
<strong>Functional Cookies</strong> - For enhanced functionality and preferences
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.ANALYTICS}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Typography variant="body2">
|
||||||
|
<strong>Analytics Cookies</strong> - To understand how you use our website
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.ALL}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Typography variant="body2">
|
||||||
|
<strong>All Cookies</strong> - Accept all cookies for the best experience
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Divider sx={{ my: 2 }} />
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={handleNecessaryOnly}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
Necessary Only
|
||||||
|
</Button>
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={handleSave}
|
||||||
|
sx={{ mr: 1 }}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
Save Preferences
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={handleAcceptAll}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
Accept All
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Slide>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expose reopen function for others to use
|
||||||
|
export const reopenCookieConsent = () => {
|
||||||
|
const consentElement = document.getElementById('cookie-consent-reopen');
|
||||||
|
if (consentElement) {
|
||||||
|
consentElement.click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CookieConsentPopup;
|
||||||
166
frontend/src/components/CookieSettingsButton.jsx
Normal file
166
frontend/src/components/CookieSettingsButton.jsx
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Button, IconButton, Tooltip, Dialog, DialogTitle, DialogContent,
|
||||||
|
DialogActions, Typography, Box, Divider, RadioGroup, Radio, FormControlLabel,
|
||||||
|
FormControl, FormLabel } from '@mui/material';
|
||||||
|
import CookieIcon from '@mui/icons-material/Cookie';
|
||||||
|
import consentService, { CONSENT_LEVELS } from '../services/consentService';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button to open cookie settings dialog
|
||||||
|
* Can be placed in the footer or other accessible areas of the app
|
||||||
|
*/
|
||||||
|
const CookieSettingsButton = ({ variant = 'text', icon = false, label = 'Cookie Settings' }) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [consentLevel, setConsentLevel] = useState(() => {
|
||||||
|
const storedConsent = consentService.getStoredConsent();
|
||||||
|
return storedConsent?.level || CONSENT_LEVELS.NECESSARY;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOpen = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConsentLevelChange = (event) => {
|
||||||
|
setConsentLevel(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
consentService.saveConsent(consentLevel);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAcceptAll = () => {
|
||||||
|
const allConsent = CONSENT_LEVELS.ALL;
|
||||||
|
setConsentLevel(allConsent);
|
||||||
|
consentService.saveConsent(allConsent);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNecessaryOnly = () => {
|
||||||
|
const necessaryOnly = CONSENT_LEVELS.NECESSARY;
|
||||||
|
setConsentLevel(necessaryOnly);
|
||||||
|
consentService.saveConsent(necessaryOnly);
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render as icon button or regular button
|
||||||
|
if (icon) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tooltip title={label}>
|
||||||
|
<IconButton onClick={handleOpen} size="small" color="inherit">
|
||||||
|
<CookieIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
{renderDialog()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button variant={variant} size="small" onClick={handleOpen}>
|
||||||
|
{label}
|
||||||
|
</Button>
|
||||||
|
{renderDialog()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
function renderDialog() {
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
|
||||||
|
<DialogTitle>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||||
|
<CookieIcon sx={{ mr: 1 }} />
|
||||||
|
Cookie Settings
|
||||||
|
</Box>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography variant="body2" paragraph>
|
||||||
|
We use cookies to enhance your browsing experience, provide personalized content,
|
||||||
|
and analyze our traffic. You can adjust your privacy settings below.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Divider sx={{ my: 2 }} />
|
||||||
|
|
||||||
|
<FormControl component="fieldset" sx={{ width: '100%' }}>
|
||||||
|
<FormLabel component="legend">Privacy Settings</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
value={consentLevel}
|
||||||
|
onChange={handleConsentLevelChange}
|
||||||
|
>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.NECESSARY}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Box>
|
||||||
|
<Typography variant="body1">Necessary Cookies Only</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Essential cookies required for basic website functionality. These cannot be disabled.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.FUNCTIONAL}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Box>
|
||||||
|
<Typography variant="body1">Functional Cookies</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Cookies that remember your preferences and enhance website functionality.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.ANALYTICS}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Box>
|
||||||
|
<Typography variant="body1">Analytics Cookies</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Cookies that help us understand how you use our website and improve your experience.
|
||||||
|
This includes Microsoft Clarity for analyzing site usage patterns.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={CONSENT_LEVELS.ALL}
|
||||||
|
control={<Radio />}
|
||||||
|
label={
|
||||||
|
<Box>
|
||||||
|
<Typography variant="body1">All Cookies</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Accept all cookies including analytics, marketing, and third-party cookies.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Divider sx={{ my: 2 }} />
|
||||||
|
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
You can change these settings at any time by clicking on the Cookie Settings link in the footer.
|
||||||
|
</Typography>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleNecessaryOnly} color="inherit">Necessary Only</Button>
|
||||||
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
|
<Button onClick={handleClose}>Cancel</Button>
|
||||||
|
<Button onClick={handleSave} variant="outlined">Save Preferences</Button>
|
||||||
|
<Button onClick={handleAcceptAll} variant="contained">Accept All</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CookieSettingsButton;
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Container, Grid, Typography, Link, IconButton } from '@mui/material';
|
import { Box, Container, Grid, Typography, Link, IconButton, Divider } from '@mui/material';
|
||||||
import FacebookIcon from '@mui/icons-material/Facebook';
|
import FacebookIcon from '@mui/icons-material/Facebook';
|
||||||
import TwitterIcon from '@mui/icons-material/Twitter';
|
import TwitterIcon from '@mui/icons-material/Twitter';
|
||||||
import InstagramIcon from '@mui/icons-material/Instagram';
|
import InstagramIcon from '@mui/icons-material/Instagram';
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import imageUtils from '@utils/imageUtils';
|
import imageUtils from '@utils/imageUtils';
|
||||||
|
import CookieSettingsButton from './CookieSettingsButton';
|
||||||
|
|
||||||
const Footer = ({brandingSettings}) => {
|
const Footer = ({brandingSettings}) => {
|
||||||
|
|
||||||
|
|
@ -89,6 +90,19 @@ const Footer = ({brandingSettings}) => {
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||||
|
{/* <Link component={RouterLink} to="/privacy-policy" color="inherit" variant="body2">
|
||||||
|
Privacy Policy
|
||||||
|
</Link>
|
||||||
|
<Link component={RouterLink} to="/terms-of-service" color="inherit" variant="body2">
|
||||||
|
Terms of Service
|
||||||
|
</Link> */}
|
||||||
|
<CookieSettingsButton />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box mt={3}>
|
<Box mt={3}>
|
||||||
<Typography variant="body2" color="text.secondary" align="center">
|
<Typography variant="body2" color="text.secondary" align="center">
|
||||||
{copyrightText}
|
{copyrightText}
|
||||||
|
|
|
||||||
107
frontend/src/services/consentService.js
Normal file
107
frontend/src/services/consentService.js
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
* Service for managing cookie and tracking consent preferences
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Clarity from '@microsoft/clarity';
|
||||||
|
|
||||||
|
// Cookie consent levels
|
||||||
|
export const CONSENT_LEVELS = {
|
||||||
|
NECESSARY: 'necessary',
|
||||||
|
FUNCTIONAL: 'functional',
|
||||||
|
ANALYTICS: 'analytics',
|
||||||
|
ALL: 'all'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Local storage key for tracking consent
|
||||||
|
export const CONSENT_STORAGE_KEY = 'rocks_bones_sticks_cookie_consent';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get stored consent level
|
||||||
|
* @returns {Object|null} Stored consent data or null if not set
|
||||||
|
*/
|
||||||
|
export const getStoredConsent = () => {
|
||||||
|
const storedConsent = localStorage.getItem(CONSENT_STORAGE_KEY);
|
||||||
|
return storedConsent ? JSON.parse(storedConsent) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user has given analytics consent
|
||||||
|
* @returns {boolean} Whether analytics is allowed
|
||||||
|
*/
|
||||||
|
export const hasAnalyticsConsent = () => {
|
||||||
|
const consent = getStoredConsent();
|
||||||
|
if (!consent) return false;
|
||||||
|
|
||||||
|
return consent.level === CONSENT_LEVELS.ANALYTICS ||
|
||||||
|
consent.level === CONSENT_LEVELS.ALL;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user has given functional cookies consent
|
||||||
|
* @returns {boolean} Whether functional cookies are allowed
|
||||||
|
*/
|
||||||
|
export const hasFunctionalConsent = () => {
|
||||||
|
const consent = getStoredConsent();
|
||||||
|
if (!consent) return false;
|
||||||
|
|
||||||
|
return consent.level === CONSENT_LEVELS.FUNCTIONAL ||
|
||||||
|
consent.level === CONSENT_LEVELS.ANALYTICS ||
|
||||||
|
consent.level === CONSENT_LEVELS.ALL;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply consent settings to tracking tools
|
||||||
|
* @param {string} level - Consent level to apply
|
||||||
|
*/
|
||||||
|
export const applyConsentSettings = (level) => {
|
||||||
|
// Determine if analytics is allowed based on consent level
|
||||||
|
const allowAnalytics = level === CONSENT_LEVELS.ANALYTICS || level === CONSENT_LEVELS.ALL;
|
||||||
|
|
||||||
|
if (allowAnalytics) {
|
||||||
|
// Enable Clarity tracking
|
||||||
|
Clarity.consent();
|
||||||
|
} else {
|
||||||
|
// Disable Clarity tracking
|
||||||
|
Clarity.consent({ clarity: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Applied consent level: ${level}, analytics ${allowAnalytics ? 'enabled' : 'disabled'}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save user consent preferences
|
||||||
|
* @param {string} level - Consent level to save
|
||||||
|
*/
|
||||||
|
export const saveConsent = (level) => {
|
||||||
|
// Save consent to local storage
|
||||||
|
localStorage.setItem(
|
||||||
|
CONSENT_STORAGE_KEY,
|
||||||
|
JSON.stringify({
|
||||||
|
level,
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Apply the consent settings
|
||||||
|
applyConsentSettings(level);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear stored consent preferences
|
||||||
|
*/
|
||||||
|
export const clearConsent = () => {
|
||||||
|
localStorage.removeItem(CONSENT_STORAGE_KEY);
|
||||||
|
|
||||||
|
// Reset to most restrictive level
|
||||||
|
applyConsentSettings(CONSENT_LEVELS.NECESSARY);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
CONSENT_LEVELS,
|
||||||
|
getStoredConsent,
|
||||||
|
hasAnalyticsConsent,
|
||||||
|
hasFunctionalConsent,
|
||||||
|
applyConsentSettings,
|
||||||
|
saveConsent,
|
||||||
|
clearConsent
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue