"use client" import * as React from "react" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { CalendarIcon, Loader, Upload, X, FileText } from "lucide-react" import { format } from "date-fns" import { toast } from "sonner" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Textarea } from "@/components/ui/textarea" import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Calendar } from "@/components/ui/calendar" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" import { z } from "zod" // Validation schema for editing investigation const editInvestigationSchema = z.object({ confirmedAt: z.union([ z.date(), z.string().transform((str) => str ? new Date(str) : undefined) ]).optional(), evaluationResult: z.enum(["APPROVED", "SUPPLEMENT", "REJECTED"]).optional(), investigationNotes: z.string().max(1000, "QM 의견은 1000자 이내로 입력해주세요.").optional(), attachments: z.array(z.instanceof(File)).optional(), }) type EditInvestigationSchema = z.infer interface EditInvestigationDialogProps { isOpen: boolean onClose: () => void investigation: { id: number confirmedAt?: Date | null evaluationResult?: string | null investigationNotes?: string | null } | null onSubmit: (data: EditInvestigationSchema) => Promise } export function EditInvestigationDialog({ isOpen, onClose, investigation, onSubmit, }: EditInvestigationDialogProps) { const [isPending, startTransition] = React.useTransition() const [selectedFiles, setSelectedFiles] = React.useState([]) const fileInputRef = React.useRef(null) const form = useForm({ resolver: zodResolver(editInvestigationSchema), defaultValues: { confirmedAt: investigation?.confirmedAt || undefined, evaluationResult: investigation?.evaluationResult as "APPROVED" | "SUPPLEMENT" | "REJECTED" | undefined, investigationNotes: investigation?.investigationNotes || "", attachments: [], }, }) // Reset form when investigation changes React.useEffect(() => { if (investigation) { form.reset({ confirmedAt: investigation.confirmedAt || undefined, evaluationResult: investigation.evaluationResult as "APPROVED" | "SUPPLEMENT" | "REJECTED" | undefined, investigationNotes: investigation.investigationNotes || "", attachments: [], }) setSelectedFiles([]) } }, [investigation, form]) // 파일 선택 핸들러 const handleFileSelect = (event: React.ChangeEvent) => { const files = Array.from(event.target.files || []) if (files.length > 0) { const newFiles = [...selectedFiles, ...files] setSelectedFiles(newFiles) form.setValue('attachments', newFiles, { shouldValidate: true }) } } // 파일 제거 핸들러 const removeFile = (index: number) => { const updatedFiles = selectedFiles.filter((_, i) => i !== index) setSelectedFiles(updatedFiles) form.setValue('attachments', updatedFiles, { shouldValidate: true }) } // 파일 크기 포맷팅 const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes' const k = 1024 const sizes = ['Bytes', 'KB', 'MB', 'GB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i] } const handleSubmit = async (values: EditInvestigationSchema) => { startTransition(async () => { try { // 선택된 파일들을 values에 포함 const submitData = { ...values, attachments: selectedFiles, } await onSubmit(submitData) toast.success("실사 정보가 업데이트되었습니다!") onClose() } catch (error) { console.error("실사 정보 업데이트 오류:", error) toast.error("실사 정보 업데이트 중 오류가 발생했습니다.") } }) } return ( 실사 정보 수정 구매자체평가 실사 정보를 수정합니다.
{/* 실사 확정일 */} ( 실사 확정일 )} /> {/* 평가 결과 */} ( 평가 결과 )} /> {/* 구매 의견 */} ( 구매 의견