From ff902243a658067fae858a615c0629aa2e0a4837 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Wed, 11 Jun 2025 12:18:38 +0000
Subject: (대표님) 20250611 21시 15분 OCR 등
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../table/revision-upload-dialog.tsx               | 132 ++++++++++++++++++---
 1 file changed, 116 insertions(+), 16 deletions(-)

(limited to 'lib/vendor-document-list/table/revision-upload-dialog.tsx')

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"
-- 
cgit v1.2.3

