From 95984e67b8d57fbe1431fcfedf3bb682f28416b3 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Thu, 27 Nov 2025 17:48:28 +0900 Subject: (김준회) swp 영문 처리 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/swp/table/swp-document-detail-dialog.tsx | 56 +++++++------- lib/swp/table/swp-help-dialog.tsx | 78 +++++++++---------- lib/swp/table/swp-inbox-document-detail-dialog.tsx | 80 +++++++++---------- lib/swp/table/swp-inbox-history-dialog.tsx | 40 +++++----- lib/swp/table/swp-inbox-table-columns.tsx | 14 ++-- lib/swp/table/swp-inbox-table.tsx | 30 ++++---- lib/swp/table/swp-note-dialog.tsx | 6 +- lib/swp/table/swp-revision-list-dialog.tsx | 28 +++---- lib/swp/table/swp-table-columns.tsx | 30 ++++---- lib/swp/table/swp-table-toolbar.tsx | 90 +++++++++++----------- lib/swp/table/swp-table.tsx | 8 +- lib/swp/table/swp-upload-result-dialog.tsx | 14 ++-- lib/swp/table/swp-upload-validation-dialog.tsx | 72 ++++++++--------- lib/swp/table/swp-uploaded-files-dialog.tsx | 62 +++++++-------- 14 files changed, 304 insertions(+), 304 deletions(-) (limited to 'lib/swp') diff --git a/lib/swp/table/swp-document-detail-dialog.tsx b/lib/swp/table/swp-document-detail-dialog.tsx index 77ef77f7..ef5cf6f9 100644 --- a/lib/swp/table/swp-document-detail-dialog.tsx +++ b/lib/swp/table/swp-document-detail-dialog.tsx @@ -122,8 +122,8 @@ export function SwpDocumentDetailDialog({ setActivities(flatActivities); } catch (error) { - console.error("문서 상세 조회 실패:", error); - toast.error("문서 리비전 트리를 불러오는데 실패했습니다"); + console.error("Failed to retrieve document details:", error); + toast.error("Failed to load document revision tree"); } finally { setIsLoading(false); } @@ -157,8 +157,8 @@ export function SwpDocumentDetailDialog({ setActivityFiles(activitySpecificFiles); } catch (error) { - console.error("파일 목록 조회 실패:", error); - toast.error("파일 목록을 불러오는데 실패했습니다"); + console.error("Failed to retrieve file list:", error); + toast.error("Failed to load file list"); } finally { setIsLoadingFiles(false); } @@ -166,11 +166,11 @@ export function SwpDocumentDetailDialog({ const handleDownloadFile = async (fileName: string, ownDocNo: string) => { try { - toast.info("파일 다운로드 중..."); + toast.info("Downloading file..."); const result = await downloadVendorFile(projNo, ownDocNo, fileName); if (!result.success || !result.data) { - toast.error(result.error || "파일 다운로드 실패"); + toast.error(result.error || "File download failed"); return; } @@ -185,10 +185,10 @@ export function SwpDocumentDetailDialog({ window.document.body.removeChild(link); URL.revokeObjectURL(url); - toast.success(`파일 다운로드 완료: ${fileName}`); + toast.success(`File download complete: ${fileName}`); } catch (error) { - console.error("파일 다운로드 실패:", error); - toast.error("파일 다운로드에 실패했습니다"); + console.error("File download failed:", error); + toast.error("Failed to download file"); } }; @@ -221,7 +221,7 @@ export function SwpDocumentDetailDialog({ - 문서 리비전 히스토리 + Document Revision History {document && ( {document.DOC_NO} - {document.DOC_TITLE} @@ -234,30 +234,30 @@ export function SwpDocumentDetailDialog({ {/* 문서 정보 */}
- 프로젝트: + Project: {document.PROJ_NO} {document.PROJ_NM && ( ({document.PROJ_NM}) )}
- 패키지: + Package: {document.PKG_NO || "-"}
- 업체: + Vendor: {document.CPY_NM || "-"} {document.VNDR_CD && ( ({document.VNDR_CD}) )}
- 최신 리비전: + Latest Revision: {document.LTST_REV_NO || "-"}
- 총 Activity: - {activities.length}개 + Total Activity: + {activities.length}
@@ -265,7 +265,7 @@ export function SwpDocumentDetailDialog({ {isLoading ? (
- 리비전 트리 로딩 중... + Loading revision tree...
) : activities.length > 0 ? ( <> @@ -357,14 +357,14 @@ export function SwpDocumentDetailDialog({ {/* 파일 목록 (아래) */}
-

파일 목록

+

File List

{selectedActivity ? (

Activity: {selectedActivity.actvNo} / Rev {selectedActivity.revNo} ({selectedActivity.stage}) / {selectedActivity.inOut}

) : (

- Activity를 선택하면 파일 목록이 표시됩니다 + Select an Activity to view the file list

)}
@@ -373,16 +373,16 @@ export function SwpDocumentDetailDialog({ isLoadingFiles ? (
- 파일 로딩 중... + Loading files...
) : activityFiles.length > 0 ? ( - 파일명 - 크기 - 날짜 - 다운로드 + File Name + Size + Date + Download @@ -405,7 +405,7 @@ export function SwpDocumentDetailDialog({ onClick={() => handleDownloadFile(file.FILE_NM, document.OWN_DOC_NO || document.DOC_NO)} > - 다운로드 + Download @@ -416,7 +416,7 @@ export function SwpDocumentDetailDialog({
-

파일이 없습니다

+

No files

) @@ -424,7 +424,7 @@ export function SwpDocumentDetailDialog({
-

Activity를 선택해주세요

+

Please select an Activity

)} @@ -434,7 +434,7 @@ export function SwpDocumentDetailDialog({ ) : (
-

Activity 정보가 없습니다

+

No Activity information

)} diff --git a/lib/swp/table/swp-help-dialog.tsx b/lib/swp/table/swp-help-dialog.tsx index 7b18c100..a355f5ad 100644 --- a/lib/swp/table/swp-help-dialog.tsx +++ b/lib/swp/table/swp-help-dialog.tsx @@ -18,21 +18,21 @@ export function SwpUploadHelpDialog() { - 파일 업로드 가이드 + File Upload Guide - 올바른 파일명 형식으로 업로드해주세요 + Please upload with the correct file name format
{/* 탭 설명 */}
-

탭 설명

+

Tab Description

@@ -40,8 +40,8 @@ export function SwpUploadHelpDialog() { DOCUMENT REGISTRATION TAB

- 파일을 업로드한 현황입니다. SHI가 파일 접수 여부를 응답할 예정입니다. - 업로드한 파일의 승낙 여부 등을 확인할 수 있으며, 접수 전의 Standby 상태의 경우 업로드를 취소할 수 있습니다. + This shows the status of uploaded files. SHI will respond with file acceptance status. + You can check the acceptance status of uploaded files, and cancel uploads in Standby status before acceptance.

@@ -50,8 +50,8 @@ export function SwpUploadHelpDialog() { DOCUMENT LIST TAB

- 파일을 업로드한 뒤, SHI가 업로드한 파일을 수락하면 Rev, Activity No가 만들어지며, 해당 테이블에 추가됩니다. - 수락시 Activity No 가 부여됩니다. + After uploading a file, if SHI accepts the uploaded file, Rev and Activity No are created and added to this table. + Activity No is assigned upon acceptance.

@@ -59,29 +59,29 @@ export function SwpUploadHelpDialog() { {/* 파일명 형식 */}
-

파일명 형식

+

File Name Format

- [DOC_NO]_[REV_NO]_[STAGE].[확장자] + [DOC_NO]_[REV_NO]_[STAGE].[Extension]

- [주의] 언더스코어(_)가 최소 2개 이상 있어야 합니다 + [Note] Must contain at least 2 underscores (_)

- [선택사항] 4번째 항목으로 파일명을 추가할 수 있습니다 (예: [DOC_NO]_[REV_NO]_[STAGE]_[파일명].[확장자]) + [Optional] You can add a file name as the 4th item (e.g. [DOC_NO]_[REV_NO]_[STAGE]_[FileName].[Extension])

{/* 각 항목 설명 - 1라인 형태 */}
-

항목 설명

+

Item Description

DOC_NO
- 벤더의 문서번호 - - 프로젝트마다 유니크해야 합니다 + Vendor Document Number + - Must be unique per project
@@ -90,8 +90,8 @@ export function SwpUploadHelpDialog() { REV_NO
- 리비전 번호 - - 보통 01, 02 같은 식으로 피드백에 따라 증가합니다 + Revision Number + - Usually increments like 01, 02 based on feedback
@@ -100,32 +100,32 @@ export function SwpUploadHelpDialog() { STAGE
- 스테이지 - - 스테이지 정보를 입력해주세요. (예: IFA, IFC) + Stage + - Please enter stage information. (e.g. IFA, IFC)
- 파일명 + File Name
- 자유 파일명 (선택사항) - - 문서를 식별할 수 있는 이름 (언더스코어 포함 가능, 생략 가능) + Free File Name (Optional) + - Name to identify the document (Underscores allowed, optional)
{/* 예시 */}
-

올바른 예시

+

Correct Examples

VD-DOC-001_01_IFA.pdf

- [O] 기본 형식 (파일명 생략) + [O] Basic Format (File Name Omitted)

@@ -133,7 +133,7 @@ export function SwpUploadHelpDialog() { VD-DOC-001_01_IFA_drawing_final.pdf

- [O] 파일명 추가 (파일명에 언더스코어 포함 가능) + [O] File Name Added (Underscores allowed in file name)

@@ -141,7 +141,7 @@ export function SwpUploadHelpDialog() { TECH-SPEC-002_02_IFC.dwg

- [O] 기본 형식 사용 + [O] Basic Format Used

@@ -149,7 +149,7 @@ export function SwpUploadHelpDialog() { DOC-003_03_IFA_test_result_data.xlsx

- [O] 파일명 추가 (여러 단어 조합 가능) + [O] File Name Added (Multiple words allowed)

@@ -157,14 +157,14 @@ export function SwpUploadHelpDialog() { {/* 잘못된 예시 */}
-

잘못된 예시

+

Incorrect Examples

VD-DOC-001-01-IFA.pdf

- [X] 언더스코어(_) 대신 하이픈(-) 사용 + [X] Hyphen (-) used instead of Underscore (_)

@@ -172,7 +172,7 @@ export function SwpUploadHelpDialog() { VD-DOC-001_01.pdf

- [X] STAGE 정보 누락 (최소 3개 항목 필요) + [X] STAGE info missing (Minimum 3 items required)

@@ -180,7 +180,7 @@ export function SwpUploadHelpDialog() { VD DOC 001_01_IFA.pdf

- [X] 공백 포함 (언더스코어 사용 필요) + [X] Contains spaces (Use underscores)

@@ -188,7 +188,7 @@ export function SwpUploadHelpDialog() { VD-DOC-001__IFA.pdf

- [X] REV_NO 비어있음 (빈 항목 불가) + [X] REV_NO empty (Cannot be empty)

@@ -197,15 +197,15 @@ export function SwpUploadHelpDialog() { {/* 주의사항 */}

- [주의사항] + [Precautions]

    -
  • 파일명은 최소 [DOC_NO]_[REV_NO]_[STAGE].[확장자] 형식이어야 합니다
  • -
  • DOC_NO는 현재 프로젝트에 할당된 문서번호여야 합니다
  • -
  • 4번째 항목(파일명)은 선택사항으로 생략 가능합니다
  • -
  • 업로드 날짜/시간은 시스템에서 자동으로 생성됩니다
  • -
  • 같은 파일명으로 이미 업로드된 파일이 있으면 덮어쓰지 않고 오류 처리됩니다
  • -
  • 프로젝트를 먼저 선택해야 업로드 버튼이 활성화됩니다
  • +
  • File name must be at least in [DOC_NO]_[REV_NO]_[STAGE].[Extension] format
  • +
  • DOC_NO must be a document number assigned to the current project
  • +
  • The 4th item (File Name) is optional and can be omitted
  • +
  • Upload date/time is automatically generated by the system
  • +
  • If a file with the same name is already uploaded, it will not be overwritten and will be treated as an error
  • +
  • You must select a project first to enable the upload button
diff --git a/lib/swp/table/swp-inbox-document-detail-dialog.tsx b/lib/swp/table/swp-inbox-document-detail-dialog.tsx index ca7fcf1b..7f814267 100644 --- a/lib/swp/table/swp-inbox-document-detail-dialog.tsx +++ b/lib/swp/table/swp-inbox-document-detail-dialog.tsx @@ -35,7 +35,7 @@ interface SwpInboxDocumentDetailDialogProps { userId: string; } -// 리비전별 그룹 타입 +// Group type by revision interface RevisionGroup { revNo: string; stage: string; @@ -43,7 +43,7 @@ interface RevisionGroup { totalFiles: number; } -// Activity별 그룹 타입 (activity가 null일 수 있음) +// Group type by Activity (activity can be null) interface ActivityGroup { actvNo: string | null; files: SwpFileApiResponse[]; @@ -59,7 +59,7 @@ export function SwpInboxDocumentDetailDialog({ const [expandedActivities, setExpandedActivities] = useState>(new Set()); const [isAllExpanded, setIsAllExpanded] = useState(true); - // 파일들을 리비전 > Activity 구조로 그룹핑 + // Group files into Revision > Activity structure const revisionGroups = useMemo(() => { if (!document) return []; @@ -78,7 +78,7 @@ export function SwpInboxDocumentDetailDialog({ revMap.forEach((revFiles, revKey) => { const [revNo, stage] = revKey.split("|"); - // Activity별로 그룹핑 (null 가능) + // Group by Activity (nullable) const actMap = new Map(); revFiles.forEach((file) => { @@ -94,7 +94,7 @@ export function SwpInboxDocumentDetailDialog({ activities.push({ actvNo, files }); }); - // Activity가 없는 것을 먼저, 있는 것을 나중에 정렬 + // Sort: No Activity first, then with Activity activities.sort((a, b) => { if (a.actvNo === null && b.actvNo !== null) return -1; if (a.actvNo !== null && b.actvNo === null) return 1; @@ -110,11 +110,11 @@ export function SwpInboxDocumentDetailDialog({ }); }); - // 리비전 번호로 정렬 (최신이 위로) + // Sort by revision number (newest first) return result.sort((a, b) => b.revNo.localeCompare(a.revNo)); }, [document]); - // Dialog가 열릴 때 모두 펼치기 + // Expand all when dialog opens React.useEffect(() => { if (open && revisionGroups.length > 0) { const allRevKeys = new Set(); @@ -160,15 +160,15 @@ export function SwpInboxDocumentDetailDialog({ }); }; - // 일괄 열기/닫기 + // Toggle all const handleToggleAll = () => { if (isAllExpanded) { - // 모두 닫기 + // Collapse all setExpandedRevisions(new Set()); setExpandedActivities(new Set()); setIsAllExpanded(false); } else { - // 모두 열기 + // Expand all const allRevKeys = new Set(); const allActKeys = new Set(); @@ -191,27 +191,27 @@ export function SwpInboxDocumentDetailDialog({ const handleCancelFile = async (boxSeq: string, actvSeq: string, fileName: string) => { try { await cancelVendorFile(boxSeq, actvSeq); - toast.success(`파일 취소 완료: ${fileName}`); + toast.success(`File cancelled: ${fileName}`); - // Dialog를 닫고 부모 컴포넌트가 새로고침하도록 함 + // Close dialog and trigger parent refresh onOpenChange(false); } catch (error) { - console.error("파일 취소 실패:", error); - toast.error("파일 취소에 실패했습니다"); + console.error("Failed to cancel file:", error); + toast.error("Failed to cancel file"); } }; const handleDownloadFile = async (fileName: string, ownDocNo: string) => { try { - toast.info("파일 다운로드 중..."); + toast.info("Downloading file..."); const result = await downloadVendorFile(projNo, ownDocNo, fileName); if (!result.success || !result.data) { - toast.error(result.error || "파일 다운로드 실패"); + toast.error(result.error || "File download failed"); return; } - // Blob 생성 및 다운로드 + // Create Blob and download const blob = new Blob([Buffer.from(result.data)], { type: result.mimeType }); const url = URL.createObjectURL(blob); const link = window.document.createElement("a"); @@ -222,10 +222,10 @@ export function SwpInboxDocumentDetailDialog({ window.document.body.removeChild(link); URL.revokeObjectURL(url); - toast.success(`파일 다운로드 완료: ${fileName}`); + toast.success(`File downloaded: ${fileName}`); } catch (error) { - console.error("파일 다운로드 실패:", error); - toast.error("파일 다운로드에 실패했습니다"); + console.error("File download failed:", error); + toast.error("Failed to download file"); } }; @@ -233,7 +233,7 @@ export function SwpInboxDocumentDetailDialog({ - 업로드 파일 상세 + Uploaded File Details {document && ( {document.ownDocNo} @@ -243,30 +243,30 @@ export function SwpInboxDocumentDetailDialog({ {document && (
- {/* 문서 정보 */} + {/* Document Info */}
OWN_DOC_NO:
{document.ownDocNo}
- 최신 스테이지: + Latest Stage:
{document.latestStage || "-"}
- 최신 리비전: + Latest Revision:
{document.latestRevNo || "-"}
- 최신 REV 파일: -
{document.latestRevFileCount}개
+ Latest REV Files: +
{document.latestRevFileCount}
- {/* 리비전 및 액티비티 트리 */} + {/* Revision and Activity Tree */} {revisionGroups.length > 0 ? (
- {/* 일괄 열기/닫기 버튼 */} + {/* Toggle All Button */}
@@ -292,7 +292,7 @@ export function SwpInboxDocumentDetailDialog({ return (
- {/* 리비전 헤더 */} + {/* Revision Header */}
toggleRevision(revKey)} @@ -314,12 +314,12 @@ export function SwpInboxDocumentDetailDialog({ {revision.stage} - {revision.activities.length}개 그룹 / {revision.totalFiles}개 파일 + {revision.activities.length} Groups / {revision.totalFiles} Files
- {/* 액티비티 목록 (또는 Activity 없는 파일들) */} + {/* Activity List (or files without Activity) */} {isRevExpanded && (
{revision.activities.map((activity) => { @@ -328,7 +328,7 @@ export function SwpInboxDocumentDetailDialog({ return (
- {/* 액티비티 헤더 */} + {/* Activity Header */}
toggleActivity(actKey)} @@ -350,16 +350,16 @@ export function SwpInboxDocumentDetailDialog({ ) : ( - Activity 없음 + No Activity )} - {activity.files.length}개 파일 + {activity.files.length} Files
- {/* 파일 목록 */} + {/* File List */} {isActExpanded && (
{activity.files.map((file, idx) => ( @@ -398,7 +398,7 @@ export function SwpInboxDocumentDetailDialog({ onClick={() => handleCancelFile(file.BOX_SEQ!, file.ACTV_SEQ!, file.FILE_NM)} > - 취소 + Cancel )} {file.FLD_PATH && ( @@ -408,7 +408,7 @@ export function SwpInboxDocumentDetailDialog({ onClick={() => handleDownloadFile(file.FILE_NM, document.ownDocNo)} > - 다운로드 + Download )}
@@ -428,7 +428,7 @@ export function SwpInboxDocumentDetailDialog({ ) : (
-

파일 정보가 없습니다

+

No file information available

)}
diff --git a/lib/swp/table/swp-inbox-history-dialog.tsx b/lib/swp/table/swp-inbox-history-dialog.tsx index fbb75f3c..e46829d0 100644 --- a/lib/swp/table/swp-inbox-history-dialog.tsx +++ b/lib/swp/table/swp-inbox-history-dialog.tsx @@ -217,7 +217,7 @@ export function SwpInboxHistoryDialog({ const handleCancelFile = async (file: SwpFileApiResponse) => { if (!file.BOX_SEQ || !file.ACTV_SEQ) { - toast.error("취소할 수 없는 파일입니다 (BOX_SEQ 또는 ACTV_SEQ 없음)"); + toast.error("File cannot be canceled (Missing BOX_SEQ or ACTV_SEQ)"); return; } @@ -236,13 +236,13 @@ export function SwpInboxHistoryDialog({ userId, }); - toast.success(`파일 취소 완료: ${file.FILE_NM}`); + toast.success(`File canceled: ${file.FILE_NM}`); // 취소된 파일로 마킹 (상태 변경) setCancelledFiles((prev) => new Set(prev).add(fileKey)); } catch (error) { - console.error("파일 취소 실패:", error); - toast.error("파일 취소에 실패했습니다"); + console.error("File cancel failed:", error); + toast.error("Failed to cancel file"); } finally { setCancellingFiles((prev) => { const newSet = new Set(prev); @@ -254,7 +254,7 @@ export function SwpInboxHistoryDialog({ const handleDownloadFile = async (file: SwpFileApiResponse) => { try { - toast.info("파일 다운로드 준비 중..."); + toast.info("Preparing file download..."); // API route를 통해 다운로드 const downloadUrl = `/api/swp/download/${encodeURIComponent(file.OWN_DOC_NO)}?projNo=${encodeURIComponent(projNo)}&fileName=${encodeURIComponent(file.FILE_NM)}`; @@ -262,10 +262,10 @@ export function SwpInboxHistoryDialog({ // 새 탭에서 다운로드 window.open(downloadUrl, "_blank"); - toast.success(`파일 다운로드 시작: ${file.FILE_NM}`); + toast.success(`File download started: ${file.FILE_NM}`); } catch (error) { - console.error("파일 다운로드 실패:", error); - toast.error("파일 다운로드에 실패했습니다"); + console.error("File download failed:", error); + toast.error("Failed to download file"); } }; @@ -284,10 +284,10 @@ export function SwpInboxHistoryDialog({ - Document 전체 이력 + Document History {docNo && ( - {docNo} - 총 {documentFiles.length}개 파일 + {docNo} - Total {documentFiles.length} files )} @@ -299,7 +299,7 @@ export function SwpInboxHistoryDialog({
setSearchQuery(e.target.value)} className="pl-10" @@ -313,12 +313,12 @@ export function SwpInboxHistoryDialog({ {isAllExpanded ? ( <> - 일괄 닫기 + Collapse All ) : ( <> - 일괄 열기 + Expand All )} @@ -327,7 +327,7 @@ export function SwpInboxHistoryDialog({ {/* 검색 결과 안내 */} {searchQuery && (
- 검색 결과: {filteredFiles.length}개 파일 (전체 {documentFiles.length}개) + Search Results: {filteredFiles.length} files (Total {documentFiles.length})
)} @@ -358,7 +358,7 @@ export function SwpInboxHistoryDialog({ {revision.stage} - {revision.activities.length}개 그룹 / {revision.totalFiles}개 파일 + {revision.activities.length} groups / {revision.totalFiles} files
@@ -394,11 +394,11 @@ export function SwpInboxHistoryDialog({ ) : ( - Activity 없음 + No Activity )} - {activity.files.length}개 파일 + {activity.files.length} files
@@ -463,12 +463,12 @@ export function SwpInboxHistoryDialog({ {isCancelling ? ( <> - 취소 중... + Canceling... ) : ( <> - 취소 + Cancel )} @@ -497,7 +497,7 @@ export function SwpInboxHistoryDialog({
) : (
- {searchQuery ? "검색 결과가 없습니다" : "파일 정보가 없습니다"} + {searchQuery ? "No search results" : "No file information"}
)} diff --git a/lib/swp/table/swp-inbox-table-columns.tsx b/lib/swp/table/swp-inbox-table-columns.tsx index dbf25c5d..f7596578 100644 --- a/lib/swp/table/swp-inbox-table-columns.tsx +++ b/lib/swp/table/swp-inbox-table-columns.tsx @@ -8,7 +8,7 @@ import type { SwpFileApiResponse } from "@/lib/swp/api-client"; export const swpInboxDocumentColumns: ColumnDef[] = [ { accessorKey: "STAT_NM", - header: "최신 리비전의 최신 파일 상태", + header: "Latest File Status of Latest Revision", cell: ({ row }) => { const statNm = row.original.STAT_NM; const stat = row.original.STAT; @@ -16,7 +16,7 @@ export const swpInboxDocumentColumns: ColumnDef[] = [ if (!stat) return displayStatus; - // STAT 코드 기반 색상 결정 + // Determine color based on STAT code const color = stat === "SCW03" || stat === "SCW08" ? "bg-green-100 text-green-800" : // Complete, Checked stat === "SCW02" ? "bg-blue-100 text-blue-800" : // Processing @@ -25,7 +25,7 @@ export const swpInboxDocumentColumns: ColumnDef[] = [ stat === "SCW07" ? "bg-purple-100 text-purple-800" : // Send for Eng Verification stat === "SCW09" ? "bg-gray-100 text-gray-800" : // Cancelled stat === "SCW00" ? "bg-orange-100 text-orange-800" : // Upload - "bg-gray-100 text-gray-800"; // 기타 + "bg-gray-100 text-gray-800"; // Others return ( @@ -45,7 +45,7 @@ export const swpInboxDocumentColumns: ColumnDef[] = [ }, { accessorKey: "FILE_NM", - header: "파일명", + header: "File Name", cell: ({ row }) => (
{row.original.FILE_NM} @@ -55,7 +55,7 @@ export const swpInboxDocumentColumns: ColumnDef[] = [ }, { accessorKey: "STAGE", - header: "스테이지", + header: "Stage", cell: ({ row }) => { const stage = row.original.STAGE; if (!stage) return "-"; @@ -91,7 +91,7 @@ export const swpInboxDocumentColumns: ColumnDef[] = [ }, { accessorKey: "FILE_SZ", - header: "파일 크기", + header: "File Size", cell: ({ row }) => { const size = row.original.FILE_SZ; if (!size) return "-"; @@ -121,7 +121,7 @@ export const swpInboxDocumentColumns: ColumnDef[] = [ }, { accessorKey: "CRTE_DTM", - header: "생성일시", + header: "Created Date", cell: ({ row }) => { const date = row.original.CRTE_DTM; if (!date) return "-"; diff --git a/lib/swp/table/swp-inbox-table.tsx b/lib/swp/table/swp-inbox-table.tsx index d070f2fd..788fcb70 100644 --- a/lib/swp/table/swp-inbox-table.tsx +++ b/lib/swp/table/swp-inbox-table.tsx @@ -389,7 +389,7 @@ export function SwpInboxTable({ // 선택된 파일 일괄 취소 const handleBulkCancel = async () => { if (selectedFiles.size === 0) { - toast.error("취소할 파일을 선택해주세요"); + toast.error("Please select files to cancel"); return; } @@ -398,12 +398,12 @@ export function SwpInboxTable({ ); if (filesToCancel.length === 0) { - toast.error("취소할 파일이 없습니다"); + toast.error("No files to cancel"); return; } try { - toast.info(`${filesToCancel.length}개 파일 취소 중...`); + toast.info(`Canceling ${filesToCancel.length} files...`); // 병렬 취소 const cancelPromises = filesToCancel.map((row) => @@ -416,21 +416,21 @@ export function SwpInboxTable({ await Promise.all(cancelPromises); - toast.success(`${filesToCancel.length}개 파일 취소 완료`); + toast.success(`Canceled ${filesToCancel.length} files`); setSelectedFiles(new Set()); // 선택 초기화 // 페이지 리프레시 window.location.reload(); } catch (error) { - console.error("일괄 취소 실패:", error); - toast.error("일부 파일 취소에 실패했습니다"); + console.error("Bulk cancel failed:", error); + toast.error("Failed to cancel some files"); } }; const handleDownloadFile = async (file: SwpFileApiResponse) => { try { - toast.info("파일 다운로드 준비 중..."); + toast.info("Preparing file download..."); // API route를 통해 다운로드 const downloadUrl = `/api/swp/download/${encodeURIComponent(file.OWN_DOC_NO)}?projNo=${encodeURIComponent(projNo)}&fileName=${encodeURIComponent(file.FILE_NM)}`; @@ -438,10 +438,10 @@ export function SwpInboxTable({ // 새 탭에서 다운로드 window.open(downloadUrl, "_blank"); - toast.success(`파일 다운로드 시작: ${file.FILE_NM}`); + toast.success(`File download started: ${file.FILE_NM}`); } catch (error) { - console.error("파일 다운로드 실패:", error); - toast.error("파일 다운로드에 실패했습니다"); + console.error("File download failed:", error); + toast.error("Failed to download file"); } }; @@ -477,7 +477,7 @@ export function SwpInboxTable({ if (files.length === 0 && requiredDocs.length === 0) { return (
- 업로드한 파일이 없습니다. + No uploaded files.
); } @@ -493,7 +493,7 @@ export function SwpInboxTable({ onClick={() => setSelectedStatus(null)} className="h-9" > - 전체 ({files.length + requiredDocs.length}) + All ({files.length + requiredDocs.length}) {statusCounts.map((statusCount) => (
) : (
@@ -685,7 +685,7 @@ export function SwpInboxTable({ }} > {row.note1 ? ( -
+
{row.note1}
) : ( diff --git a/lib/swp/table/swp-note-dialog.tsx b/lib/swp/table/swp-note-dialog.tsx index 5f86de24..c8372d68 100644 --- a/lib/swp/table/swp-note-dialog.tsx +++ b/lib/swp/table/swp-note-dialog.tsx @@ -17,8 +17,8 @@ interface SwpNoteDialogProps { } /** - * SWP Note 전체 내용 표시 Dialog - * DC Note (NOTE1) 또는 Eng Note (NOTE2)의 전체 내용을 표시합니다. + * SWP Note Full Content Dialog + * Displays the full content of DC Note (NOTE1) or Eng Note (NOTE2). */ export function SwpNoteDialog({ open, @@ -34,7 +34,7 @@ export function SwpNoteDialog({
- {content || 내용이 없습니다.} + {content || No content.}
diff --git a/lib/swp/table/swp-revision-list-dialog.tsx b/lib/swp/table/swp-revision-list-dialog.tsx index 8924db81..66892469 100644 --- a/lib/swp/table/swp-revision-list-dialog.tsx +++ b/lib/swp/table/swp-revision-list-dialog.tsx @@ -55,7 +55,7 @@ export function SwpRevisionListDialog({ - 문서 상세 + Document Detail {document && ( {document.DOC_NO} - {document.DOC_TITLE} @@ -68,25 +68,25 @@ export function SwpRevisionListDialog({ {/* 문서 정보 */}
- 프로젝트: + Project:
{document.PROJ_NO}
{document.PROJ_NM && (
{document.PROJ_NM}
)}
- 패키지: + Package:
{document.PKG_NO || "-"}
- 업체: + Company:
{document.CPY_NM || "-"}
{document.VNDR_CD && (
{document.VNDR_CD}
)}
- 마지막 리비전 넘버: + Last Revision Number:
{document.LTST_REV_NO || "-"}
@@ -95,7 +95,7 @@ export function SwpRevisionListDialog({ {loadingRevisions ? (
- 리비전 로딩 중... + Loading revisions...
) : revisions.length ? ( ) : (
- 리비전 없음 + No revisions
)}
@@ -178,11 +178,11 @@ function DocumentDetailView({ size="sm" onClick={handleExpandAll} > - {allExpanded ? "모두 접기" : "모두 펼치기"} + {allExpanded ? "Collapse All" : "Expand All"}
- {/* 리비전 테이블 */} + {/* Revision Table */}
@@ -204,7 +204,7 @@ function DocumentDetailView({ {revisionTable.getRowModel().rows.map((row) => ( - {/* 리비전 행 */} + {/* Revision Row */} {row.getVisibleCells().map((cell) => ( @@ -230,20 +230,20 @@ function DocumentDetailView({ ))} - {/* 파일 행들 (확장 시) */} + {/* File Rows (when expanded) */} {row.getIsExpanded() && ( {loadingFiles.has(row.original.id) ? (
- 파일 로딩 중... + Loading files...
) : fileData[row.original.id]?.length ? ( ) : (
- 파일 없음 + No files
)}
@@ -259,7 +259,7 @@ function DocumentDetailView({ } // ============================================================================ -// 파일 서브 테이블 +// File Sub Table // ============================================================================ interface FileSubTableProps { diff --git a/lib/swp/table/swp-table-columns.tsx b/lib/swp/table/swp-table-columns.tsx index 261cf960..9cb645a5 100644 --- a/lib/swp/table/swp-table-columns.tsx +++ b/lib/swp/table/swp-table-columns.tsx @@ -11,10 +11,10 @@ import { toast } from "sonner"; export const swpDocumentColumns: ColumnDef[] = [ { accessorKey: "LTST_ACTV_STAT", - header: "상태", + header: "Status", cell: ({ row }) => { const status = row.original.LTST_ACTV_STAT; - if (!status) return "-"; + if (!status) return "Waiting"; const color = status.includes("Complete") ? "bg-green-100 text-green-800" : @@ -54,7 +54,7 @@ export const swpDocumentColumns: ColumnDef[] = [ }, { accessorKey: "DOC_TITLE", - header: "문서제목", + header: "Document Title", cell: ({ row }) => (
{row.original.DOC_TITLE} @@ -66,7 +66,7 @@ export const swpDocumentColumns: ColumnDef[] = [ }, { accessorKey: "PROJ_NO", - header: "프로젝트", + header: "Project", cell: ({ row }) => (
{row.original.PROJ_NO}
@@ -83,7 +83,7 @@ export const swpDocumentColumns: ColumnDef[] = [ }, { accessorKey: "PKG_NO", - header: "패키지", + header: "Package", cell: ({ row }) => row.original.PKG_NO || "-", size: 100, minSize: 100, @@ -91,7 +91,7 @@ export const swpDocumentColumns: ColumnDef[] = [ }, { accessorKey: "VNDR_CD", - header: "업체", + header: "Vendor", cell: ({ row }) => (
{row.original.VNDR_CD && ( @@ -110,7 +110,7 @@ export const swpDocumentColumns: ColumnDef[] = [ }, { accessorKey: "STAGE", - header: "최신 스테이지", + header: "Latest Stage", cell: ({ row }) => { const stage = row.original.STAGE; if (!stage) return "-"; @@ -132,7 +132,7 @@ export const swpDocumentColumns: ColumnDef[] = [ }, { accessorKey: "LTST_REV_NO", - header: "최신 REV", + header: "Latest REV", cell: ({ row }) => row.original.LTST_REV_NO || "-", size: 100, minSize: 100, @@ -141,7 +141,7 @@ export const swpDocumentColumns: ColumnDef[] = [ { id: "actions", - header: "커버페이지 다운로드", + header: "Download Cover Page", cell: function ActionCell({ row }) { const [isDownloading, setIsDownloading] = React.useState(false); @@ -152,7 +152,7 @@ export const swpDocumentColumns: ColumnDef[] = [ const projectCode = row.original.PROJ_NO; if (!docNumber || !projectCode) { - toast.error("문서 번호 또는 프로젝트 정보가 없습니다."); + toast.error("Missing document number or project information."); return; } @@ -165,7 +165,7 @@ export const swpDocumentColumns: ColumnDef[] = [ ); if (!projectIdResponse.ok) { - toast.error("프로젝트 정보를 찾을 수 없습니다."); + toast.error("Project information not found."); return; } @@ -178,7 +178,7 @@ export const swpDocumentColumns: ColumnDef[] = [ if (!response.ok) { const error = await response.json(); - throw new Error(error.message || "커버페이지 다운로드 실패"); + throw new Error(error.message || "Failed to download cover page"); } // 3. 파일 다운로드 @@ -192,14 +192,14 @@ export const swpDocumentColumns: ColumnDef[] = [ window.URL.revokeObjectURL(url); document.body.removeChild(a); - toast.success("커버페이지 다운로드가 시작되었습니다."); + toast.success("Cover page download started."); } catch (error) { console.error("커버페이지 다운로드 오류:", error); toast.error( error instanceof Error ? error.message - : "커버페이지 다운로드 중 오류가 발생했습니다." + : "An error occurred while downloading the cover page." ); } finally { setIsDownloading(false); @@ -213,7 +213,7 @@ export const swpDocumentColumns: ColumnDef[] = [ onClick={handleDownloadCover} disabled={isDownloading} className="h-8 w-8 p-0" - title="커버페이지 다운로드" + title="Download Cover Page" > {isDownloading ? ( diff --git a/lib/swp/table/swp-table-toolbar.tsx b/lib/swp/table/swp-table-toolbar.tsx index 276eca14..ab01a87d 100644 --- a/lib/swp/table/swp-table-toolbar.tsx +++ b/lib/swp/table/swp-table-toolbar.tsx @@ -140,7 +140,7 @@ export function SwpTableToolbar({ const loadDocumentClassInfo = async () => { try { - console.log(`[SwpTableToolbar] 프로젝트 ${projNo} 문서 정보 로드 시작`); + console.log(`[SwpTableToolbar] Start loading document info for project ${projNo}`); // 서버 액션 호출 const result = await getDocumentClassInfoByProjectCode(projNo); @@ -150,32 +150,32 @@ export function SwpTableToolbar({ setVendorDocNumberToDocClassMap(result.vendorDocNumberToDocClassMap); setDocumentClassStages(result.documentClassStages); - console.log(`[SwpTableToolbar] 문서 정보 로드 완료:`, { + console.log(`[SwpTableToolbar] Document info load complete:`, { vendorDocNumbers: Object.keys(result.vendorDocNumberToDocClassMap).length, documentClassStages: result.documentClassStages, }); } else { - console.warn(`[SwpTableToolbar] 문서 정보 로드 실패:`, result.error); + console.warn(`[SwpTableToolbar] Document info load failed:`, result.error); setVendorDocNumberToDocClassMap({}); setDocumentClassStages({}); toast({ variant: "destructive", - title: "문서 정보 로드 실패", - description: result.error || "문서 정보를 가져올 수 없습니다.", + title: "Failed to load document info", + description: result.error || "Cannot retrieve document info.", }); } } } catch (error) { if (!isCancelled) { - console.error('[SwpTableToolbar] 문서 정보 로드 실패:', error); + console.error('[SwpTableToolbar] Failed to load document info:', error); setVendorDocNumberToDocClassMap({}); setDocumentClassStages({}); toast({ variant: "destructive", - title: "문서 정보 로드 실패", - description: "문서 정보를 가져올 수 없습니다. 페이지를 새로고침해주세요.", + title: "Failed to load document info", + description: "Cannot retrieve document info. Please refresh the page.", }); } } @@ -197,8 +197,8 @@ export function SwpTableToolbar({ if (!projNo) { toast({ variant: "destructive", - title: "프로젝트 선택 필요", - description: "파일을 업로드할 프로젝트를 먼저 선택해주세요.", + title: "Project selection required", + description: "Please select a project to upload files to first.", }); onFilesProcessed?.(); return; @@ -207,8 +207,8 @@ export function SwpTableToolbar({ if (!vendorCode) { toast({ variant: "destructive", - title: "업체 코드 오류", - description: "벤더 정보를 가져올 수 없습니다.", + title: "Vendor code error", + description: "Cannot retrieve vendor info.", }); onFilesProcessed?.(); return; @@ -244,8 +244,8 @@ export function SwpTableToolbar({ if (!projNo) { toast({ variant: "destructive", - title: "프로젝트 선택 필요", - description: "파일을 업로드할 프로젝트를 먼저 선택해주세요.", + title: "Project selection required", + description: "Please select a project to upload files to first.", }); return; } @@ -253,8 +253,8 @@ export function SwpTableToolbar({ if (!vendorCode) { toast({ variant: "destructive", - title: "업체 코드 오류", - description: "벤더 정보를 가져올 수 없습니다.", + title: "Vendor code error", + description: "Cannot retrieve vendor info.", }); return; } @@ -304,8 +304,8 @@ export function SwpTableToolbar({ startUpload(async () => { try { toast({ - title: "파일 업로드 시작", - description: `${validFiles.length}개 파일을 업로드합니다...`, + title: "File upload started", + description: `Uploading ${validFiles.length} files...`, }); const formData = new FormData(); @@ -322,7 +322,7 @@ export function SwpTableToolbar({ }); if (!response.ok) { - throw new Error(`업로드 실패: ${response.statusText}`); + throw new Error(`Upload failed: ${response.statusText}`); } const result = await response.json(); @@ -335,7 +335,7 @@ export function SwpTableToolbar({ setShowResultDialog(true); toast({ - title: result.success ? "업로드 완료" : "일부 업로드 실패", + title: result.success ? "Upload complete" : "Some uploads failed", description: result.message, }); @@ -345,21 +345,21 @@ export function SwpTableToolbar({ onUploadComplete?.(); toast({ - title: "문서 목록 갱신 중", - description: "외부 시스템 처리를 기다리는 중입니다...", + title: "Refreshing document list", + description: "Waiting for external system processing...", }); // 2초 딜레이 후 새로고침 setTimeout(() => { onRefresh(); toast({ - title: "갱신 완료", - description: "업로드된 파일이 문서 목록에 반영되었습니다.", + title: "Refresh complete", + description: "Uploaded files have been reflected in the document list.", }); }, 2000); } } catch (error) { - console.error("파일 업로드 실패:", error); + console.error("File upload failed:", error); // 검증 다이얼로그 닫기 setShowValidationDialog(false); @@ -367,7 +367,7 @@ export function SwpTableToolbar({ const errorResults = validFiles.map((file) => ({ fileName: file.name, success: false, - error: error instanceof Error ? error.message : "알 수 없는 오류", + error: error instanceof Error ? error.message : "Unknown error", })); setUploadResults(errorResults); @@ -444,7 +444,7 @@ export function SwpTableToolbar({ disabled={isRefreshing || !projNo} > - 새로고침 + Refresh {/* 별도 탭으로 분리하고 메인 테이블로 변경하였음. */} @@ -472,7 +472,7 @@ export function SwpTableToolbar({ {/* 검색 필터 */}
-

검색 필터

+

Search Filter

{/* 프로젝트 번호 */}
- + {projects.length > 0 ? ( @@ -507,7 +507,7 @@ export function SwpTableToolbar({ {"]"} ) : ( - 프로젝트 선택 + Select Project )} @@ -517,7 +517,7 @@ export function SwpTableToolbar({
setProjectSearch(e.target.value)} className="border-0 focus-visible:ring-0 focus-visible:ring-offset-0" @@ -548,7 +548,7 @@ export function SwpTableToolbar({ ))} {filteredProjects.length === 0 && (
- 검색 결과가 없습니다. + No search results.
)}
@@ -558,7 +558,7 @@ export function SwpTableToolbar({ ) : ( - + setLocalFilters({ ...localFilters, docNo: e.target.value }) @@ -582,10 +582,10 @@ export function SwpTableToolbar({ {/* 문서 제목 */}
- + setLocalFilters({ ...localFilters, docTitle: e.target.value }) @@ -596,10 +596,10 @@ export function SwpTableToolbar({ {/* 패키지 번호 */}
- + setLocalFilters({ ...localFilters, pkgNo: e.target.value }) @@ -610,10 +610,10 @@ export function SwpTableToolbar({ {/* 스테이지 */}
- + setLocalFilters({ ...localFilters, stage: e.target.value }) @@ -624,7 +624,7 @@ export function SwpTableToolbar({ {/* 상태 */}
- + - {isRefreshing ? "로딩 중..." : "검색"} + {isRefreshing ? "Loading..." : "Search"}
diff --git a/lib/swp/table/swp-table.tsx b/lib/swp/table/swp-table.tsx index 6f810415..348f388b 100644 --- a/lib/swp/table/swp-table.tsx +++ b/lib/swp/table/swp-table.tsx @@ -47,7 +47,7 @@ export function SwpTable({ const statusMap = new Map(); documents.forEach((doc) => { - const status = doc.LTST_ACTV_STAT || "UNKNOWN"; + const status = doc.LTST_ACTV_STAT || "Waiting"; statusMap.set(status, (statusMap.get(status) || 0) + 1); }); @@ -68,7 +68,7 @@ export function SwpTable({ if (!selectedStatus) { return documents; } - return documents.filter((doc) => doc.LTST_ACTV_STAT === selectedStatus); + return documents.filter((doc) => (doc.LTST_ACTV_STAT || "Waiting") === selectedStatus); }, [documents, selectedStatus]); const table = useReactTable({ @@ -95,7 +95,7 @@ export function SwpTable({ onClick={() => setSelectedStatus(null)} className="h-9" > - 전체 ({documents.length}) + All ({documents.length}) {statusCounts.map((statusCount) => ( +
diff --git a/lib/swp/table/swp-upload-validation-dialog.tsx b/lib/swp/table/swp-upload-validation-dialog.tsx index 803b1564..3357ec7a 100644 --- a/lib/swp/table/swp-upload-validation-dialog.tsx +++ b/lib/swp/table/swp-upload-validation-dialog.tsx @@ -69,7 +69,7 @@ export function validateFileName( if (lastDotIndex === -1) { return { valid: false, - error: "파일 확장자가 없습니다", + error: "File extension missing", }; } @@ -83,7 +83,7 @@ export function validateFileName( if (parts.length < 3) { return { valid: false, - error: `언더스코어(_)가 최소 2개 있어야 합니다 (현재: ${parts.length - 1}개). 형식: [OWN_DOC_NO]_[REV_NO]_[STAGE].[확장자]`, + error: `Must have at least 2 underscores (_) (Current: ${parts.length - 1}). Format: [OWN_DOC_NO]_[REV_NO]_[STAGE].[Extension]`, }; } @@ -99,21 +99,21 @@ export function validateFileName( if (!ownDocNo || ownDocNo.trim() === "") { return { valid: false, - error: "문서번호(OWN_DOC_NO)가 비어있습니다", + error: "Document Number (OWN_DOC_NO) is empty", }; } if (!revNo || revNo.trim() === "") { return { valid: false, - error: "리비전 번호(REV_NO)가 비어있습니다", + error: "Revision Number (REV_NO) is empty", }; } if (!stage || stage.trim() === "") { return { valid: false, - error: "스테이지(STAGE)가 비어있습니다", + error: "Stage (STAGE) is empty", }; } @@ -127,7 +127,7 @@ export function validateFileName( if (!availableDocNos || availableDocNos.length === 0) { return { valid: false, - error: "할당된 문서가 없거나 문서 목록 로드에 실패했습니다. 페이지를 새로고침하거나 관리자에게 문의하세요.", + error: "No assigned documents or failed to load document list. Please refresh the page or contact administrator.", }; } @@ -135,7 +135,7 @@ export function validateFileName( if (!availableDocNos.includes(trimmedDocNo)) { return { valid: false, - error: `문서번호 '${trimmedDocNo}'는 업로드 권한이 없습니다. 할당된 문서번호를 확인해주세요.`, + error: `Document number '${trimmedDocNo}' does not have upload permission. Please check assigned document numbers.`, }; } } @@ -152,7 +152,7 @@ export function validateFileName( // 문서가 EVCP DB에 등록되지 않음 return { valid: false, - error: `문서번호 '${trimmedDocNo}'는 문서 리스트에 등록되지 않았습니다. 먼저 문서 리스트를 제출해주세요.`, + error: `Document number '${trimmedDocNo}' is not registered in the document list. Please submit the document list first.`, }; } @@ -163,7 +163,7 @@ export function validateFileName( // Document Class에 Stage가 설정되지 않음 return { valid: false, - error: `문서 '${trimmedDocNo}'의 Document Class '${docCls}'에 Stage가 설정되지 않았습니다. 관리자에게 문의하세요.`, + error: `Stage is not set for Document Class '${docCls}' of document '${trimmedDocNo}'. Please contact administrator.`, }; } @@ -171,7 +171,7 @@ export function validateFileName( if (!allowedStages.includes(trimmedStage)) { return { valid: false, - error: `문서 '${trimmedDocNo}'의 Document Class '${docCls}'에서 Stage '${trimmedStage}'는 허용되지 않습니다. 허용된 Stage: ${allowedStages.join(", ")}`, + error: `Stage '${trimmedStage}' is not allowed for Document Class '${docCls}' of document '${trimmedDocNo}'. Allowed Stages: ${allowedStages.join(", ")}`, }; } @@ -181,7 +181,7 @@ export function validateFileName( console.log(`[validateFileName] 검증 정보가 없음 → 업로드 차단`); return { valid: false, - error: "문서 정보를 가져올 수 없습니다. 페이지를 새로고침하거나 프로젝트를 다시 선택해주세요.", + error: "Cannot retrieve document info. Please refresh the page or re-select the project.", }; } @@ -198,7 +198,7 @@ export function validateFileName( } catch (error) { return { valid: false, - error: error instanceof Error ? error.message : "알 수 없는 오류", + error: error instanceof Error ? error.message : "Unknown error", }; } } @@ -234,9 +234,9 @@ export function SwpUploadValidationDialog({ - 파일 업로드 검증 + File Upload Validation - 선택한 파일의 파일명 형식을 검증합니다 + Validating file name format of selected files @@ -244,17 +244,17 @@ export function SwpUploadValidationDialog({ {/* 요약 통계 */}
-
전체 파일
+
Total Files
{validationResults.length}
-
검증 성공
+
Validation Success
{validFiles.length}
-
검증 실패
+
Validation Failed
{invalidFiles.length}
@@ -266,8 +266,8 @@ export function SwpUploadValidationDialog({ - {invalidFiles.length}개 파일의 파일명 형식이 올바르지 않습니다. - 검증에 성공한 {validFiles.length}개 파일만 업로드됩니다. + {invalidFiles.length} files have incorrect file name format. + Only {validFiles.length} successfully validated files will be uploaded. )} @@ -276,7 +276,7 @@ export function SwpUploadValidationDialog({ - 업로드 가능한 파일이 없습니다. 파일명 형식을 확인해주세요. + No uploadable files. Please check file name format. )} @@ -289,7 +289,7 @@ export function SwpUploadValidationDialog({

- 검증 성공 ({validFiles.length}개) + Validation Success ({validFiles.length})

{validFiles.map((result, index) => (
- 문서: {result.parsed.ownDocNo} + Doc: {result.parsed.ownDocNo} Rev: {result.parsed.revNo} @@ -314,11 +314,11 @@ export function SwpUploadValidationDialog({ {result.parsed.fileName && ( - 파일명: {result.parsed.fileName} + FileName: {result.parsed.fileName} )} - 확장자: .{result.parsed.extension} + Ext: .{result.parsed.extension}
)} @@ -335,7 +335,7 @@ export function SwpUploadValidationDialog({

- 검증 실패 ({invalidFiles.length}개) + Validation Failed ({invalidFiles.length})

{invalidFiles.map((result, index) => (
- 📋 올바른 파일명 형식 + 📋 Correct File Name Format
- [OWN_DOC_NO]_[REV_NO]_[STAGE].[확장자] + [OWN_DOC_NO]_[REV_NO]_[STAGE].[Extension]
- 예: VD-DOC-001_01_IFA.pdf + Ex: VD-DOC-001_01_IFA.pdf
- ※ 선택사항: [OWN_DOC_NO]_[REV_NO]_[STAGE]_[파일명].[확장자] (파일명 추가 가능) + ※ Optional: [OWN_DOC_NO]_[REV_NO]_[STAGE]_[FileName].[Extension] (FileName can be added)
- ※ 파일명에는 언더스코어(_)가 포함될 수 있습니다. + ※ File name can contain underscores (_).
{isVendorMode && ( <>
{availableDocNos.length > 0 ? ( - <>ℹ️ 업로드 가능한 문서: {availableDocNos.length}개 + <>ℹ️ Uploadable Documents: {availableDocNos.length} ) : ( - <>⚠️ 할당된 문서가 없습니다 + <>⚠️ No assigned documents )}
- ⚠️ 각 문서의 Document Class에 정의된 Stage만 사용할 수 있습니다. + ⚠️ Only Stages defined in each document's Document Class can be used.
)} @@ -402,7 +402,7 @@ export function SwpUploadValidationDialog({ onClick={handleCancel} disabled={isUploading} > - 취소 + Cancel diff --git a/lib/swp/table/swp-uploaded-files-dialog.tsx b/lib/swp/table/swp-uploaded-files-dialog.tsx index 14d69df4..e92cb0ad 100644 --- a/lib/swp/table/swp-uploaded-files-dialog.tsx +++ b/lib/swp/table/swp-uploaded-files-dialog.tsx @@ -90,8 +90,8 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi if (!projNo) { toast({ variant: "destructive", - title: "조회 불가", - description: "프로젝트 정보가 필요합니다.", + title: "Unable to retrieve files", + description: "Project information is required.", }); return; } @@ -102,15 +102,15 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi const result = await fetchVendorUploadedFiles(projNo); setFiles(result); toast({ - title: "조회 완료", - description: `${result.length}개의 파일을 조회했습니다.`, + title: "Files retrieved successfully", + description: `${result.length} files retrieved.`, }); } catch (error) { - console.error("파일 목록 조회 실패:", error); + console.error("Failed to retrieve files:", error); toast({ variant: "destructive", - title: "조회 실패", - description: error instanceof Error ? error.message : "알 수 없는 오류", + title: "Failed to retrieve files", + description: error instanceof Error ? error.message : "Unknown error", }); } }); @@ -121,8 +121,8 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi if (!file.BOX_SEQ || !file.ACTV_SEQ) { toast({ variant: "destructive", - title: "취소 불가", - description: "파일 정보가 올바르지 않습니다.", + title: "Unable to cancel file", + description: "File information is invalid.", }); return; } @@ -138,18 +138,18 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi }); toast({ - title: "취소 완료", - description: `${file.FILE_NM} 파일이 취소되었습니다.`, + title: "File canceled successfully", + description: `${file.FILE_NM} file canceled.`, }); // 목록 새로고침 loadFiles(); } catch (error) { - console.error("파일 취소 실패:", error); + console.error("Failed to cancel file:", error); toast({ variant: "destructive", - title: "취소 실패", - description: error instanceof Error ? error.message : "알 수 없는 오류", + title: "Failed to cancel file", + description: error instanceof Error ? error.message : "Unknown error", }); } finally { setCancellingFiles((prev) => { @@ -192,14 +192,14 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi - 업로드한 파일 목록 + Uploaded File List - 프로젝트: {projNo} | 업체: {vndrCd} + Project: {projNo} | Company: {vndrCd} @@ -207,7 +207,7 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi {/* 액션 바 */}
- 총 {files.length}개 파일 + Total {files.length} files
@@ -234,11 +234,11 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi {isLoading && files.length === 0 ? (
- 파일 목록을 조회하는 중... + Loading files...
) : files.length === 0 ? (
- 업로드한 파일이 없습니다. + No files uploaded.
) : (
@@ -257,7 +257,7 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi {docNo} - {docNode.revisions.size}개 리비전 + {docNode.revisions.size} revisions
@@ -280,7 +280,7 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi )} Rev: {revNo} - {revNode.files.files.length}개 파일 + {revNode.files.files.length} files
@@ -303,7 +303,7 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi
Stage: {file.STAGE} - 상태: {file.STAT_NM || file.STAT || "알 수 없음"} + Status: {file.STAT_NM || file.STAT || "Unknown"}
@@ -348,8 +348,8 @@ export function SwpUploadedFilesDialog({ projNo, vndrCd, userId }: SwpUploadedFi {/* 안내 메시지 */}
-

ℹ️ 접수 전(SCW01) 상태의 파일만 취소할 수 있습니다.

-

ℹ️ 취소된 파일은 목록에서 제거됩니다.

+

Files in the 'SCW01' status can only be canceled.

+

Canceled files will be removed from the list.

-- cgit v1.2.3