diff options
Diffstat (limited to 'lib/vendors/materials-table/item-action-dialog.tsx')
| -rw-r--r-- | lib/vendors/materials-table/item-action-dialog.tsx | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/vendors/materials-table/item-action-dialog.tsx b/lib/vendors/materials-table/item-action-dialog.tsx new file mode 100644 index 00000000..d06f609c --- /dev/null +++ b/lib/vendors/materials-table/item-action-dialog.tsx @@ -0,0 +1,207 @@ +"use client" + +import * as React from "react" +import type { DataTableRowAction } from "@/types/table" +import { VendorMaterialsView } from "@/db/schema/vendors" +import { toast } from "sonner" + +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog" +import { Button } from "@/components/ui/button" +import { Label } from "@/components/ui/label" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { deleteVendorMaterial, getMaterialsForVendor, updateVendorMaterial } from "../service" + + +interface ItemActionsDialogsProps { + vendorId: number + rowAction: DataTableRowAction<VendorMaterialsView> | null + setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<VendorMaterialsView> | null>> +} + +export function ItemActionsDialogs({ + vendorId, + rowAction, + setRowAction, +}: ItemActionsDialogsProps) { + const [isUpdatePending, startUpdateTransition] = React.useTransition() + const [isDeletePending, startDeleteTransition] = React.useTransition() + const [availableMaterials, setAvailableMaterials] = React.useState<any[]>([]) + const [selectedItemCode, setSelectedItemCode] = React.useState<string>("") + + // 사용 가능한 재료 목록 로드 + React.useEffect(() => { + if (rowAction?.type === "update") { + getMaterialsForVendor(vendorId).then((result) => { + if (result.data) { + setAvailableMaterials(result.data) + } + }) + } + }, [rowAction, vendorId]) + + // Edit Dialog + const EditDialog = () => { + if (!rowAction || rowAction.type !== "update") return null + + const item = rowAction.row.original + + const handleSubmit = () => { + if (!selectedItemCode) { + toast.error("Please select a new item") + return + } + + startUpdateTransition(async () => { + const result = await updateVendorMaterial(vendorId, item.itemCode, selectedItemCode) + + if (result.error) { + toast.error(result.error) + } else { + toast.success("Item updated successfully") + setRowAction(null) + } + }) + } + + return ( + <Dialog + open={true} + onOpenChange={(open) => !open && setRowAction(null)} + > + <DialogContent className="sm:max-w-[425px]"> + <DialogHeader> + <DialogTitle>Change Item</DialogTitle> + <DialogDescription> + Select a new item to replace "{item.itemName}" (Code: {item.itemCode}). + </DialogDescription> + </DialogHeader> + + <div className="space-y-4"> + <div className="space-y-2"> + <Label>Current Item</Label> + <div className="p-2 bg-muted rounded-md"> + <div className="font-medium">{item.itemName}</div> + <div className="text-sm text-muted-foreground">Code: {item.itemCode}</div> + </div> + </div> + + <div className="space-y-2"> + <Label htmlFor="newItem">New Item</Label> + <Select value={selectedItemCode} onValueChange={setSelectedItemCode}> + <SelectTrigger> + <SelectValue placeholder="Select a new item" /> + </SelectTrigger> + <SelectContent> + {availableMaterials.map((material) => ( + <SelectItem key={material.itemCode} value={material.itemCode}> + <div> + <div className="font-medium">{material.itemName}</div> + <div className="text-sm text-muted-foreground">Code: {material.itemCode}</div> + </div> + </SelectItem> + ))} + </SelectContent> + </Select> + </div> + </div> + + <DialogFooter> + <Button + type="button" + variant="outline" + onClick={() => setRowAction(null)} + disabled={isUpdatePending} + > + Cancel + </Button> + <Button + onClick={handleSubmit} + disabled={isUpdatePending || !selectedItemCode} + > + {isUpdatePending ? "Updating..." : "Update Item"} + </Button> + </DialogFooter> + </DialogContent> + </Dialog> + ) + } + + // Delete Dialog + const DeleteDialog = () => { + if (!rowAction || rowAction.type !== "delete") return null + + const item = rowAction.row.original + + const handleDelete = () => { + startDeleteTransition(async () => { + const result = await deleteVendorMaterial(vendorId, item.itemCode) + + if (result.success) { + toast.success(result.message) + setRowAction(null) + } else { + toast.error(result.message) + } + }) + } + + return ( + <AlertDialog + open={true} + onOpenChange={(open) => !open && setRowAction(null)} + > + <AlertDialogContent> + <AlertDialogHeader> + <AlertDialogTitle>Are you sure?</AlertDialogTitle> + <AlertDialogDescription> + This will permanently delete the item "{item.itemName}" (Code: {item.itemCode}). + This action cannot be undone. + </AlertDialogDescription> + </AlertDialogHeader> + <AlertDialogFooter> + <AlertDialogCancel disabled={isDeletePending}> + Cancel + </AlertDialogCancel> + <AlertDialogAction + onClick={handleDelete} + disabled={isDeletePending} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + > + {isDeletePending ? "Deleting..." : "Delete"} + </AlertDialogAction> + </AlertDialogFooter> + </AlertDialogContent> + </AlertDialog> + ) + } + + return ( + <> + <EditDialog /> + <DeleteDialog /> + </> + ) +}
\ No newline at end of file |
