// Confirmation Dialog Component
// Replaces browser confirm() with proper UI dialogs for destructive actions
import React from 'react';
import { AlertTriangle, X } from 'lucide-react';
// ============================================
// TYPES
// ============================================
export type ConfirmationVariant = 'danger' | 'warning' | 'info';
export interface ConfirmationDialogProps {
isOpen: boolean;
onClose: () => void;
onConfirm: () => void;
title: string;
message?: string;
confirmText?: string;
cancelText?: string;
variant?: ConfirmationVariant;
isLoading?: boolean;
}
// ============================================
// COMPONENT
// ============================================
export const ConfirmationDialog = ({
isOpen,
onClose,
onConfirm,
title,
message,
confirmText = 'Confirm',
cancelText = 'Cancel',
variant = 'danger',
isLoading = false
}: ConfirmationDialogProps) => {
if (!isOpen) return null;
const variantConfig = getVariantConfig(variant);
return (
{/* Backdrop */}
{/* Dialog */}
{/* Close button */}
{/* Content */}
{/* Icon */}
{/* Title */}
{title}
{/* Message */}
{message && (
{message}
)}
{/* Actions */}
{/* Animation styles */}
);
};
// ============================================
// VARIANT CONFIG
// ============================================
interface VariantConfig {
bgClass: string;
iconClass: string;
titleClass: string;
buttonClass: string;
}
const getVariantConfig = (variant: ConfirmationVariant): VariantConfig => {
const configs: Record = {
danger: {
bgClass: 'bg-red-100',
iconClass: 'text-red-500',
titleClass: 'text-red-600',
buttonClass: 'bg-red-500 hover:bg-red-600'
},
warning: {
bgClass: 'bg-amber-100',
iconClass: 'text-amber-500',
titleClass: 'text-amber-600',
buttonClass: 'bg-amber-500 hover:bg-amber-600'
},
info: {
bgClass: 'bg-blue-100',
iconClass: 'text-blue-500',
titleClass: 'text-blue-600',
buttonClass: 'bg-blue-500 hover:bg-blue-600'
}
};
return configs[variant];
};
// ============================================
// HOOK FOR EASIER USAGE
// ============================================
import { useState, useCallback } from 'react';
interface UseConfirmationOptions {
title: string;
message?: string;
confirmText?: string;
cancelText?: string;
variant?: ConfirmationVariant;
onConfirm: () => void | Promise;
}
export const useConfirmation = () => {
const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [options, setOptions] = useState(null);
const confirm = useCallback((opts: UseConfirmationOptions) => {
setOptions(opts);
setIsOpen(true);
}, []);
const handleClose = useCallback(() => {
setIsOpen(false);
setOptions(null);
}, []);
const handleConfirm = useCallback(async () => {
if (!options) return;
setIsLoading(true);
try {
await options.onConfirm();
handleClose();
} catch (error) {
console.error('Confirmation action failed:', error);
} finally {
setIsLoading(false);
}
}, [options, handleClose]);
const dialogProps = {
isOpen,
onClose: handleClose,
onConfirm: handleConfirm,
title: options?.title || '',
message: options?.message,
confirmText: options?.confirmText,
cancelText: options?.cancelText,
variant: options?.variant,
isLoading
};
return { confirm, dialogProps };
};
export default ConfirmationDialog;