"use client" import * as React from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { z } from "zod" import { toast } from "sonner" import { Upload, X } from "lucide-react" 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 { ProjectSelector } from "@/components/ProjectSelector" import { uploadProjectGtcFile, getProjectsWithGtcFiles } from "../service" import { type Project } from "@/lib/rfqs/service" const addProjectSchema = z.object({ projectId: z.number().min(1, "프로젝트 선택은 필수입니다."), gtcFile: z.instanceof(File, { message: "GTC 파일은 필수입니다." }).optional(), }) type AddProjectFormValues = z.infer interface AddProjectDialogProps { open: boolean onOpenChange: (open: boolean) => void onSuccess?: () => void } export function AddProjectDialog({ open, onOpenChange, onSuccess, }: AddProjectDialogProps) { const [isLoading, setIsLoading] = React.useState(false) const [selectedProject, setSelectedProject] = React.useState(null) const [selectedFile, setSelectedFile] = React.useState(null) const [excludedProjectIds, setExcludedProjectIds] = React.useState([]) const form = useForm({ resolver: zodResolver(addProjectSchema), defaultValues: { projectId: 0, gtcFile: undefined, }, }) // 이미 GTC 파일이 등록된 프로젝트 ID 목록 로드 React.useEffect(() => { async function loadExcludedProjects() { try { const excludedIds = await getProjectsWithGtcFiles(); setExcludedProjectIds(excludedIds); } catch (error) { console.error("제외할 프로젝트 목록 로드 오류:", error); } } if (open) { loadExcludedProjects(); } }, [open]); // 프로젝트 선택 시 폼에 자동으로 채우기 const handleProjectSelect = (project: Project) => { // 이미 GTC 파일이 등록된 프로젝트인지 확인 if (excludedProjectIds.includes(project.id)) { toast.error("이미 GTC 파일이 등록된 프로젝트입니다."); // 선택된 프로젝트 정보 초기화 setSelectedProject(null); form.setValue("projectId", 0); return; } setSelectedProject(project) form.setValue("projectId", project.id) } // 파일 선택 처리 const handleFileSelect = (event: React.ChangeEvent) => { const file = event.target.files?.[0] if (file) { // PDF 파일만 허용 if (file.type !== 'application/pdf') { toast.error("PDF 파일만 업로드 가능합니다.") return } setSelectedFile(file) form.setValue("gtcFile", file) } } // 파일 제거 const handleRemoveFile = () => { setSelectedFile(null) form.setValue("gtcFile", undefined) // input 요소의 value도 초기화 const fileInput = document.getElementById('gtc-file-input') as HTMLInputElement if (fileInput) { fileInput.value = '' } } const onSubmit = async (data: AddProjectFormValues) => { // 프로젝트가 선택되지 않았으면 에러 if (!selectedProject) { toast.error("프로젝트를 선택해주세요.") return } // 이미 GTC 파일이 등록된 프로젝트인지 다시 한번 확인 if (excludedProjectIds.includes(selectedProject.id)) { toast.error("이미 GTC 파일이 등록된 프로젝트입니다.") return } // GTC 파일이 없으면 에러 if (!data.gtcFile) { toast.error("GTC 파일은 필수입니다.") return } setIsLoading(true) try { // GTC 파일 업로드 const fileResult = await uploadProjectGtcFile(selectedProject.id, data.gtcFile) if (!fileResult.success) { toast.error(fileResult.error || "GTC 파일 업로드에 실패했습니다.") return } toast.success("GTC 파일이 성공적으로 업로드되었습니다.") form.reset() setSelectedProject(null) setSelectedFile(null) onOpenChange(false) onSuccess?.() } catch (error) { console.error("GTC 파일 업로드 오류:", error) toast.error("GTC 파일 업로드 중 오류가 발생했습니다.") } finally { setIsLoading(false) } } const handleOpenChange = (newOpen: boolean) => { if (!newOpen) { form.reset() setSelectedProject(null) setSelectedFile(null) } onOpenChange(newOpen) } return ( GTC 파일 추가 기존 프로젝트를 선택하고 GTC 파일을 업로드합니다. (이미 GTC 파일이 등록된 프로젝트는 제외됩니다)
{/* 프로젝트 선택 (필수) */} ( 프로젝트 선택 * )} /> {/* 선택된 프로젝트 정보 표시 (읽기 전용) */} {selectedProject && (

선택된 프로젝트 정보

프로젝트 코드: {selectedProject.projectCode}
프로젝트명: {selectedProject.projectName}
)} {/* GTC 파일 업로드 */} ( GTC 파일 *
{!selectedFile ? (
) : (
{selectedFile.name} ({(selectedFile.size / 1024 / 1024).toFixed(2)} MB)
)}
)} />
) }