🙆♀️
【Convex】NextJs14 と Convex【#30 Convex Delete Card】
【#30 Convex Delete Card】
YouTube: https://youtu.be/sXHdfW5lS-w
今回はカードの削除の処理を実装します。
そして、いきなり削除するのではなく
確認用のモーダルを表示して削除の処理を行います。
モーダルは「alert-dialog」を使用します。
npx shadcn-ui@latest add alert-dialog
app/(main)/_components/card/card-actions.tsx
"use client";
import { Pencil, Trash2 } from "lucide-react";
import { toast } from "sonner";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { useRenameCardModal } from "@/store/use-rename-card-modal";
import { useApiMutation } from "@/hooks/use-api-mutation";
import { api } from "@/convex/_generated/api";
import { Button } from "@/components/ui/button";
import { ConfirmModal } from "@/components/confirm-modal";
interface Props {
children: React.ReactNode;
id: string;
title: string;
}
export const CardActions = ({ children, id, title }: Props) => {
const { onOpen } = useRenameCardModal();
const { pending, mutate } = useApiMutation(api.card.deleteCard);
const onDelete = () => {
mutate({ id })
.then(() => toast.success("Card deleted"))
.catch(() => toast.error("Failed to delete card"));
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
className="p-3 cursor-pointer"
onClick={() => onOpen(id, title)}
>
<Pencil className="h-4 w-4 mr-2" /> Rename
</DropdownMenuItem>
<ConfirmModal
header="Are you sure you want to delete card?"
description="All contents on the card will be deleted and cannot undone."
disabled={pending}
onConfirm={onDelete}
>
<Button
variant="ghost"
className="p-3 cursor-pointer text-sm w-full justify-start font-normal"
>
<Trash2 className="h-4 w-4 mr-2" /> Delete
</Button>
</ConfirmModal>
</DropdownMenuContent>
</DropdownMenu>
);
};
components/confirm-modal.tsx
"use client";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
interface Props {
children: React.ReactNode;
onConfirm: () => void;
disabled?: boolean;
header: string;
description?: string;
}
export const ConfirmModal = ({
children,
onConfirm,
disabled,
header,
description,
}: Props) => {
const handleConfirm = () => {
onConfirm();
};
return (
<AlertDialog>
<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{header}</AlertDialogTitle>
<AlertDialogDescription>{description}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction disabled={disabled} onClick={handleConfirm}>
Confirm
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};
Discussion