import * as React from 'react'; import { Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Dialog, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; /* ── ConfirmDialog ────────────────────────────────────────────── Reusable confirmation dialog that replaces window.confirm. Props: open boolean onOpenChange (open: boolean) => void title string description string | ReactNode confirmLabel string (default: 'Confirm') cancelLabel string (default: 'Cancel') variant 'default' | 'destructive' onConfirm () => void | Promise loading boolean ─────────────────────────────────────────────────────────────── */ export function ConfirmDialog({ open, onOpenChange, title, description, confirmLabel = 'Confirm', cancelLabel = 'Cancel', variant = 'default', onConfirm, loading = false, }) { const handleConfirm = async () => { await onConfirm?.(); }; const handleCancel = () => { if (!loading) onOpenChange(false); }; return ( {title} {description && ( {description} )} ); } /* ── useConfirm hook ──────────────────────────────────────────── Imperative API for ConfirmDialog. Usage: const { confirm, ConfirmDialogComponent } = useConfirm(); // ... const ok = await confirm({ title, description, confirmLabel, variant }); // Returns true if confirmed, false if cancelled. // Render anywhere in the tree. ─────────────────────────────────────────────────────────────── */ export function useConfirm() { const [state, setState] = React.useState({ open: false, title: '', description: '', confirmLabel: 'Confirm', cancelLabel: 'Cancel', variant: 'default', loading: false, }); // Keep a stable ref to the resolve callback so it survives re-renders const resolveRef = React.useRef(null); const confirm = React.useCallback( ({ title = 'Are you sure?', description = '', confirmLabel = 'Confirm', cancelLabel = 'Cancel', variant = 'default', } = {}) => { return new Promise((resolve) => { resolveRef.current = resolve; setState({ open: true, title, description, confirmLabel, cancelLabel, variant, loading: false, }); }); }, [] ); const handleConfirm = React.useCallback(async () => { setState((s) => ({ ...s, loading: true })); resolveRef.current?.(true); resolveRef.current = null; setState((s) => ({ ...s, open: false, loading: false })); }, []); const handleOpenChange = React.useCallback((open) => { if (!open) { resolveRef.current?.(false); resolveRef.current = null; setState((s) => ({ ...s, open: false })); } }, []); const ConfirmDialogComponent = React.useCallback( () => ( ), // eslint-disable-next-line react-hooks/exhaustive-deps [state, handleConfirm, handleOpenChange] ); return { confirm, ConfirmDialogComponent }; }