Ctrl K
ComunidadGuías…

components/ConfirmDeleteModal.tsx

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
'use client';

import { TrashIcon } from '@heroicons/react/24/outline';
import { useRouter } from 'next/navigation';
import { ReactNode, useState } from 'react';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
  DialogTrigger,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { AlertOctagon } from 'lucide-react';
import { useTranslations } from 'next-intl';

type ConfirmDeleteModalProps = {
  namespace: string;
  entityTitle: string;
  onDelete: () => Promise<unknown>;
  onSuccess?: () => void;
  triggerClassName?: string;
  triggerIconClassName?: string;
  trigger?: ReactNode;
};

export default function ConfirmDeleteModal({
  namespace,
  entityTitle,
  onDelete,
  onSuccess,
  triggerClassName = 'h-8 w-8',
  triggerIconClassName = 'h-4 w-4',
  trigger,
}: ConfirmDeleteModalProps) {
  const t = useTranslations(namespace);
  const router = useRouter();
  const [deleting, setDeleting] = useState(false);
  const [open, setOpen] = useState(false);

  const handleDeleteClick = async () => {
    setDeleting(true);
    let deleted: unknown;
    try {
      deleted = await onDelete();
    } catch (error) {
      console.error('Delete failed:', error);
      return;
    } finally {
      setDeleting(false);
    }
    // Delete actions return null when the user may not delete the entity.
    if (deleted === null) return;
    setOpen(false);
    if (onSuccess) onSuccess();
    else router.refresh();
  };

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        {trigger || (
          <Button variant="ghost" size="icon" className={triggerClassName}>
            <TrashIcon className={triggerIconClassName} />
            <span className="sr-only">{t('delete')}</span>
          </Button>
        )}
      </DialogTrigger>
      <DialogContent className="p-10 max-w-[480px]">
        <DialogHeader className="mb-6">
          <Label className="text-destructive">{t('security')}</Label>
          <DialogTitle className="flex items-center gap-2">
            {t('title')}
          </DialogTitle>
        </DialogHeader>

        <div className="space-y-8">
          <p className="text-sm text-muted-foreground leading-relaxed antialiased">
            {t('description', { title: entityTitle })}
          </p>

          <div className="p-4 bg-[var(--color-accent-red)] rounded-[12px] border border-destructive/20">
            <p className="text-[12px] text-destructive font-medium leading-normal flex gap-2">
              <AlertOctagon className="h-4 w-4 flex-shrink-0" />
              {t('warning')}
            </p>
          </div>
        </div>

        <DialogFooter className="mt-8">
          <Button
            type="button"
            variant="ghost"
            onClick={() => setOpen(false)}
            className="rounded-[12px] text-muted-foreground font-bold hover:bg-secondary/10"
            disabled={deleting}
          >
            {t('cancel')}
          </Button>
          <Button
            variant="danger"
            onClick={handleDeleteClick}
            disabled={deleting}
            className="font-bold px-8 shadow-none"
          >
            {deleting ? t('deleting') : t('confirm')}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}