summaryrefslogtreecommitdiff
path: root/lib/tech-vendor-possible-items/table/delete-possible-items-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tech-vendor-possible-items/table/delete-possible-items-dialog.tsx')
-rw-r--r--lib/tech-vendor-possible-items/table/delete-possible-items-dialog.tsx175
1 files changed, 175 insertions, 0 deletions
diff --git a/lib/tech-vendor-possible-items/table/delete-possible-items-dialog.tsx b/lib/tech-vendor-possible-items/table/delete-possible-items-dialog.tsx
new file mode 100644
index 00000000..6b1c7775
--- /dev/null
+++ b/lib/tech-vendor-possible-items/table/delete-possible-items-dialog.tsx
@@ -0,0 +1,175 @@
+"use client";
+
+import * as React from "react";
+import { Trash2, AlertTriangle } from "lucide-react";
+
+import { Button } from "@/components/ui/button";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog";
+import { Badge } from "@/components/ui/badge";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import { useToast } from "@/hooks/use-toast";
+import { deleteTechVendorPossibleItems } from "@/lib/tech-vendor-possible-items/service";
+
+interface TechVendorPossibleItemsData {
+ id: number;
+ vendorId: number;
+ vendorCode: string | null;
+ vendorName: string;
+ techVendorType: string;
+ itemCode: string;
+ itemList: string | null;
+ workType: string | null;
+ shipTypes: string | null;
+ subItemList: string | null;
+ createdAt: Date;
+ updatedAt: Date;
+}
+
+interface DeletePossibleItemsDialogProps {
+ selectedItems: TechVendorPossibleItemsData[];
+ children?: React.ReactNode;
+ onSuccess?: () => void;
+}
+
+export function DeletePossibleItemsDialog({
+ selectedItems,
+ children,
+ onSuccess
+}: DeletePossibleItemsDialogProps) {
+ const { toast } = useToast();
+ const [open, setOpen] = React.useState(false);
+ const [isLoading, setIsLoading] = React.useState(false);
+
+ const handleDelete = async () => {
+ if (selectedItems.length === 0) return;
+
+ try {
+ setIsLoading(true);
+ const selectedIds = selectedItems.map(item => item.id);
+
+ const result = await deleteTechVendorPossibleItems(selectedIds);
+
+ if (result.success) {
+ toast({
+ title: "성공",
+ description: `${selectedIds.length}개의 아이템이 삭제되었습니다.`,
+ });
+
+ setOpen(false);
+ onSuccess?.();
+ } else {
+ toast({
+ title: "오류",
+ description: result.error || "삭제 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ }
+ } catch (error) {
+ console.error("Delete error:", error);
+ toast({
+ title: "오류",
+ description: "삭제 중 오류가 발생했습니다.",
+ variant: "destructive",
+ });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const parseVendorTypes = (vendorType: string): string[] => {
+ try {
+ return JSON.parse(vendorType);
+ } catch {
+ return vendorType.split(',').map(t => t.trim());
+ }
+ };
+
+ return (
+ <Dialog open={open} onOpenChange={setOpen}>
+ <DialogTrigger asChild>
+ {children || (
+ <Button
+ variant="destructive"
+ size="sm"
+ disabled={selectedItems.length === 0}
+ >
+ <Trash2 className="mr-2 h-4 w-4" />
+ 삭제 ({selectedItems.length})
+ </Button>
+ )}
+ </DialogTrigger>
+ <DialogContent className="max-w-2xl">
+ <DialogHeader>
+ <DialogTitle className="flex items-center gap-2">
+ <AlertTriangle className="h-5 w-5 text-destructive" />
+ 아이템 삭제 확인
+ </DialogTitle>
+ <DialogDescription>
+ 선택한 {selectedItems.length}개의 벤더-아이템 조합을 삭제하시겠습니까?
+ 이 작업은 되돌릴 수 없습니다.
+ </DialogDescription>
+ </DialogHeader>
+
+ <div className="py-4">
+ <div className="text-sm font-medium mb-3">삭제될 아이템 목록:</div>
+ <ScrollArea className="max-h-[300px] border rounded-md">
+ <div className="p-4 space-y-3">
+ {selectedItems.map((item) => (
+ <div key={item.id} className="border rounded-md p-3 bg-muted/50">
+ <div className="flex justify-between items-start">
+ <div className="space-y-1">
+ <div className="font-medium text-sm">
+ {item.vendorName} ({item.vendorCode})
+ </div>
+ <div className="text-sm text-muted-foreground">
+ 아이템코드: {item.itemCode}
+ </div>
+ {item.itemList && (
+ <div className="text-xs text-muted-foreground">
+ 아이템리스트: {item.itemList}
+ </div>
+ )}
+ {item.workType && (
+ <div className="text-xs text-muted-foreground">
+ 공종: {item.workType}
+ </div>
+ )}
+ </div>
+ <div className="flex flex-wrap gap-1">
+ {parseVendorTypes(item.techVendorType).map((type, index) => (
+ <Badge key={index} variant="secondary" className="text-xs">
+ {type}
+ </Badge>
+ ))}
+ </div>
+ </div>
+ </div>
+ ))}
+ </div>
+ </ScrollArea>
+ </div>
+
+ <DialogFooter>
+ <Button variant="outline" onClick={() => setOpen(false)}>
+ 취소
+ </Button>
+ <Button
+ variant="destructive"
+ onClick={handleDelete}
+ disabled={isLoading}
+ >
+ {isLoading ? "삭제 중..." : `삭제 (${selectedItems.length})`}
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ );
+} \ No newline at end of file