"use client" import * as React from "react" import { zodResolver } from "@hookform/resolvers/zod" import { Loader } from "lucide-react" import { useForm } from "react-hook-form" import { toast } from "sonner" import { z } from "zod" import { Button } from "@/components/ui/button" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Input } from "@/components/ui/input" import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@/components/ui/sheet" import { Textarea } from "@/components/ui/textarea" import { VendorWithCbeFields } from "@/config/vendorCbeColumnsConfig" import { getCommercialResponseByResponseId, updateCommercialResponse } from "../service" // Define schema for form validation (client-side) const commercialResponseFormSchema = z.object({ responseStatus: z.enum(["PENDING", "IN_PROGRESS", "SUBMITTED", "REJECTED", "ACCEPTED"]), totalPrice: z.coerce.number().optional(), currency: z.string().default("USD"), paymentTerms: z.string().optional(), incoterms: z.string().optional(), deliveryPeriod: z.string().optional(), warrantyPeriod: z.string().optional(), validityPeriod: z.string().optional(), priceBreakdown: z.string().optional(), commercialNotes: z.string().optional(), }) type CommercialResponseFormInput = z.infer interface CommercialResponseSheetProps extends React.ComponentPropsWithRef { rfq: VendorWithCbeFields | null responseId: number | null // This is the vendor_responses.id onSuccess?: () => void } export function CommercialResponseSheet({ rfq, responseId, onSuccess, ...props }: CommercialResponseSheetProps) { const [isSubmitting, startSubmitTransition] = React.useTransition() const [isLoading, setIsLoading] = React.useState(true) const form = useForm({ resolver: zodResolver(commercialResponseFormSchema), defaultValues: { responseStatus: "PENDING", totalPrice: undefined, currency: "USD", paymentTerms: "", incoterms: "", deliveryPeriod: "", warrantyPeriod: "", validityPeriod: "", priceBreakdown: "", commercialNotes: "", }, }) // Load existing commercial response data when sheet opens React.useEffect(() => { async function loadCommercialResponse() { if (!responseId) return setIsLoading(true) try { // Use the helper function to get existing data const existingResponse = await getCommercialResponseByResponseId(responseId) if (existingResponse) { // If we found existing data, populate the form form.reset({ responseStatus: existingResponse.responseStatus, totalPrice: existingResponse.totalPrice, currency: existingResponse.currency || "USD", paymentTerms: existingResponse.paymentTerms || "", incoterms: existingResponse.incoterms || "", deliveryPeriod: existingResponse.deliveryPeriod || "", warrantyPeriod: existingResponse.warrantyPeriod || "", validityPeriod: existingResponse.validityPeriod || "", priceBreakdown: existingResponse.priceBreakdown || "", commercialNotes: existingResponse.commercialNotes || "", }) } else if (rfq) { // If no existing data but we have rfq data with some values already form.reset({ responseStatus: rfq.commercialResponseStatus as any || "PENDING", totalPrice: rfq.totalPrice || undefined, currency: rfq.currency || "USD", paymentTerms: rfq.paymentTerms || "", incoterms: rfq.incoterms || "", deliveryPeriod: rfq.deliveryPeriod || "", warrantyPeriod: rfq.warrantyPeriod || "", validityPeriod: rfq.validityPeriod || "", priceBreakdown: "", commercialNotes: "", }) } } catch (error) { console.error("Failed to load commercial response data:", error) toast.error("상업 응답 데이터를 불러오는데 실패했습니다") } finally { setIsLoading(false) } } loadCommercialResponse() }, [responseId, rfq, form]) function onSubmit(formData: CommercialResponseFormInput) { if (!responseId) { toast.error("응답 ID를 찾을 수 없습니다") return } if (!rfq?.vendorId) { toast.error("협력업체 ID를 찾을 수 없습니다") return } startSubmitTransition(async () => { try { // Pass both responseId and vendorId to the server action const result = await updateCommercialResponse({ responseId, vendorId: rfq.vendorId, // Include vendorId for revalidateTag ...formData, }) if (!result.success) { toast.error(result.error || "응답 제출 중 오류가 발생했습니다") return } toast.success("Commercial response successfully submitted") props.onOpenChange?.(false) if (onSuccess) { onSuccess() } } catch (error) { console.error("Error submitting response:", error) toast.error("응답 제출 중 오류가 발생했습니다") } }) } return ( Commercial Response {rfq?.rfqCode && {rfq.rfqCode}}
Please provide your commercial response for this RFQ
{isLoading ? (
) : (
( Response Status )} />
( Total Price { const value = e.target.value === '' ? undefined : parseFloat(e.target.value); field.onChange(value); }} /> )} /> ( Currency )} />
{/* Other form fields remain the same */} ( Payment Terms )} /> ( Incoterms )} /> ( Delivery Period )} /> ( Warranty Period )} /> ( Validity Period )} /> ( Price Breakdown (Optional)