"use client" import * as React from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { z } from "zod" import { Upload } from "lucide-react" import { toast } from "sonner" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Dropzone, DropzoneDescription, DropzoneInput, DropzoneTitle, DropzoneUploadIcon, DropzoneZone, } from "@/components/ui/dropzone" import { FileList, FileListAction, FileListDescription, FileListHeader, FileListIcon, FileListInfo, FileListItem, FileListName, FileListSize, } from "@/components/ui/file-list" import { Button } from "@/components/ui/button" import { Textarea } from "@/components/ui/textarea" import { addRevisionToAttachment } from "../service" // 리비전 추가 폼 스키마 const addRevisionSchema = z.object({ revisionComment: z.string().optional(), file: z.instanceof(File, { message: "파일을 선택해주세요.", }), }) type AddRevisionFormData = z.infer interface AddRevisionDialogProps { open: boolean onOpenChange: (open: boolean) => void attachmentId: number currentRevision: string originalFileName: string onSuccess?: () => void } export function AddRevisionDialog({ open, onOpenChange, attachmentId, currentRevision, originalFileName, onSuccess }: AddRevisionDialogProps) { const [isSubmitting, setIsSubmitting] = React.useState(false) const [uploadProgress, setUploadProgress] = React.useState(0) const form = useForm({ resolver: zodResolver(addRevisionSchema), defaultValues: { revisionComment: "", file: undefined, }, }) const selectedFile = form.watch("file") // 다이얼로그 닫기 핸들러 const handleOpenChange = (newOpen: boolean) => { if (!newOpen && !isSubmitting) { form.reset() } onOpenChange(newOpen) } // 파일 선택 처리 const handleFileChange = (files: File[]) => { if (files.length === 0) return const file = files[0] // 파일 크기 검증 const maxFileSize = 10 * 1024 * 1024 // 10MB if (file.size > maxFileSize) { toast.error(`파일이 너무 큽니다. (최대 10MB)`) return } form.setValue("file", file) form.clearErrors("file") } // 파일 제거 const removeFile = () => { form.resetField("file") } // 파일 업로드 API 호출 const uploadFile = async (file: File): Promise<{ fileName: string originalFileName: string filePath: string fileSize: number fileType: string }> => { const formData = new FormData() formData.append("attachmentId", attachmentId.toString()) formData.append("file", file) formData.append("isRevision", "true") const response = await fetch("/api/upload/rfq-attachment-revision", { method: "POST", body: formData, }) if (!response.ok) { const error = await response.json() throw new Error(error.message || "파일 업로드 실패") } return response.json() } // 폼 제출 const onSubmit = async (data: AddRevisionFormData) => { setIsSubmitting(true) setUploadProgress(0) try { // 1단계: 파일 업로드 setUploadProgress(30) const uploadedFile = await uploadFile(data.file) // 2단계: DB 리비전 레코드 생성 setUploadProgress(70) const result = await addRevisionToAttachment(attachmentId, { fileName: uploadedFile.fileName, originalFileName: uploadedFile.originalFileName, filePath: uploadedFile.filePath, fileSize: uploadedFile.fileSize, fileType: uploadedFile.fileType, revisionComment: data.revisionComment, }) setUploadProgress(100) if (result.success) { toast.success(result.message) form.reset() handleOpenChange(false) onSuccess?.() } else { toast.error(result.message) } } catch (error) { console.error("Upload error:", error) toast.error(error instanceof Error ? error.message : "리비전 추가 중 오류가 발생했습니다.") } finally { setIsSubmitting(false) setUploadProgress(0) } } // 다음 리비전 번호 계산 const getNextRevision = (current: string) => { const match = current.match(/Rev\.(\d+)/) if (match) { const num = parseInt(match[1]) + 1 return `Rev.${num}` } return "Rev.1" } const nextRevision = getNextRevision(currentRevision) return ( 새 리비전 추가 "{originalFileName}"의 새 버전을 업로드합니다. 현재 {currentRevision} → {nextRevision}
{/* 리비전 코멘트 */} ( 리비전 코멘트 (선택)