"use client";
import { useState } from "react";
import {
AlertTriangle,
Check,
Loader2,
Send,
Archive,
Globe,
Lock,
RefreshCw,
Trash2,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { cn } from "@/lib/utils";
type ActionVariant = "default" | "warning" | "destructive" | "info";
type ActionConfig = {
id: string;
title: string;
description: string;
confirmLabel: string;
icon: React.ElementType;
variant: ActionVariant;
triggerLabel: string;
};
const actions: ActionConfig[] = [
{
id: "publish",
title: "Publish Content?",
description:
"This will make your content visible to the public. You can unpublish it later if needed.",
confirmLabel: "Publish",
icon: Globe,
variant: "default",
triggerLabel: "Publish",
},
{
id: "archive",
title: "Archive Project?",
description:
"This project will be moved to archives. Team members will lose access but data will be preserved.",
confirmLabel: "Archive",
icon: Archive,
variant: "warning",
triggerLabel: "Archive",
},
{
id: "reset",
title: "Reset Settings?",
description:
"All your customizations will be lost and settings will return to their defaults. This cannot be undone.",
confirmLabel: "Reset All",
icon: RefreshCw,
variant: "destructive",
triggerLabel: "Reset",
},
];
const variantStyles = {
default: {
icon: "text-primary",
button: "",
},
warning: {
icon: "text-yellow-600",
button: "bg-yellow-600 text-white hover:bg-yellow-700",
},
destructive: {
icon: "text-destructive",
button: "bg-destructive text-white hover:bg-destructive/90",
},
info: {
icon: "text-blue-600",
button: "bg-blue-600 text-white hover:bg-blue-700",
},
};
export const title = "React Dialog Block Confirm Action";
export default function DialogConfirmAction() {
const [openDialog, setOpenDialog] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [dontAskAgain, setDontAskAgain] = useState(false);
const handleConfirm = async (actionId: string) => {
setIsLoading(true);
// Simulate action
await new Promise((resolve) => setTimeout(resolve, 1500));
setIsLoading(false);
setOpenDialog(null);
setDontAskAgain(false);
};
const handleCancel = () => {
setOpenDialog(null);
setDontAskAgain(false);
};
return (
<div className="flex min-h-[350px] items-center justify-center">
<div className="flex flex-wrap gap-3 justify-center">
{actions.map((action) => {
const Icon = action.icon;
const styles = variantStyles[action.variant];
return (
<AlertDialog
key={action.id}
open={openDialog === action.id}
onOpenChange={(open) => setOpenDialog(open ? action.id : null)}
>
<AlertDialogTrigger asChild>
<Button
variant={action.variant === "destructive" ? "destructive" : "outline"}
>
<Icon className="mr-2 h-4 w-4" />
{action.triggerLabel}
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<div className="flex items-start gap-4">
<div
className={cn(
"flex h-10 w-10 shrink-0 items-center justify-center rounded-full border",
action.variant === "destructive" && "border-destructive/50",
action.variant === "warning" && "border-yellow-600/50"
)}
>
<Icon className={cn("h-5 w-5", styles.icon)} />
</div>
<div className="space-y-2">
<AlertDialogTitle>{action.title}</AlertDialogTitle>
<AlertDialogDescription>
{action.description}
</AlertDialogDescription>
</div>
</div>
</AlertDialogHeader>
{/* Don't ask again option */}
<div className="flex items-center gap-2 py-2">
<Checkbox
id={`dont-ask-${action.id}`}
checked={dontAskAgain}
onCheckedChange={(checked) => setDontAskAgain(checked === true)}
/>
<Label
htmlFor={`dont-ask-${action.id}`}
className="text-sm font-normal text-muted-foreground cursor-pointer"
>
Don't ask me again
</Label>
</div>
<AlertDialogFooter>
<AlertDialogCancel onClick={handleCancel} disabled={isLoading}>
Cancel
</AlertDialogCancel>
<AlertDialogAction
onClick={(e) => {
e.preventDefault();
handleConfirm(action.id);
}}
className={cn(styles.button)}
disabled={isLoading}
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Processing...
</>
) : (
<>
<Check className="mr-2 h-4 w-4" />
{action.confirmLabel}
</>
)}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
})}
</div>
</div>
);
}