diff options
Diffstat (limited to 'lib/general-check-list/table/delete-check-lists-dialog.tsx')
| -rw-r--r-- | lib/general-check-list/table/delete-check-lists-dialog.tsx | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/lib/general-check-list/table/delete-check-lists-dialog.tsx b/lib/general-check-list/table/delete-check-lists-dialog.tsx new file mode 100644 index 00000000..b4b4d648 --- /dev/null +++ b/lib/general-check-list/table/delete-check-lists-dialog.tsx @@ -0,0 +1,106 @@ +"use client"; +import * as React from "react"; +import { Button } from "@/components/ui/button"; +import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from "@/components/ui/dialog"; +import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from "@/components/ui/drawer"; +import { Trash, Loader } from "lucide-react"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { deleteGeneralEvaluations } from "@/lib/general-check-list/service"; +import { toast } from "sonner"; +import { useRouter } from "next/navigation"; + +export function DeleteEvaluationsDialog({ + evaluations, + showTrigger = true, + onSuccess, + ...props +}: { + evaluations: { id: number; serialNumber: string }[]; + showTrigger?: boolean; + onSuccess?: () => void; + open?: boolean; + onOpenChange?: (v: boolean) => void; +}) { + const [pending, startTransition] = React.useTransition(); + const isDesktop = useMediaQuery("(min-width:640px)"); + const router = useRouter(); + + const deleteText = evaluations.length === 1 ? "항목" : "항목들"; + + const handleDelete = () => { + startTransition(async () => { + const res = await deleteGeneralEvaluations(evaluations.map((e) => e.id)); + if (res.success) { + toast.success(res.message); + router.refresh(); + props.onOpenChange?.(false); + onSuccess?.(); + } else { + toast.error(res.message); + } + }); + }; + + const Content = ( + <> + <DialogHeader> + <DialogTitle>삭제 확인</DialogTitle> + <DialogDescription> + 선택된 {evaluations.length}개의 {deleteText}을(를) 삭제합니다. 이 작업은 되돌릴 수 없습니다. + </DialogDescription> + </DialogHeader> + <DialogFooter className="gap-2 sm:space-x-0"> + <DialogClose asChild> + <Button variant="outline">취소</Button> + </DialogClose> + <Button variant="destructive" onClick={handleDelete} disabled={pending}> + {pending && <Loader className="mr-2 size-4 animate-spin" />} 삭제 + </Button> + </DialogFooter> + </> + ); + + if (isDesktop) { + return ( + <Dialog {...props}> + {showTrigger && ( + <DialogTrigger asChild> + <Button variant="outline" size="sm"> + <Trash className="size-4 mr-2" /> 삭제({evaluations.length}) + </Button> + </DialogTrigger> + )} + <DialogContent>{Content}</DialogContent> + </Dialog> + ); + } + + // Mobile Drawer + return ( + <Drawer {...props}> + {showTrigger && ( + <DrawerTrigger asChild> + <Button variant="outline" size="sm"> + <Trash className="size-4 mr-2" /> 삭제({evaluations.length}) + </Button> + </DrawerTrigger> + )} + <DrawerContent className="p-4 space-y-4"> + <DrawerHeader> + <DrawerTitle>삭제 확인</DrawerTitle> + </DrawerHeader> + <DrawerDescription> + 선택된 {evaluations.length}개의 {deleteText}을(를) 삭제합니다. 이 작업은 되돌릴 수 없습니다. + </DrawerDescription> + <DrawerFooter className="gap-2 sm:space-x-0"> + <DrawerClose asChild> + <Button variant="outline">취소</Button> + </DrawerClose> + <Button variant="destructive" onClick={handleDelete} disabled={pending}> + {pending && <Loader className="mr-2 size-4 animate-spin" />} 삭제 + </Button> + </DrawerFooter> + </DrawerContent> + </Drawer> + ); +} |
