"use client" import * as React from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { z } from "zod" import { Button } from "@/components/ui/button" import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@/components/ui/sheet" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { toast } from "sonner" import { Upload, X, FileText } from "lucide-react" // 협력업체 정보 입력 스키마 const vendorInfoSchema = z.object({ // 실사 장소 정보 factoryName: z.string().min(1, "실사 장소명을 입력해주세요."), factoryLocation: z.string().min(1, "실사 지역을 입력해주세요."), factoryAddress: z.string().min(1, "실사 주소를 입력해주세요."), // 실사 참석자 정보 factoryPicName: z.string().min(1, "실사 참석자 이름을 입력해주세요."), factoryPicPhone: z.string().min(1, "실사 참석자 전화번호를 입력해주세요."), factoryPicEmail: z.string().email("올바른 이메일 주소를 입력해주세요."), // 실사 장소 이동 방법 factoryDirections: z.string().min(1, "실사 장소 이동 방법을 입력해주세요."), // 실사 장소 출입절차 accessProcedure: z.string().min(1, "실사 장소 출입절차를 입력해주세요."), // 첨부파일 hasAttachments: z.boolean().default(false), // 기타 정보 otherInfo: z.string().optional(), }) export type VendorInfoFormValues = z.infer interface VendorInfoSheetProps { isOpen: boolean onClose: () => void onSubmit: (data: VendorInfoFormValues & { attachments?: File[] }) => Promise siteVisitRequestId: number initialData?: VendorInfoFormValues | null } export function VendorInfoSheet({ isOpen, onClose, onSubmit, siteVisitRequestId, initialData, }: VendorInfoSheetProps) { const [isPending, setIsPending] = React.useState(false) const [selectedFiles, setSelectedFiles] = React.useState([]) const fileInputRef = React.useRef(null) const form = useForm({ resolver: zodResolver(vendorInfoSchema), defaultValues: { factoryName: "", factoryLocation: "", factoryAddress: "", factoryPicName: "", factoryPicPhone: "", factoryPicEmail: "", factoryDirections: "", accessProcedure: "", hasAttachments: false, otherInfo: "", }, }) // Sheet가 열릴 때마다 폼 재설정 React.useEffect(() => { if (isOpen) { if (initialData) { form.reset(initialData) } else { form.reset({ factoryName: "", factoryLocation: "", factoryAddress: "", factoryPicName: "", factoryPicPhone: "", factoryPicEmail: "", factoryDirections: "", accessProcedure: "", hasAttachments: false, otherInfo: "", }) } } }, [isOpen, form, initialData]) // 파일 업로드 핸들러 const handleFileUpload = (event: React.ChangeEvent) => { const files = event.target.files if (!files || files.length === 0) return const newFiles = Array.from(files) // 파일 크기 체크 (10MB) const validFiles = newFiles.filter(file => { if (file.size > 10 * 1024 * 1024) { toast.error(`${file.name}: 파일 크기가 10MB를 초과합니다.`) return false } return true }) if (validFiles.length > 0) { setSelectedFiles(prev => [...prev, ...validFiles]) form.setValue("hasAttachments", true) toast.success(`${validFiles.length}개 파일이 추가되었습니다.`) } } // 파일 삭제 핸들러 const handleRemoveFile = (index: number) => { setSelectedFiles(prev => prev.filter((_, i) => i !== index)) const newFileCount = selectedFiles.length - 1 form.setValue("hasAttachments", newFileCount > 0) } async function handleSubmit(data: VendorInfoFormValues) { setIsPending(true) try { // 첨부파일 정보를 포함하여 제출 const submitData = { ...data, siteVisitRequestId, attachments: selectedFiles } await onSubmit(submitData) toast.success("협력업체 정보가 성공적으로 제출되었습니다.") onClose() } catch (error) { toast.error("협력업체 정보 제출 중 오류가 발생했습니다.") console.error("협력업체 정보 제출 오류:", error) } finally { setIsPending(false) } } return ( !open && onClose()}> 협력업체 정보 입력 방문실사 관련 협력업체 정보를 입력해주세요.
{/* 실사 장소 정보 */}

실사 장소 정보

( 실사 장소명 * )} /> ( 실사 지역 * )} />
( 실사 주소 *