diff options
Diffstat (limited to 'lib/vendor-document-list/table/revision-upload-dialog.tsx')
| -rw-r--r-- | lib/vendor-document-list/table/revision-upload-dialog.tsx | 132 |
1 files changed, 116 insertions, 16 deletions
diff --git a/lib/vendor-document-list/table/revision-upload-dialog.tsx b/lib/vendor-document-list/table/revision-upload-dialog.tsx index 546fa7a3..16fc9fbb 100644 --- a/lib/vendor-document-list/table/revision-upload-dialog.tsx +++ b/lib/vendor-document-list/table/revision-upload-dialog.tsx @@ -66,7 +66,29 @@ const revisionUploadSchema = z.object({ uploaderName: z.string().optional(), comment: z.string().optional(), attachments: z.array(z.instanceof(File)).min(1, "최소 1개 파일이 필요합니다"), -}) + // ✅ B3 문서용 usage 필드 추가 + usage: z.string().optional(), +}).refine((data) => { + // B3 문서이고 특정 stage인 경우 usage 필수 + // 이 검증은 컴포넌트 내에서 조건부로 처리 + return true; +}, { + message: "Usage는 필수입니다", + path: ["usage"], +}); + +const getUsageOptions = (stageName: string): string[] => { + const stageNameLower = stageName.toLowerCase(); + + if (stageNameLower.includes('approval')) { + return ['Approval (Partial)', 'Approval (Full)']; + } else if (stageNameLower.includes('working')) { + return ['Working (Partial)', 'Working (Full)']; + } + + return []; +}; + type RevisionUploadSchema = z.infer<typeof revisionUploadSchema> @@ -93,7 +115,7 @@ export function RevisionUploadDialog({ presetStage, presetRevision, mode = 'new', - onUploadComplete, // ✅ 추가된 prop + onUploadComplete, }: RevisionUploadDialogProps) { const targetSystem = React.useMemo( @@ -106,7 +128,6 @@ export function RevisionUploadDialog({ const [uploadProgress, setUploadProgress] = React.useState(0) const router = useRouter() - // ✅ next-auth session 가져오기 const { data: session } = useSession() // 사용 가능한 스테이지 옵션 @@ -125,17 +146,33 @@ export function RevisionUploadDialog({ uploaderName: session?.user?.name || "", comment: "", attachments: [], + usage: "", // ✅ usage 기본값 추가 }, }) - // ✅ session이 로드되면 uploaderName 업데이트 + // ✅ 현재 선택된 stage 값을 watch + const currentStage = form.watch('stage') + + // ✅ B3 문서 여부 확인 + const isB3Document = document?.drawingKind === 'B3' + + // ✅ 현재 stage에 따른 usage 옵션 + const usageOptions = React.useMemo(() => { + if (!isB3Document || !currentStage) return [] + return getUsageOptions(currentStage) + }, [isB3Document, currentStage]) + + // ✅ usage 필드가 필요한지 확인 + const isUsageRequired = isB3Document && usageOptions.length > 0 + + // session이 로드되면 uploaderName 업데이트 React.useEffect(() => { if (session?.user?.name) { form.setValue('uploaderName', session.user.name) } }, [session?.user?.name, form]) - // ✅ presetStage와 presetRevision이 변경될 때 폼 값 업데이트 + // presetStage와 presetRevision이 변경될 때 폼 값 업데이트 React.useEffect(() => { if (presetStage) { form.setValue('stage', presetStage) @@ -145,6 +182,22 @@ export function RevisionUploadDialog({ } }, [presetStage, presetRevision, form]) + // ✅ stage가 변경될 때 usage 값 리셋 + React.useEffect(() => { + if (isB3Document) { + const newUsageOptions = getUsageOptions(currentStage) + if (newUsageOptions.length === 0) { + form.setValue('usage', '') + } else { + // 기존 값이 새로운 옵션에 없으면 리셋 + const currentUsage = form.getValues('usage') + if (currentUsage && !newUsageOptions.includes(currentUsage)) { + form.setValue('usage', '') + } + } + } + }, [currentStage, isB3Document, form]) + // 파일 드롭 처리 const handleDropAccepted = (acceptedFiles: File[]) => { const newFiles = [...selectedFiles, ...acceptedFiles] @@ -159,26 +212,22 @@ export function RevisionUploadDialog({ form.setValue('attachments', updatedFiles, { shouldValidate: true }) } - // ✅ 캐시 갱신 함수 + // 캐시 갱신 함수 const refreshCaches = async () => { try { - // 1. 서버 컴포넌트 캐시 갱신 (Enhanced Documents 등) router.refresh() - // 2. SWR 캐시 갱신 (Sync Status) if (document?.contractId) { await mutate(`/api/sync/status/${document.contractId}/${targetSystem}`) console.log('✅ Sync status cache refreshed') } - // 3. 다른 관련 SWR 캐시들도 갱신 (필요시) await mutate(key => typeof key === 'string' && key.includes('sync') && key.includes(String(document?.contractId)) ) - // 4. 상위 컴포넌트 콜백 호출 onUploadComplete?.() console.log('✅ All caches refreshed after upload') @@ -187,10 +236,19 @@ export function RevisionUploadDialog({ } } - // 업로드 처리 + // ✅ 업로드 처리 - usage 필드 검증 및 전송 async function onSubmit(data: RevisionUploadSchema) { if (!document) return + // ✅ B3 문서에서 usage가 필요한 경우 검증 + if (isUsageRequired && !data.usage) { + form.setError('usage', { + type: 'required', + message: 'Usage 선택은 필수입니다' + }) + return + } + setIsUploading(true) setUploadProgress(0) @@ -210,6 +268,11 @@ export function RevisionUploadDialog({ formData.append("comment", data.comment) } + // ✅ B3 문서인 경우 usage 추가 + if (isB3Document && data.usage) { + formData.append("usage", data.usage) + } + // 파일들 추가 data.attachments.forEach((file) => { formData.append("attachments", file) @@ -220,7 +283,6 @@ export function RevisionUploadDialog({ setUploadProgress(Math.min(progress, 95)) } - // 파일 크기에 따른 진행률 시뮬레이션 const totalSize = data.attachments.reduce((sum, file) => sum + file.size, 0) let uploadedSize = 0 @@ -230,7 +292,6 @@ export function RevisionUploadDialog({ updateProgress(progress) }, 300) - // ✅ 실제 API 호출 const response = await fetch('/api/revision-upload', { method: 'POST', body: formData, @@ -253,7 +314,6 @@ export function RevisionUploadDialog({ console.log('✅ 업로드 성공:', result) - // ✅ 캐시 갱신 및 다이얼로그 닫기 setTimeout(async () => { await refreshCaches() handleDialogClose() @@ -275,6 +335,7 @@ export function RevisionUploadDialog({ uploaderName: session?.user?.name || "", comment: "", attachments: [], + usage: "", // ✅ usage 리셋 추가 }) setSelectedFiles([]) setIsUploading(false) @@ -295,14 +356,19 @@ export function RevisionUploadDialog({ mode === 'new' ? "문서에 새 리비전을 업로드합니다." : "기존 리비전에 파일을 추가합니다."} </DialogDescription> - <div className="flex items-center gap-2 pt-2"> + <div className="flex items-center gap-2 pt-2 flex-wrap"> <Badge variant={projectType === "ship" ? "default" : "secondary"}> {projectType === "ship" ? "조선 프로젝트" : "플랜트 프로젝트"} </Badge> - {/* ✅ 타겟 시스템 표시 추가 */} <Badge variant="outline" className="text-xs"> → {targetSystem} </Badge> + {/* ✅ B3 문서 표시 */} + {isB3Document && ( + <Badge variant="outline" className="text-xs bg-orange-50 text-orange-700 border-orange-200"> + B3 문서 + </Badge> + )} {session?.user?.name && ( <Badge variant="outline" className="text-xs"> 업로더: {session.user.name} @@ -379,6 +445,40 @@ export function RevisionUploadDialog({ /> </div> + {/* ✅ B3 문서용 Usage 필드 - 조건부 표시 */} + {isB3Document && usageOptions.length > 0 && ( + <FormField + control={form.control} + name="usage" + render={({ field }) => ( + <FormItem> + <FormLabel className="flex items-center gap-2"> + 용도 + {isUsageRequired && <span className="text-red-500">*</span>} + </FormLabel> + <Select onValueChange={field.onChange} value={field.value}> + <FormControl> + <SelectTrigger> + <SelectValue placeholder="용도를 선택하세요" /> + </SelectTrigger> + </FormControl> + <SelectContent> + {usageOptions.map((usage) => ( + <SelectItem key={usage} value={usage}> + {usage} + </SelectItem> + ))} + </SelectContent> + </Select> + <FormMessage /> + <p className="text-xs text-gray-500"> + {currentStage} 스테이지에 필요한 용도를 선택하세요. + </p> + </FormItem> + )} + /> + )} + <FormField control={form.control} name="uploaderName" |
