From 94082bfe915d3b0337f8929a2bb27828abb5d3c7 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Thu, 21 Aug 2025 09:10:06 +0000 Subject: (최겸) 협력업체 기본정보 기능 개발 및 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendors/[id]/info/basic/basic-info-client.tsx | 302 ++++++++++++++++----- 1 file changed, 230 insertions(+), 72 deletions(-) (limited to 'app') diff --git a/app/[lng]/evcp/(evcp)/vendors/[id]/info/basic/basic-info-client.tsx b/app/[lng]/evcp/(evcp)/vendors/[id]/info/basic/basic-info-client.tsx index e92edc11..0e4dccf4 100644 --- a/app/[lng]/evcp/(evcp)/vendors/[id]/info/basic/basic-info-client.tsx +++ b/app/[lng]/evcp/(evcp)/vendors/[id]/info/basic/basic-info-client.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useTransition } from "react"; +import React, { useState, useTransition } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -24,6 +24,8 @@ import { DocumentStatusDialog } from "@/components/vendor-regular-registrations/ import { AdditionalInfoDialog } from "@/components/vendor-regular-registrations/additional-info-dialog"; import { getSiteVisitRequestsByVendorId } from "@/lib/site-visit/service"; import { fetchVendorRegistrationStatus } from "@/lib/vendor-regular-registrations/service"; +import { getVendorAttachmentsByType, getVendorPeriodicGrade, getVendorTypeInfo } from "@/lib/vendor-info/service"; +import { downloadFile } from "@/lib/file-download"; import { Table, TableBody, @@ -330,6 +332,11 @@ export default function BasicInfoClient({ // 각 다이얼로그에 필요한 데이터 상태 const [selectedSiteVisitRequest, setSelectedSiteVisitRequest] = useState(null); const [registrationData, setRegistrationData] = useState(null); + + // 첨부파일 및 평가 정보 상태 + const [attachmentsByType, setAttachmentsByType] = useState>({}); + const [periodicGrade, setPeriodicGrade] = useState(null); + const [vendorTypeInfo, setVendorTypeInfo] = useState(null); const [formData, setFormData] = useState({ vendorName: initialData?.vendorName || "", representativeName: initialData?.representativeName || "", @@ -400,13 +407,6 @@ export default function BasicInfoClient({ setFormData((prev) => ({ ...prev, [field]: value })); }; - const handleFileManagement = (attachmentType: string) => { - // TODO: 파일 관리 다이얼로그 열기 - toast.info( - `[개발중] ${attachmentType} [필요시] 조회/삭제/추가 기능을 구현 예정입니다.` - ); - }; - // PQ 조회 핸들러 const handlePQView = () => { setPqDialogOpen(true); @@ -437,14 +437,29 @@ export default function BasicInfoClient({ return; } - // 등록 데이터가 있는지 확인 - const registrationRecord = result.data; - if (!registrationRecord || !registrationRecord.documentSubmissions) { - toast.info("정규등록 정보가 없습니다."); - return; - } + // DocumentStatusDialog가 기대하는 형태로 데이터 구성 + const dialogData = { + // 기본 정보 + companyName: result.data.vendor.vendorName, + businessNumber: result.data.vendor.taxId, + representative: result.data.vendor.representativeName, + country: result.data.vendor.country, + status: result.data.registration?.status || "정보없음", + + // 문서 제출 현황 - documentSubmissions 속성으로 매핑 + documentSubmissions: result.data.documentStatus, + + // 기본계약 정보 + basicContracts: result.data.basicContracts || [], + + // 안전적격성 평가 + safetyQualificationContent: result.data.registration?.safetyQualificationContent || null, + + // 추가정보 완료 여부 + additionalInfo: result.data.additionalInfoCompleted, + }; - setRegistrationData(registrationRecord); + setRegistrationData(dialogData); setContractDialogOpen(true); } catch (error) { console.error("기본계약 정보 조회 오류:", error); @@ -457,6 +472,77 @@ export default function BasicInfoClient({ setAdditionalInfoDialogOpen(true); }; + // 첨부파일 및 평가 정보 로드 + const loadVendorData = async () => { + try { + // 첨부파일 조회 + const attachmentsResult = await getVendorAttachmentsByType(parseInt(vendorId)); + if (attachmentsResult.success && attachmentsResult.data) { + setAttachmentsByType(attachmentsResult.data); + } + + // 정기평가 등급 조회 + const gradeResult = await getVendorPeriodicGrade(parseInt(vendorId)); + if (gradeResult.success && gradeResult.data) { + setPeriodicGrade(gradeResult.data.finalGrade); + } + + // 벤더 타입 정보 조회 + const typeResult = await getVendorTypeInfo(parseInt(vendorId)); + if (typeResult.success && typeResult.data) { + setVendorTypeInfo(typeResult.data); + } + } catch (error) { + console.error("벤더 데이터 로드 오류:", error); + } + }; + + // 컴포넌트 마운트 시 데이터 로드 + React.useEffect(() => { + if (vendorId) { + loadVendorData(); + } + }, [vendorId]); + + // 첨부파일 다운로드 핸들러 + const handleAttachmentDownload = async (filePath: string, fileName: string) => { + try { + const result = await downloadFile(filePath, fileName); + if (result.success) { + toast.success(`${fileName} 파일이 다운로드되었습니다.`); + } else { + toast.error(result.error || "파일 다운로드에 실패했습니다."); + } + } catch (error) { + console.error("파일 다운로드 오류:", error); + toast.error("파일 다운로드에 실패했습니다."); + } + }; + + // 첨부파일 관리 핸들러 (타입별) + const handleAttachmentFileManagement = (attachmentType: string, typeName: string) => { + const files = attachmentsByType[attachmentType] || []; + + if (files.length === 0) { + toast.info(`${typeName} 파일이 없습니다.`); + return; + } + + // 파일이 하나인 경우 바로 다운로드 + if (files.length === 1) { + handleAttachmentDownload(files[0].filePath, files[0].fileName); + return; + } + + // 파일이 여러 개인 경우 순차적으로 모든 파일 다운로드 + toast.info(`${typeName} 파일 ${files.length}개를 다운로드합니다.`); + files.forEach((file, index) => { + setTimeout(() => { + handleAttachmentDownload(file.filePath, file.fileName); + }, index * 500); // 500ms 간격으로 순차 다운로드 + }); + }; + if (!initialData) { return (
@@ -467,16 +553,7 @@ export default function BasicInfoClient({ ); } - const attachmentsByType = initialData.attachments.reduce( - (acc: Record, attachment: VendorAttachment) => { - if (!acc[attachment.attachmentType]) { - acc[attachment.attachmentType] = []; - } - acc[attachment.attachmentType].push(attachment); - return acc; - }, - {} - ); + // attachmentsByType는 상태로 관리되고 있으므로 제거 return (
@@ -571,9 +648,7 @@ export default function BasicInfoClient({ /> */}
@@ -592,27 +667,18 @@ export default function BasicInfoClient({ /> updateField("address", value)} + value={initialData.address || ""} + type="readonly" /> updateField("addressDetail", value)} + value={initialData.addressDetail || ""} + type="readonly" /> updateField("postalCode", value)} + value={initialData.postalCode || ""} + type="readonly" /> updateField("businessSize", value)} placeholder="기업규모를 선택하세요" /> */} - handleFileManagement("사업자등록증")} - /> - + /> */}
} column3={
{/* - - handleFileManagement("ISO 인증서")} - /> - */} + + {/* + /> */} +
+ } + /> + + + + {/* 첨부파일 */} + + {/* 사업자등록증 */} +
+
사업자등록증
+
+
+ {attachmentsByType.BUSINESS_REGISTRATION?.length || 0}건 +
+ {attachmentsByType.BUSINESS_REGISTRATION?.length > 0 && ( + + )} +
+
+ + {/* 신용평가보고서 */} +
+
신용평가보고서
+
+
+ {attachmentsByType.CREDIT_REPORT?.length || 0}건 +
+ {attachmentsByType.CREDIT_REPORT?.length > 0 && ( + + )} +
+
+ + {/* 통장사본 */} +
+
통장사본
+
+
+ {attachmentsByType.BANK_ACCOUNT_COPY?.length || 0}건 +
+ {attachmentsByType.BANK_ACCOUNT_COPY?.length > 0 && ( + + )} +
+
+ + {/* ISO 인증서 */} +
+
ISO 인증서
+
+
+ {attachmentsByType.ISO_CERTIFICATION?.length || 0}건 +
+ {attachmentsByType.ISO_CERTIFICATION?.length > 0 && ( + + )} +
+
+ + {/* 기타 첨부파일 (GENERAL) */} +
+
기타 첨부파일
+
+
+ {attachmentsByType.GENERAL?.length || 0}건 +
+ {attachmentsByType.GENERAL?.length > 0 && ( + + )} +
+
} /> @@ -1189,7 +1347,7 @@ export default function BasicInfoClient({ } /> */} - {/* */} + {/* 추가 조회 기능 버튼들 */}
-- cgit v1.2.3