"use client" import * as React from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { Loader, Send, User } from "lucide-react" import { toast } from "sonner" import { z } from "zod" import { useMediaQuery } from "@/hooks/use-media-query" import { Button } from "@/components/ui/button" import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, } from "@/components/ui/drawer" import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription, } from "@/components/ui/form" import { type Row } from "@tanstack/react-table" import { Badge } from "@/components/ui/badge" import { ScrollArea } from "@/components/ui/scroll-area" import { VendorWithCbeFields } from "@/config/vendorCbeColumnsConfig" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { createCbeEvaluation } from "@/lib/rfqs/service" // 컴포넌트 내부에서 사용할 폼 스키마 정의 const formSchema = z.object({ paymentTerms: z.string().min(1, "결제 조건을 입력하세요"), incoterms: z.string().min(1, "Incoterms를 입력하세요"), deliverySchedule: z.string().min(1, "배송 일정을 입력하세요"), notes: z.string().optional(), }) type FormValues = z.infer interface InviteVendorsDialogProps extends React.ComponentPropsWithoutRef { rfqId: number vendors: Row["original"][] currentUserId?: number currentUser?: { id: string name?: string | null email?: string | null image?: string | null companyId?: number | null domain?: string | null } showTrigger?: boolean onSuccess?: () => void hasMultipleRfqIds?: boolean } export function InviteVendorsDialog({ rfqId, vendors, currentUserId, currentUser, showTrigger = true, onSuccess, hasMultipleRfqIds, ...props }: InviteVendorsDialogProps) { const [files, setFiles] = React.useState(null) const isDesktop = useMediaQuery("(min-width: 640px)") const [isSubmitting, setIsSubmitting] = React.useState(false) // 로컬 스키마와 폼 값을 사용하도록 수정 const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { paymentTerms: "", incoterms: "", deliverySchedule: "", notes: "", }, mode: "onChange", }) // 폼 상태 감시 const { formState } = form const isValid = formState.isValid && !!form.getValues("paymentTerms") && !!form.getValues("incoterms") && !!form.getValues("deliverySchedule") // 디버깅용 상태 트래킹 React.useEffect(() => { const subscription = form.watch((value) => { // 폼 값이 변경될 때마다 실행되는 콜백 console.log("Form values changed:", value); }); return () => subscription.unsubscribe(); }, [form]); async function onSubmit(data: FormValues) { try { setIsSubmitting(true) // 기본 FormData 생성 const formData = new FormData() // rfqId 추가 formData.append("rfqId", String(rfqId)) // 폼 데이터 추가 Object.entries(data).forEach(([key, value]) => { if (value !== undefined && value !== null) { formData.append(key, String(value)) } }) // 현재 사용자 ID 추가 if (currentUserId) { formData.append("evaluatedBy", String(currentUserId)) } // 협력업체 ID만 추가 (서버에서 연락처 정보를 조회) vendors.forEach((vendor) => { formData.append("vendorIds[]", String(vendor.vendorId)) }) // 파일 추가 (있는 경우에만) if (files && files.length > 0) { for (let i = 0; i < files.length; i++) { formData.append("files", files[i]) } } // 서버 액션 호출 const response = await createCbeEvaluation(formData) if (response.error) { toast.error(response.error) return } // 성공 처리 toast.success(`${vendors.length}개 협력업체에 CBE 평가가 성공적으로 전송되었습니다!`) form.reset() setFiles(null) props.onOpenChange?.(false) onSuccess?.() } catch (error) { console.error(error) toast.error("CBE 평가 생성 중 오류가 발생했습니다.") } finally { setIsSubmitting(false) } } function handleDialogOpenChange(nextOpen: boolean) { if (!nextOpen) { form.reset() setFiles(null) } props.onOpenChange?.(nextOpen) } // 필수 필드 라벨에 추가할 요소 const RequiredLabel = ( * ) const formContent = (
{/* 선택된 협력업체 정보 표시 */}
선택된 협력업체 ({vendors.length})
{vendors.map((vendor, index) => ( {vendor.vendorName || `협력업체 #${vendor.vendorCode}`} ))}
선택된 모든 협력업체의 등록된 연락처에게 CBE 평가 알림이 전송됩니다.
{/* 작성자 정보 (읽기 전용) */} {currentUser && (
작성자
{currentUser.image ? ( {currentUser.name?.charAt(0) || } ) : ( {currentUser.name?.charAt(0) || } )}

{currentUser.name || "Unknown User"}

{currentUser.email || ""}

)} {/* 결제 조건 - 필수 필드 */} ( 결제 조건{RequiredLabel} )} /> {/* Incoterms - 필수 필드 */} ( Incoterms{RequiredLabel} )} /> {/* 배송 일정 - 필수 필드 */} ( 배송 일정{RequiredLabel}