"use client";
import { useState } from "react";
import {
Cookie,
Shield,
BarChart3,
Megaphone,
Settings2,
Info,
ExternalLink,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { cn } from "@/lib/utils";
type CookieCategory = {
id: string;
name: string;
description: string;
details: string;
icon: React.ElementType;
required?: boolean;
cookies: { name: string; purpose: string; expiry: string }[];
};
const cookieCategories: CookieCategory[] = [
{
id: "necessary",
name: "Strictly Necessary",
description: "Essential for the website to function properly",
details:
"These cookies are required for basic site functionality and cannot be disabled. They include session management, security features, and accessibility preferences.",
icon: Shield,
required: true,
cookies: [
{ name: "session_id", purpose: "Session management", expiry: "Session" },
{ name: "csrf_token", purpose: "Security protection", expiry: "Session" },
{ name: "cookie_consent", purpose: "Store your preferences", expiry: "1 year" },
],
},
{
id: "functional",
name: "Functional",
description: "Enhanced features and personalization",
details:
"These cookies enable enhanced functionality like remembering your preferences, language settings, and providing personalized features.",
icon: Settings2,
cookies: [
{ name: "language", purpose: "Language preference", expiry: "1 year" },
{ name: "theme", purpose: "Display preferences", expiry: "1 year" },
{ name: "recent_items", purpose: "Recently viewed", expiry: "30 days" },
],
},
{
id: "analytics",
name: "Analytics",
description: "Help us understand how you use our site",
details:
"These cookies collect information about how you interact with our website, helping us improve user experience and identify issues.",
icon: BarChart3,
cookies: [
{ name: "_ga", purpose: "Google Analytics tracking", expiry: "2 years" },
{ name: "_gid", purpose: "Distinguish users", expiry: "24 hours" },
{ name: "performance_data", purpose: "Page load metrics", expiry: "30 days" },
],
},
{
id: "marketing",
name: "Marketing",
description: "Personalized ads and content",
details:
"These cookies are used to deliver relevant advertisements and track campaign performance. They may be set by our advertising partners.",
icon: Megaphone,
cookies: [
{ name: "_fbp", purpose: "Facebook advertising", expiry: "3 months" },
{ name: "ads_prefs", purpose: "Ad preferences", expiry: "1 year" },
{ name: "conversion_tracking", purpose: "Campaign attribution", expiry: "90 days" },
],
},
];
export const title = "React Dialog Block Cookie Settings";
export default function DialogCookieSettings() {
const [open, setOpen] = useState(false);
const [preferences, setPreferences] = useState<Record<string, boolean>>({
necessary: true,
functional: false,
analytics: false,
marketing: false,
});
const handleToggle = (categoryId: string) => {
if (categoryId === "necessary") return; // Cannot disable necessary cookies
setPreferences((prev) => ({
...prev,
[categoryId]: !prev[categoryId],
}));
};
const handleAcceptAll = () => {
setPreferences({
necessary: true,
functional: true,
analytics: true,
marketing: true,
});
};
const handleRejectAll = () => {
setPreferences({
necessary: true,
functional: false,
analytics: false,
marketing: false,
});
};
const handleSave = () => {
// In real app: save to cookie/localStorage and apply preferences
setOpen(false);
};
const enabledCount = Object.values(preferences).filter(Boolean).length;
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Cookie className="mr-2 h-4 w-4" />
Cookie Settings
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Cookie className="h-5 w-5" />
Cookie Preferences
</DialogTitle>
<DialogDescription>
Manage how we use cookies to improve your experience.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
{/* Quick Actions */}
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
className="flex-1"
onClick={handleRejectAll}
>
Reject All
</Button>
<Button
variant="outline"
size="sm"
className="flex-1"
onClick={handleAcceptAll}
>
Accept All
</Button>
</div>
<Separator />
{/* Cookie Categories */}
<Accordion type="multiple" className="w-full">
{cookieCategories.map((category) => {
const Icon = category.icon;
const isEnabled = preferences[category.id];
return (
<AccordionItem key={category.id} value={category.id}>
<div className="flex items-center gap-3 py-2">
<Icon className="h-4 w-4 text-muted-foreground shrink-0" />
<div className="flex-1 min-w-0">
<AccordionTrigger className="py-0 hover:no-underline">
<div className="flex items-center gap-2 text-left">
<span className="font-medium">{category.name}</span>
{category.required && (
<Badge variant="secondary" className="text-xs">
Required
</Badge>
)}
</div>
</AccordionTrigger>
<p className="text-xs text-muted-foreground mt-0.5">
{category.description}
</p>
</div>
<Switch
checked={isEnabled}
onCheckedChange={() => handleToggle(category.id)}
disabled={category.required}
aria-label={`Toggle ${category.name} cookies`}
/>
</div>
<AccordionContent>
<div className="pl-7 space-y-3">
<p className="text-sm text-muted-foreground">
{category.details}
</p>
<div className="rounded-lg border">
<div className="grid grid-cols-3 gap-2 p-2 text-xs font-medium border-b">
<span>Cookie</span>
<span>Purpose</span>
<span>Expiry</span>
</div>
{category.cookies.map((cookie, index) => (
<div
key={cookie.name}
className={cn(
"grid grid-cols-3 gap-2 p-2 text-xs",
index !== category.cookies.length - 1 && "border-b"
)}
>
<span className="font-mono">{cookie.name}</span>
<span className="text-muted-foreground">
{cookie.purpose}
</span>
<span className="text-muted-foreground">
{cookie.expiry}
</span>
</div>
))}
</div>
</div>
</AccordionContent>
</AccordionItem>
);
})}
</Accordion>
{/* Summary */}
<div className="flex items-center justify-between text-sm text-muted-foreground">
<span>
{enabledCount} of {cookieCategories.length} categories enabled
</span>
<Button variant="link" size="sm" className="h-auto p-0 text-xs">
Privacy Policy
<ExternalLink className="ml-1 h-3 w-3" />
</Button>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button onClick={handleSave}>
<Cookie className="mr-2 h-4 w-4" />
Save Preferences
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}