"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 { Button } from "@/components/ui/button" import { Textarea } from "@/components/ui/textarea" import { Input } from "@/components/ui/input" import { Progress } from "@/components/ui/progress" const updateRevisionSchema = z.object({ revisionComment: z.string().min(1, "리비전 설명을 입력해주세요"), file: z.instanceof(File, { message: "새 버전 파일을 선택해주세요", }).refine((file) => file.size <= 100 * 1024 * 1024, { message: "파일 크기는 100MB를 초과할 수 없습니다.", }), }) type UpdateRevisionFormData = z.infer interface UpdateRevisionDialogProps { open: boolean; onOpenChange: (open: boolean) => void; attachment: { id: number; originalFileName?: string | null; currentRevision?: string | null; }; onSuccess?: () => void; } export function UpdateRevisionDialog({ open, onOpenChange, attachment, onSuccess, }: UpdateRevisionDialogProps) { const [isSubmitting, setIsSubmitting] = React.useState(false) const [uploadProgress, setUploadProgress] = React.useState(0) const form = useForm({ resolver: zodResolver(updateRevisionSchema), defaultValues: { revisionComment: "", }, }) const onSubmit = async (data: UpdateRevisionFormData) => { setIsSubmitting(true); setUploadProgress(0); try { const formData = new FormData(); formData.append("attachmentId", attachment.id.toString()); formData.append("revisionComment", data.revisionComment); formData.append("file", data.file); // 진행률 시뮬레이션 setUploadProgress(30); const response = await fetch("/api/rfq-attachments/revision", { method: "POST", body: formData, }); setUploadProgress(70); if (!response.ok) { const error = await response.json(); throw new Error(error.message || "리비전 업데이트 실패"); } const result = await response.json(); setUploadProgress(100); if (result.success) { toast.success(result.message); form.reset(); onOpenChange(false); onSuccess?.(); } else { toast.error(result.message); } } catch (error) { toast.error(error instanceof Error ? error.message : "파일 업로드 중 오류가 발생했습니다"); } finally { setIsSubmitting(false); setUploadProgress(0); } } return ( 새 버전 업로드 {attachment.originalFileName && (
현재 파일:
{attachment.originalFileName} {attachment.currentRevision && ` (Rev. ${attachment.currentRevision})`}
)}
( 새 버전 파일 { const file = e.target.files?.[0]; if (file) { onChange(file); // 파일 크기 검증 if (file.size > 100 * 1024 * 1024) { form.setError("file", { message: "파일 크기는 100MB를 초과할 수 없습니다." }); } } }} disabled={isSubmitting} {...field} /> {value && (

선택된 파일: {value.name} ({(value.size / 1024 / 1024).toFixed(2)}MB)

)}
)} /> ( 리비전 설명