Files
bakery-ia/frontend/src/pages/public/CookiePreferencesPage.tsx
2025-10-30 21:08:07 +01:00

235 lines
9.0 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Button, Card } from '../../components/ui';
import { Cookie, CheckCircle, XCircle, Shield, BarChart3, Target, Settings as SettingsIcon } from 'lucide-react';
import {
getCookieConsent,
saveCookieConsent,
getCookieCategories,
CookiePreferences
} from '../../components/ui/CookieConsent';
import { showToast } from '../../utils/toast';
export const CookiePreferencesPage: React.FC = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const [preferences, setPreferences] = useState<CookiePreferences>({
essential: true,
analytics: false,
marketing: false,
preferences: false,
timestamp: new Date().toISOString(),
version: '1.0'
});
useEffect(() => {
const existingConsent = getCookieConsent();
if (existingConsent) {
setPreferences(existingConsent);
}
}, []);
const handleToggle = (category: keyof Omit<CookiePreferences, 'timestamp' | 'version'>) => {
if (category === 'essential') return;
setPreferences(prev => ({
...prev,
[category]: !prev[category]
}));
};
const handleSave = () => {
const updatedPreferences: CookiePreferences = {
...preferences,
timestamp: new Date().toISOString()
};
saveCookieConsent(updatedPreferences);
showToast.success(
t('common:cookie.preferences_saved', 'Your cookie preferences have been saved successfully.'),
{ title: t('common:cookie.success', 'Preferences Saved') }
);
};
const handleAcceptAll = () => {
const allEnabled: CookiePreferences = {
essential: true,
analytics: true,
marketing: true,
preferences: true,
timestamp: new Date().toISOString(),
version: '1.0'
};
saveCookieConsent(allEnabled);
setPreferences(allEnabled);
showToast.success(
t('common:cookie.all_accepted', 'All cookies have been accepted.'),
{ title: t('common:cookie.success', 'Preferences Saved') }
);
};
const handleRejectAll = () => {
const essentialOnly: CookiePreferences = {
essential: true,
analytics: false,
marketing: false,
preferences: false,
timestamp: new Date().toISOString(),
version: '1.0'
};
saveCookieConsent(essentialOnly);
setPreferences(essentialOnly);
showToast.success(
t('common:cookie.only_essential', 'Only essential cookies are enabled.'),
{ title: t('common:cookie.success', 'Preferences Saved') }
);
};
const categories = getCookieCategories();
const getCategoryIcon = (categoryId: string) => {
switch (categoryId) {
case 'essential':
return <Shield className="w-5 h-5 text-green-600" />;
case 'preferences':
return <SettingsIcon className="w-5 h-5 text-blue-600" />;
case 'analytics':
return <BarChart3 className="w-5 h-5 text-purple-600" />;
case 'marketing':
return <Target className="w-5 h-5 text-orange-600" />;
default:
return <Cookie className="w-5 h-5 text-gray-600" />;
}
};
return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 py-12 px-4">
<div className="max-w-4xl mx-auto">
<div className="text-center mb-8">
<div className="flex justify-center mb-4">
<Cookie className="w-16 h-16 text-amber-600" />
</div>
<h1 className="text-3xl font-bold text-gray-900 dark:text-white mb-2">
{t('common:cookie.preferences_title', 'Cookie Preferences')}
</h1>
<p className="text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
{t(
'common:cookie.preferences_description',
'Manage your cookie preferences. You can enable or disable different types of cookies below. Note that blocking some types of cookies may impact your experience on our website.'
)}
</p>
</div>
<div className="space-y-4 mb-6">
{categories.map((category) => {
const isEnabled = preferences[category.id as keyof Omit<CookiePreferences, 'timestamp' | 'version'>];
return (
<Card key={category.id} className="p-6">
<div className="flex items-start justify-between gap-4">
<div className="flex items-start gap-4 flex-1">
<div className="mt-1">{getCategoryIcon(category.id)}</div>
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
{category.name}
</h3>
{category.required && (
<span className="px-2 py-1 bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-100 text-xs font-medium rounded">
{t('common:cookie.required', 'Required')}
</span>
)}
</div>
<p className="text-sm text-gray-600 dark:text-gray-400 mb-3">
{category.description}
</p>
<div className="text-xs text-gray-500 dark:text-gray-500">
<span className="font-medium">{t('common:cookie.examples', 'Examples')}: </span>
{category.examples.join(', ')}
</div>
</div>
</div>
<button
onClick={() => handleToggle(category.id as keyof Omit<CookiePreferences, 'timestamp' | 'version'>)}
disabled={category.required}
className={`flex-shrink-0 w-14 h-8 rounded-full transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 ${
isEnabled
? 'bg-primary-600'
: 'bg-gray-300 dark:bg-gray-600'
} ${category.required ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`}
role="switch"
aria-checked={isEnabled}
aria-label={`Toggle ${category.name}`}
>
<span
className={`inline-block w-6 h-6 mt-1 bg-white rounded-full shadow transform transition-transform duration-200 ease-in-out ${
isEnabled ? 'translate-x-7' : 'translate-x-1'
}`}
/>
</button>
</div>
</Card>
);
})}
</div>
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 mb-6">
<div className="flex items-start gap-3">
<Shield className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<div className="text-sm text-blue-800 dark:text-blue-200">
<p className="font-medium mb-1">
{t('common:cookie.info_title', 'About Cookie Management')}
</p>
<p>
{t(
'common:cookie.info_description',
'Essential cookies are always enabled to ensure the basic functionality of our website. You can choose to disable other cookie categories, but this may affect certain features. For more information, please read our '
)}
<a href="/cookies" className="underline font-medium hover:text-blue-900 dark:hover:text-blue-100">
{t('common:cookie.cookie_policy', 'Cookie Policy')}
</a>
{' '}
{t('common:cookie.and', 'and')}
{' '}
<a href="/privacy" className="underline font-medium hover:text-blue-900 dark:hover:text-blue-100">
{t('common:cookie.privacy_policy', 'Privacy Policy')}
</a>
.
</p>
</div>
</div>
</div>
<div className="flex flex-col sm:flex-row gap-3">
<Button onClick={handleAcceptAll} variant="primary" className="flex-1">
{t('common:cookie.accept_all', 'Accept All')}
</Button>
<Button onClick={handleSave} variant="outline" className="flex-1">
{t('common:cookie.save_preferences', 'Save Preferences')}
</Button>
<Button onClick={handleRejectAll} variant="ghost" className="flex-1">
{t('common:cookie.reject_all', 'Reject All Non-Essential')}
</Button>
</div>
<div className="mt-6 text-center">
<button
onClick={() => navigate(-1)}
className="text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white underline"
>
{t('common:actions.go_back', 'Go Back')}
</button>
</div>
</div>
</div>
);
};
export default CookiePreferencesPage;