From ef4c533ebacc2cdc97e518f30e9a9350004fcdfb Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 28 Apr 2025 02:13:30 +0000 Subject: ~20250428 작업사항 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tbe/table/tbe-result-dialog.tsx | 208 ++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 lib/tbe/table/tbe-result-dialog.tsx (limited to 'lib/tbe/table/tbe-result-dialog.tsx') diff --git a/lib/tbe/table/tbe-result-dialog.tsx b/lib/tbe/table/tbe-result-dialog.tsx new file mode 100644 index 00000000..59e2f49b --- /dev/null +++ b/lib/tbe/table/tbe-result-dialog.tsx @@ -0,0 +1,208 @@ +"use client" + +import * as React from "react" +import { toast } from "sonner" + +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { Textarea } from "@/components/ui/textarea" +import { Label } from "@/components/ui/label" +import { VendorWithTbeFields } from "@/config/vendorTbeColumnsConfig" +import { getErrorMessage } from "@/lib/handle-error" +import { saveTbeResult } from "@/lib/rfqs/service" + +// Define the props for the TbeResultDialog component +interface TbeResultDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + tbe: VendorWithTbeFields | null + onRefresh?: () => void +} + +// Define TBE result options +const TBE_RESULT_OPTIONS = [ + { value: "pass", label: "Pass", badgeVariant: "default" }, + { value: "non-pass", label: "Non-Pass", badgeVariant: "destructive" }, + { value: "conditional pass", label: "Conditional Pass", badgeVariant: "secondary" }, +] as const + +type TbeResultOption = typeof TBE_RESULT_OPTIONS[number]["value"] + +export function TbeResultDialog({ + open, + onOpenChange, + tbe, + onRefresh, +}: TbeResultDialogProps) { + // Initialize state for form inputs + const [result, setResult] = React.useState("") + const [note, setNote] = React.useState("") + const [isSubmitting, setIsSubmitting] = React.useState(false) + + // Update form values when the tbe prop changes + React.useEffect(() => { + if (tbe) { + setResult((tbe.tbeResult as TbeResultOption) || "") + setNote(tbe.tbeNote || "") + } + }, [tbe]) + + // Reset form when dialog closes + React.useEffect(() => { + if (!open) { + // Small delay to avoid visual glitches when dialog is closing + const timer = setTimeout(() => { + if (!tbe) { + setResult("") + setNote("") + } + }, 300) + return () => clearTimeout(timer) + } + }, [open, tbe]) + + // Handle form submission with server action + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + + if (!tbe || !result) return + + setIsSubmitting(true) + + try { + // Call the server action to save the TBE result + const response = await saveTbeResult({ + id: tbe.tbeId ?? 0, // This is the id in the rfq_evaluations table + vendorId: tbe.vendorId, // This is the vendorId in the rfq_evaluations table + result: result, // The selected evaluation result + notes: note, // The evaluation notes + }) + + if (!response.success) { + throw new Error(response.message || "Failed to save TBE result") + } + + // Show success toast + toast.success("TBE result saved successfully") + + // Close the dialog + onOpenChange(false) + + // Refresh the data if refresh callback is provided + if (onRefresh) { + onRefresh() + } + } catch (error) { + // Show error toast + toast.error(`Failed to save: ${getErrorMessage(error)}`) + } finally { + setIsSubmitting(false) + } + } + + // Find the selected result option + const selectedOption = TBE_RESULT_OPTIONS.find(option => option.value === result) + + return ( + + + + + {tbe?.tbeResult ? "Edit TBE Result" : "Enter TBE Result"} + + {tbe && ( + +
+ + Vendor: {tbe.vendorName} + + + RFQ Code: {tbe.rfqCode} + + {tbe.email && ( + + Email: {tbe.email} + + )} +
+
+ )} +
+ +
+
+ + +
+ +
+ +