- 선택된 파일 ({selectedFiles.length}개)
+ {t("bulkUpload.selectedFiles", { count: selectedFiles.length })}
@@ -555,7 +559,7 @@ export function B4BulkUploadDialog({
size="sm"
onClick={() => handleRemoveFile(index)}
>
- 제거
+ {t("bulkUpload.removeFile")}
))}
@@ -570,7 +574,7 @@ export function B4BulkUploadDialog({
- 파일 검증 중입니다...
+ {t("bulkUpload.validating")}
)}
@@ -580,21 +584,21 @@ export function B4BulkUploadDialog({
-
파일 업로드 중...
+
{t("bulkUpload.uploading")}
- 잠시만 기다려주세요
+ {t("bulkUpload.uploadingWait")}
- 진행률
+ {t("bulkUpload.uploadProgress")}
{uploadProgress}%
{/* 90% 이상일 때 추가 안내 메시지 */}
{uploadProgress >= 90 && uploadProgress < 100 && (
- 서버에서 DOLCE API로 전송 중입니다...
+ {t("bulkUpload.uploadingToServer")}
)}
@@ -606,16 +610,16 @@ export function B4BulkUploadDialog({
-
업로드 완료!
+
{t("bulkUpload.uploadComplete")}
- {uploadResult.successCount}개 파일이 성공적으로 업로드되었습니다
+ {t("bulkUpload.uploadSuccessMessage", { count: uploadResult.successCount })}
{uploadResult.failCount && uploadResult.failCount > 0 && (
- {uploadResult.failCount}개 파일 업로드 실패
+ {t("bulkUpload.uploadFailMessage", { count: uploadResult.failCount })}
)}
@@ -627,7 +631,7 @@ export function B4BulkUploadDialog({
onUploadComplete?.();
}}
>
- 확인
+ {t("bulkUpload.confirmButton")}
@@ -643,13 +647,13 @@ export function B4BulkUploadDialog({
variant="outline"
onClick={() => onOpenChange(false)}
>
- 취소
+ {t("bulkUpload.cancelButton")}
>
@@ -662,13 +666,13 @@ export function B4BulkUploadDialog({
onClick={() => setCurrentStep("settings")}
>
- 이전
+ {t("bulkUpload.previousButton")}
>
@@ -685,6 +689,7 @@ export function B4BulkUploadDialog({
validationResults={validationResults}
onConfirmUpload={handleConfirmUpload}
isUploading={isUploading}
+ lng={lng}
/>
>
);
diff --git a/lib/dolce/dialogs/detail-drawing-dialog.tsx b/lib/dolce/dialogs/detail-drawing-dialog.tsx
index a06c9688..d9df58db 100644
--- a/lib/dolce/dialogs/detail-drawing-dialog.tsx
+++ b/lib/dolce/dialogs/detail-drawing-dialog.tsx
@@ -12,6 +12,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { Plus, RefreshCw, Upload, Loader2 } from "lucide-react";
import { toast } from "sonner";
+import { useTranslation } from "@/i18n/client";
import {
UnifiedDwgReceiptItem,
DetailDwgReceiptItem,
@@ -20,7 +21,7 @@ import {
fetchFileInfoList,
} from "../actions";
import { DrawingListTable } from "../table/drawing-list-table";
-import { detailDrawingColumns } from "../table/detail-drawing-columns";
+import { createDetailDrawingColumns } from "../table/detail-drawing-columns";
import { createFileListColumns } from "../table/file-list-columns";
import { AddDetailDrawingDialog } from "./add-detail-drawing-dialog";
import { UploadFilesToDetailDialog } from "./upload-files-to-detail-dialog";
@@ -34,6 +35,7 @@ interface DetailDrawingDialogProps {
userName: string;
userEmail: string;
drawingKind: "B3" | "B4";
+ lng: string;
}
export function DetailDrawingDialog({
@@ -45,7 +47,9 @@ export function DetailDrawingDialog({
userName,
userEmail,
drawingKind,
+ lng,
}: DetailDrawingDialogProps) {
+ const { t } = useTranslation(lng, "dolce");
const [detailDrawings, setDetailDrawings] = useState
([]);
const [selectedDetail, setSelectedDetail] = useState(null);
const [files, setFiles] = useState([]);
@@ -75,11 +79,11 @@ export function DetailDrawingDialog({
}
} catch (error) {
console.error("상세도면 로드 실패:", error);
- toast.error("상세도면 로드에 실패했습니다");
+ toast.error(t("detailDialog.detailLoadError"));
} finally {
setIsLoading(false);
}
- }, [drawing, selectedDetail]);
+ }, [drawing, selectedDetail, t]);
// 파일 목록 로드
const loadFiles = useCallback(async () => {
@@ -94,11 +98,11 @@ export function DetailDrawingDialog({
setFiles(data);
} catch (error) {
console.error("파일 목록 로드 실패:", error);
- toast.error("파일 목록 로드에 실패했습니다");
+ toast.error(t("detailDialog.fileLoadError"));
} finally {
setIsLoadingFiles(false);
}
- }, [selectedDetail]);
+ }, [selectedDetail, t]);
// 다이얼로그 열릴 때 데이터 로드
useEffect(() => {
@@ -120,7 +124,7 @@ export function DetailDrawingDialog({
const handleDownload = async (file: FileInfoItem) => {
try {
- toast.info("파일 다운로드를 준비 중입니다...");
+ toast.info(t("detailDialog.downloadPreparing"));
// 파일 생성자의 userId를 사용하여 다운로드
const response = await fetch("/api/dolce/download", {
@@ -136,7 +140,7 @@ export function DetailDrawingDialog({
});
if (!response.ok) {
- throw new Error("파일 다운로드 실패");
+ throw new Error(t("detailDialog.downloadError"));
}
const blob = await response.blob();
@@ -149,10 +153,10 @@ export function DetailDrawingDialog({
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
- toast.success("파일 다운로드가 완료되었습니다");
+ toast.success(t("detailDialog.downloadSuccess"));
} catch (error) {
console.error("파일 다운로드 실패:", error);
- toast.error("파일 다운로드에 실패했습니다");
+ toast.error(t("detailDialog.downloadError"));
}
};
@@ -170,7 +174,7 @@ export function DetailDrawingDialog({
loadFiles();
};
- const fileColumns = createFileListColumns({ onDownload: handleDownload });
+ const fileColumns = createFileListColumns({ onDownload: handleDownload, lng });
// RegisterId + UploadId 조합으로 고유 ID 생성
const getDetailDrawingId = (detail: DetailDwgReceiptItem) => {
@@ -188,10 +192,15 @@ export function DetailDrawingDialog({
- 상세도면 정보
+ {t("detailDialog.title")}
{drawing && (
- {drawing.DrawingNo} | 프로젝트: {drawing.ProjectNo} | Discipline: {drawing.Discipline} | 종류: {drawing.DrawingKind}
+ {t("detailDialog.subtitle", {
+ drawingNo: drawing.DrawingNo,
+ projectNo: drawing.ProjectNo,
+ discipline: drawing.Discipline,
+ drawingKind: drawing.DrawingKind
+ })}
)}
@@ -201,7 +210,7 @@ export function DetailDrawingDialog({
{/* 상단: 상세도면 리스트 */}
- 상세도면 목록
+ {t("detailDialog.detailListTitle")}
{canAddDetailDrawing && (
)}
- columns={detailDrawingColumns}
+ columns={createDetailDrawingColumns(lng, t)}
data={detailDrawings}
onRowClick={setSelectedDetail}
selectedRow={selectedDetail || undefined}
@@ -239,8 +248,8 @@ export function DetailDrawingDialog({
- 첨부파일 목록
- {selectedDetail && ` - Rev. ${selectedDetail.DrawingRevNo}`}
+ {t("detailDialog.fileListTitle")}
+ {selectedDetail && t("detailDialog.fileListSubtitle", { revNo: selectedDetail.DrawingRevNo })}
{selectedDetail && canAddDetailDrawing && (
)}
{!selectedDetail ? (
- 상세도면을 선택하세요
+ {t("detailDialog.selectDetailDrawing")}
) : isLoadingFiles ? (
- Loading files...
+ {t("detailDialog.loadingFiles")}
@@ -292,6 +301,7 @@ export function DetailDrawingDialog({
userEmail={userEmail}
onComplete={handleAddComplete}
drawingKind={drawingKind}
+ lng={lng}
/>
{selectedDetail && (
@@ -303,6 +313,7 @@ export function DetailDrawingDialog({
revNo={selectedDetail.DrawingRevNo}
userId={userId}
onUploadComplete={handleUploadComplete}
+ lng={lng}
/>
)}
>
diff --git a/lib/dolce/dialogs/upload-files-to-detail-dialog.tsx b/lib/dolce/dialogs/upload-files-to-detail-dialog.tsx
index 431a2c77..09f68614 100644
--- a/lib/dolce/dialogs/upload-files-to-detail-dialog.tsx
+++ b/lib/dolce/dialogs/upload-files-to-detail-dialog.tsx
@@ -26,6 +26,7 @@ interface UploadFilesToDetailDialogProps {
revNo: string;
userId: string;
onUploadComplete?: () => void;
+ lng?: string; // i18n support
}
export function UploadFilesToDetailDialog({
diff --git a/lib/dolce/table/detail-drawing-columns.tsx b/lib/dolce/table/detail-drawing-columns.tsx
index 7f519179..77d25953 100644
--- a/lib/dolce/table/detail-drawing-columns.tsx
+++ b/lib/dolce/table/detail-drawing-columns.tsx
@@ -2,7 +2,41 @@
import { ColumnDef } from "@tanstack/react-table";
import { DetailDwgReceiptItem } from "../actions";
+import { formatDolceDateTime } from "../utils/date-formatter";
+// DOLCE API ENM 필드가 제대로 번역되지 않아 직접 매핑
+const DRAWING_USAGE_MAP: Record
= {
+ APP: { ko: "승인용", en: "Approval" },
+ WOR: { ko: "작업용", en: "Working" },
+ REC: { ko: "입수용 / GTT→SHI", en: "GTT→SHI" },
+ SUB: { ko: "제출용 / SHI→GTT", en: "SHI→GTT" },
+};
+
+const REGISTER_KIND_MAP: Record = {
+ APPR: { ko: "승인 제출용 도면(Full)", en: "For Approval(Full)" },
+ APPP: { ko: "승인 제출용 도면(Partial)", en: "For Approval(Partial)" },
+ WORK: { ko: "작업용 입수도면(Full)", en: "For Working(Full)" },
+ WORP: { ko: "작업용 입수도면(Partial)", en: "For Working(Partial)" },
+ RECW: { ko: "Working 도면입수(GTT→SHI)", en: "Working Dwg(GTT→SHI)" },
+ RECP: { ko: "Pre. 도면입수(GTT→SHI)", en: "Pre. Dwg(GTT→SHI)" },
+};
+
+// 카테고리는 API에서 ENM이 제공되는 것으로 가정 (필요시 추가)
+const translateDrawingUsage = (code: string | null, lng: string): string => {
+ if (!code) return "";
+ const mapped = DRAWING_USAGE_MAP[code];
+ if (!mapped) return code;
+ return lng === "en" ? mapped.en : mapped.ko;
+};
+
+const translateRegisterKind = (code: string | null, lng: string): string => {
+ if (!code) return "";
+ const mapped = REGISTER_KIND_MAP[code];
+ if (!mapped) return code;
+ return lng === "en" ? mapped.en : mapped.ko;
+};
+
+// 기본 컬럼 (기존 호환성 유지)
export const detailDrawingColumns: ColumnDef[] = [
{
accessorKey: "RegisterSerialNo",
@@ -78,3 +112,88 @@ export const detailDrawingColumns: ColumnDef[] = [
},
];
+// 다국어 지원 컬럼 생성 함수
+export function createDetailDrawingColumns(
+ lng: string,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ t: any
+): ColumnDef[] {
+ return [
+ {
+ accessorKey: "RegisterSerialNo",
+ header: t("detailDrawing.columns.serialNo"),
+ minSize: 80,
+ cell: ({ row }) => {
+ return {row.getValue("RegisterSerialNo")}
;
+ },
+ },
+ {
+ accessorKey: "DrawingRevNo",
+ header: t("detailDrawing.columns.revNo"),
+ minSize: 100,
+ cell: ({ row }) => {
+ return {row.getValue("DrawingRevNo")}
;
+ },
+ },
+ {
+ accessorKey: "Status",
+ header: t("detailDrawing.columns.status"),
+ minSize: 120,
+ cell: ({ row }) => {
+ return {row.getValue("Status")}
;
+ },
+ },
+ {
+ accessorKey: "CategoryENM",
+ header: t("detailDrawing.columns.category"),
+ minSize: 120,
+ cell: ({ row }) => {
+ const categoryENM = row.getValue("CategoryENM") as string;
+ const categoryNM = row.original.CategoryNM;
+ // 영어인 경우 ENM, 한국어인 경우 NM 사용
+ return {lng === "en" ? (categoryENM || categoryNM) : (categoryNM || categoryENM)}
;
+ },
+ },
+ {
+ accessorKey: "DrawingUsageENM",
+ header: t("detailDrawing.columns.drawingUsage"),
+ minSize: 100,
+ cell: ({ row }) => {
+ // API의 ENM이 제대로 번역되지 않아 코드 값으로 직접 변환
+ const usageCode = row.getValue("DrawingUsageENM") as string | null;
+ const translated = translateDrawingUsage(usageCode, lng);
+ return {translated || usageCode || row.original.DrawingUsageNM}
;
+ },
+ },
+ {
+ accessorKey: "RegisterKindENM",
+ header: t("detailDrawing.columns.registerKind"),
+ minSize: 180,
+ cell: ({ row }) => {
+ // API의 ENM이 제대로 번역되지 않아 코드 값으로 직접 변환
+ const kindCode = row.getValue("RegisterKindENM") as string | null;
+ const translated = translateRegisterKind(kindCode, lng);
+ return {translated || kindCode || row.original.RegisterKindNM}
;
+ },
+ },
+ {
+ accessorKey: "CreateUserNM",
+ header: t("detailDrawing.columns.createdBy"),
+ minSize: 150,
+ cell: ({ row }) => {
+ const userENM = row.original.CreateUserENM;
+ const userNM = row.getValue("CreateUserNM") as string;
+ return {lng === "en" ? (userENM || userNM) : (userNM || userENM)}
;
+ },
+ },
+ {
+ accessorKey: "CreateDt",
+ header: t("detailDrawing.columns.createdAt"),
+ minSize: 200,
+ cell: ({ row }) => {
+ const date = row.getValue("CreateDt") as string;
+ return {formatDolceDateTime(date)}
;
+ },
+ },
+ ];
+}
diff --git a/lib/dolce/table/drawing-list-columns.tsx b/lib/dolce/table/drawing-list-columns.tsx
index 0e18266d..58631084 100644
--- a/lib/dolce/table/drawing-list-columns.tsx
+++ b/lib/dolce/table/drawing-list-columns.tsx
@@ -2,86 +2,86 @@
import { ColumnDef } from "@tanstack/react-table";
import { DwgReceiptItem } from "../actions";
+import { formatDolceDateYYYYMMDD, formatDolceDateTime } from "../utils/date-formatter";
-export const drawingListColumns: ColumnDef[] = [
- {
- accessorKey: "DrawingNo",
- header: "도면번호",
- minSize: 200,
- cell: ({ row }) => {
- return {row.getValue("DrawingNo")}
;
+export function drawingListColumns(lng: string, t: any): ColumnDef[] {
+ return [
+ {
+ accessorKey: "DrawingNo",
+ header: t("drawingList.columns.drawingNo"),
+ minSize: 200,
+ cell: ({ row }) => {
+ return {row.getValue("DrawingNo")}
;
+ },
},
- },
- {
- accessorKey: "DrawingName",
- header: "도면명",
- minSize: 400,
- cell: ({ row }) => {
- return {row.getValue("DrawingName")}
;
+ {
+ accessorKey: "DrawingName",
+ header: t("drawingList.columns.drawingName"),
+ minSize: 600,
+ cell: ({ row }) => {
+ return {row.getValue("DrawingName")}
;
+ },
},
- },
- {
- accessorKey: "Discipline",
- header: "설계공종",
- minSize: 80,
- },
- {
- accessorKey: "Manager",
- header: "담당자명",
- minSize: 200,
- cell: ({ row }) => {
- const managerENM = row.original.ManagerENM;
- const manager = row.getValue("Manager");
- return {managerENM || manager}
;
+ {
+ accessorKey: "Discipline",
+ header: t("drawingList.columns.discipline"),
+ minSize: 80,
},
- },
- {
- accessorKey: "AppDwg_PlanDate",
- header: "승인도면 예정일",
- minSize: 140,
- cell: ({ row }) => {
- const date = row.getValue("AppDwg_PlanDate") as string;
- if (!date || date.length !== 8) return null;
- return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ {
+ accessorKey: "Manager",
+ header: t("drawingList.columns.manager"),
+ minSize: 200,
+ cell: ({ row }) => {
+ const managerENM = row.original.ManagerENM;
+ const manager = row.getValue("Manager");
+ return {managerENM || manager}
;
+ },
},
- },
- {
- accessorKey: "AppDwg_ResultDate",
- header: "승인도면 결과일",
- minSize: 140,
- cell: ({ row }) => {
- const date = row.getValue("AppDwg_ResultDate") as string;
- if (!date || date.length !== 8) return null;
- return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ {
+ accessorKey: "AppDwg_PlanDate",
+ header: t("drawingList.columns.appDwgPlanDate"),
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("AppDwg_PlanDate") as string;
+ return formatDolceDateYYYYMMDD(date);
+ },
},
- },
- {
- accessorKey: "WorDwg_PlanDate",
- header: "작업도면 예정일",
- minSize: 140,
- cell: ({ row }) => {
- const date = row.getValue("WorDwg_PlanDate") as string;
- if (!date || date.length !== 8) return null;
- return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ {
+ accessorKey: "AppDwg_ResultDate",
+ header: t("drawingList.columns.appDwgResultDate"),
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("AppDwg_ResultDate") as string;
+ return formatDolceDateYYYYMMDD(date);
+ },
},
- },
- {
- accessorKey: "WorDwg_ResultDate",
- header: "작업도면 결과일",
- minSize: 140,
- cell: ({ row }) => {
- const date = row.getValue("WorDwg_ResultDate") as string;
- if (!date || date.length !== 8) return null;
- return `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`;
+ {
+ accessorKey: "WorDwg_PlanDate",
+ header: t("drawingList.columns.worDwgPlanDate"),
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("WorDwg_PlanDate") as string;
+ return formatDolceDateYYYYMMDD(date);
+ },
},
- },
- {
- accessorKey: "CreateDt",
- header: "생성일시",
- minSize: 200,
- cell: ({ row }) => {
- return {row.getValue("CreateDt")}
;
+ {
+ accessorKey: "WorDwg_ResultDate",
+ header: t("drawingList.columns.worDwgResultDate"),
+ minSize: 140,
+ cell: ({ row }) => {
+ const date = row.getValue("WorDwg_ResultDate") as string;
+ return formatDolceDateYYYYMMDD(date);
+ },
},
- },
-];
+ {
+ accessorKey: "CreateDt",
+ header: t("drawingList.columns.createDt"),
+ minSize: 260,
+ cell: ({ row }) => {
+ const date = row.getValue("CreateDt") as string;
+ return {formatDolceDateTime(date)}
;
+ },
+ },
+ ];
+}
diff --git a/lib/dolce/table/file-list-columns.tsx b/lib/dolce/table/file-list-columns.tsx
index f703d56d..36a579a3 100644
--- a/lib/dolce/table/file-list-columns.tsx
+++ b/lib/dolce/table/file-list-columns.tsx
@@ -4,17 +4,20 @@ import { ColumnDef } from "@tanstack/react-table";
import { FileInfoItem } from "../actions";
import { Button } from "@/components/ui/button";
import { Download } from "lucide-react";
+import { formatDolceDateTime } from "../utils/date-formatter";
interface FileListColumnsProps {
onDownload: (file: FileInfoItem) => void;
+ lng?: string;
}
export const createFileListColumns = ({
onDownload,
+ lng = "ko",
}: FileListColumnsProps): ColumnDef[] => [
{
accessorKey: "FileSeq",
- header: "순번",
+ header: lng === "ko" ? "순번" : "No.",
minSize: 80,
cell: ({ row }) => {
return {row.getValue("FileSeq")}
;
@@ -22,7 +25,7 @@ export const createFileListColumns = ({
},
{
accessorKey: "FileName",
- header: "파일명",
+ header: lng === "ko" ? "파일명" : "File Name",
minSize: 300,
cell: ({ row }) => {
return {row.getValue("FileName")}
;
@@ -30,7 +33,7 @@ export const createFileListColumns = ({
},
{
accessorKey: "FileSize",
- header: "파일크기",
+ header: lng === "ko" ? "파일크기" : "File Size",
minSize: 100,
cell: ({ row }) => {
const size = parseInt(row.getValue("FileSize") as string);
@@ -43,15 +46,16 @@ export const createFileListColumns = ({
},
{
accessorKey: "CreateDt",
- header: "생성일시",
+ header: lng === "ko" ? "생성일시" : "Created Date",
minSize: 200,
cell: ({ row }) => {
- return {row.getValue("CreateDt")}
;
+ const date = row.getValue("CreateDt") as string;
+ return {formatDolceDateTime(date)}
;
},
},
{
id: "actions",
- header: "다운로드",
+ header: lng === "ko" ? "다운로드" : "Download",
minSize: 120,
cell: ({ row }) => {
return (
@@ -61,7 +65,7 @@ export const createFileListColumns = ({
onClick={() => onDownload(row.original)}
>
- 다운로드
+ {lng === "ko" ? "다운로드" : "Download"}
);
},
diff --git a/lib/dolce/table/gtt-drawing-list-columns.tsx b/lib/dolce/table/gtt-drawing-list-columns.tsx
index 2ff2d7e2..093fc10c 100644
--- a/lib/dolce/table/gtt-drawing-list-columns.tsx
+++ b/lib/dolce/table/gtt-drawing-list-columns.tsx
@@ -2,27 +2,27 @@
import { ColumnDef } from "@tanstack/react-table";
import { GttDwgReceiptItem } from "../actions";
-
-// 날짜 포맷 헬퍼
-function formatDate(dateStr: string | null): string | null {
- if (!dateStr || dateStr.length !== 8) return null;
- return `${dateStr.substring(0, 4)}-${dateStr.substring(4, 6)}-${dateStr.substring(6, 8)}`;
-}
+import { translateDrawingMoveGbn } from "../utils/code-translator";
+import { formatDolceDateYYYYMMDD, formatDolceDateTime } from "../utils/date-formatter";
// Document Type 필터
export type DocumentType = "ALL" | "GTT_DELIVERABLES" | "SHI_INPUT";
interface GttDrawingListColumnsOptions {
documentType: DocumentType;
+ lng: string;
+ t: any;
}
export function createGttDrawingListColumns({
documentType,
+ lng,
+ t,
}: GttDrawingListColumnsOptions): ColumnDef[] {
const baseColumns: ColumnDef[] = [
{
accessorKey: "DrawingNo",
- header: "도면번호",
+ header: t("drawingList.columns.drawingNo"),
minSize: 200,
cell: ({ row }) => {
return {row.getValue("DrawingNo")}
;
@@ -30,7 +30,7 @@ export function createGttDrawingListColumns({
},
{
accessorKey: "DrawingName",
- header: "도면명",
+ header: t("drawingList.columns.drawingName"),
minSize: 400,
cell: ({ row }) => {
return {row.getValue("DrawingName")}
;
@@ -38,12 +38,12 @@ export function createGttDrawingListColumns({
},
{
accessorKey: "Discipline",
- header: "설계공종",
+ header: t("drawingList.columns.discipline"),
minSize: 80,
},
{
accessorKey: "Manager",
- header: "담당자명",
+ header: t("drawingList.columns.manager"),
minSize: 200,
cell: ({ row }) => {
const managerENM = row.original.ManagerENM;
@@ -53,8 +53,12 @@ export function createGttDrawingListColumns({
},
{
accessorKey: "DrawingMoveGbn",
- header: "구분",
+ header: t("drawingList.columns.category"),
minSize: 120,
+ cell: ({ row }) => {
+ const value = row.getValue("DrawingMoveGbn") as string;
+ return {translateDrawingMoveGbn(value, lng)}
;
+ },
},
];
@@ -66,39 +70,39 @@ export function createGttDrawingListColumns({
dateColumns.push(
{
accessorKey: "GTTInput_PlanDate",
- header: "GTT Input 예정일",
+ header: t("drawingList.columns.gttInputPlanDate"),
minSize: 150,
- cell: ({ row }) => formatDate(row.getValue("GTTInput_PlanDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTInput_PlanDate")),
},
{
accessorKey: "GTTInput_ResultDate",
- header: "GTT Input 결과일",
+ header: t("drawingList.columns.gttInputResultDate"),
minSize: 150,
- cell: ({ row }) => formatDate(row.getValue("GTTInput_ResultDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTInput_ResultDate")),
},
{
accessorKey: "GTTPreDwg_PlanDate",
- header: "GTT Pre 예정일",
+ header: t("drawingList.columns.gttPreDwgPlanDate"),
minSize: 140,
- cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_PlanDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTPreDwg_PlanDate")),
},
{
accessorKey: "GTTPreDwg_ResultDate",
- header: "GTT Pre 결과일",
+ header: t("drawingList.columns.gttPreDwgResultDate"),
minSize: 140,
- cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_ResultDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTPreDwg_ResultDate")),
},
{
accessorKey: "GTTWorkingDwg_PlanDate",
- header: "GTT Working 예정일",
+ header: t("drawingList.columns.gttWorkingDwgPlanDate"),
minSize: 160,
- cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_PlanDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTWorkingDwg_PlanDate")),
},
{
accessorKey: "GTTWorkingDwg_ResultDate",
- header: "GTT Working 결과일",
+ header: t("drawingList.columns.gttWorkingDwgResultDate"),
minSize: 160,
- cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_ResultDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTWorkingDwg_ResultDate")),
}
);
}
@@ -107,15 +111,15 @@ export function createGttDrawingListColumns({
dateColumns.push(
{
accessorKey: "GTTInput_PlanDate",
- header: "Input 예정일",
+ header: t("drawingList.columns.inputPlanDate"),
minSize: 120,
- cell: ({ row }) => formatDate(row.getValue("GTTInput_PlanDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTInput_PlanDate")),
},
{
accessorKey: "GTTInput_ResultDate",
- header: "Input 결과일",
+ header: t("drawingList.columns.inputResultDate"),
minSize: 120,
- cell: ({ row }) => formatDate(row.getValue("GTTInput_ResultDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTInput_ResultDate")),
}
);
}
@@ -124,27 +128,27 @@ export function createGttDrawingListColumns({
dateColumns.push(
{
accessorKey: "GTTPreDwg_PlanDate",
- header: "Pre 예정일",
+ header: t("drawingList.columns.prePlanDate"),
minSize: 120,
- cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_PlanDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTPreDwg_PlanDate")),
},
{
accessorKey: "GTTPreDwg_ResultDate",
- header: "Pre 결과일",
+ header: t("drawingList.columns.preResultDate"),
minSize: 120,
- cell: ({ row }) => formatDate(row.getValue("GTTPreDwg_ResultDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTPreDwg_ResultDate")),
},
{
accessorKey: "GTTWorkingDwg_PlanDate",
- header: "Working 예정일",
+ header: t("drawingList.columns.workingPlanDate"),
minSize: 130,
- cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_PlanDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTWorkingDwg_PlanDate")),
},
{
accessorKey: "GTTWorkingDwg_ResultDate",
- header: "Working 결과일",
+ header: t("drawingList.columns.workingResultDate"),
minSize: 130,
- cell: ({ row }) => formatDate(row.getValue("GTTWorkingDwg_ResultDate")),
+ cell: ({ row }) => formatDolceDateYYYYMMDD(row.getValue("GTTWorkingDwg_ResultDate")),
}
);
}
@@ -153,10 +157,11 @@ export function createGttDrawingListColumns({
const endColumns: ColumnDef[] = [
{
accessorKey: "CreateDt",
- header: "생성일시",
+ header: t("drawingList.columns.createDt"),
minSize: 200,
cell: ({ row }) => {
- return {row.getValue("CreateDt")}
;
+ const date = row.getValue("CreateDt") as string;
+ return {formatDolceDateTime(date)}
;
},
},
];
diff --git a/lib/dolce/utils/code-translator.ts b/lib/dolce/utils/code-translator.ts
new file mode 100644
index 00000000..19cb4217
--- /dev/null
+++ b/lib/dolce/utils/code-translator.ts
@@ -0,0 +1,208 @@
+/**
+ * DOLCE 코드 값 번역 유틸리티
+ *
+ * 코드 값을 다국어로 번역하고, 검색 시 번역된 텍스트도 매칭할 수 있도록 지원
+ */
+
+// B3 DrawingUsage 번역
+export function translateB3DrawingUsage(code: string, lng: string): string {
+ const translations: Record> = {
+ "Approval": {
+ ko: "승인용",
+ en: "Approval",
+ },
+ "Working": {
+ ko: "작업용",
+ en: "Working",
+ },
+ "APP": {
+ ko: "승인용",
+ en: "Approval",
+ },
+ "WOR": {
+ ko: "작업용",
+ en: "Working",
+ },
+ };
+
+ return translations[code]?.[lng] || code;
+}
+
+// B3 RegisterKind 번역
+export function translateB3RegisterKind(code: string, lng: string): string {
+ const translations: Record> = {
+ "APPR": {
+ ko: "승인 제출용 도면(Full)",
+ en: "For Approval(Full)",
+ },
+ "APPP": {
+ ko: "승인 제출용 도면(Partial)",
+ en: "For Approval(Partial)",
+ },
+ "WORK": {
+ ko: "작업용 입수도면(Full)",
+ en: "For Working(Full)",
+ },
+ "WORP": {
+ ko: "작업용 입수도면(Partial)",
+ en: "For Working(Partial)",
+ },
+ };
+
+ return translations[code]?.[lng] || code;
+}
+
+// B4 DrawingUsage 번역
+export function translateB4DrawingUsage(code: string, lng: string): string {
+ const translations: Record> = {
+ "REC": {
+ ko: "입수용",
+ en: "GTT→SHI",
+ },
+ "SUB": {
+ ko: "제출용",
+ en: "SHI→GTT",
+ },
+ };
+
+ return translations[code]?.[lng] || code;
+}
+
+// B4 RegisterKind 번역
+export function translateB4RegisterKind(code: string, lng: string): string {
+ const translations: Record> = {
+ "RECW": {
+ ko: "Working 도면입수(GTT→SHI)",
+ en: "Working Dwg(GTT→SHI)",
+ },
+ "RECP": {
+ ko: "Pre. 도면입수(GTT→SHI)",
+ en: "Pre. Dwg(GTT→SHI)",
+ },
+ "SUBW": {
+ ko: "Working 제출용(SHI→GTT)",
+ en: "Working Submission(SHI→GTT)",
+ },
+ "SUBP": {
+ ko: "Pre. 제출용(SHI→GTT)",
+ en: "Pre. Submission(SHI→GTT)",
+ },
+ };
+
+ return translations[code]?.[lng] || code;
+}
+
+// DrawingMoveGbn 번역 (B4 GTT)
+export function translateDrawingMoveGbn(code: string, lng: string): string {
+ const translations: Record> = {
+ "도면입수": {
+ ko: "도면입수",
+ en: "Receipt",
+ },
+ "도면제출": {
+ ko: "도면제출",
+ en: "Submission",
+ },
+ };
+
+ return translations[code]?.[lng] || code;
+}
+
+// 통합 번역 함수
+export function translateDolceCode(
+ codeType: "B3_DrawingUsage" | "B3_RegisterKind" | "B4_DrawingUsage" | "B4_RegisterKind" | "DrawingMoveGbn",
+ code: string,
+ lng: string
+): string {
+ switch (codeType) {
+ case "B3_DrawingUsage":
+ return translateB3DrawingUsage(code, lng);
+ case "B3_RegisterKind":
+ return translateB3RegisterKind(code, lng);
+ case "B4_DrawingUsage":
+ return translateB4DrawingUsage(code, lng);
+ case "B4_RegisterKind":
+ return translateB4RegisterKind(code, lng);
+ case "DrawingMoveGbn":
+ return translateDrawingMoveGbn(code, lng);
+ default:
+ return code;
+ }
+}
+
+// 검색용: 코드와 번역된 텍스트 모두 매칭
+export function matchesTranslatedCode(
+ codeType: "B3_DrawingUsage" | "B3_RegisterKind" | "B4_DrawingUsage" | "B4_RegisterKind" | "DrawingMoveGbn",
+ code: string,
+ searchTerm: string,
+ lng: string
+): boolean {
+ if (!searchTerm) return true;
+
+ const normalizedSearch = searchTerm.toLowerCase();
+
+ // 원본 코드로 검색
+ if (code.toLowerCase().includes(normalizedSearch)) {
+ return true;
+ }
+
+ // 번역된 텍스트로 검색
+ const translated = translateDolceCode(codeType, code, lng);
+ if (translated.toLowerCase().includes(normalizedSearch)) {
+ return true;
+ }
+
+ // 다른 언어의 번역도 검색 (한국어 사용자가 영어로 검색하는 경우)
+ const otherLng = lng === "ko" ? "en" : "ko";
+ const otherTranslated = translateDolceCode(codeType, code, otherLng);
+ if (otherTranslated.toLowerCase().includes(normalizedSearch)) {
+ return true;
+ }
+
+ return false;
+}
+
+// 옵션 목록 생성 (Select 컴포넌트용)
+export function getB3DrawingUsageOptions(lng: string) {
+ return [
+ { value: "APP", label: translateB3DrawingUsage("APP", lng) },
+ { value: "WOR", label: translateB3DrawingUsage("WOR", lng) },
+ ];
+}
+
+export function getB3RegisterKindOptions(drawingUsage: string, lng: string) {
+ if (drawingUsage === "APP") {
+ return [
+ { value: "APPR", label: translateB3RegisterKind("APPR", lng) },
+ { value: "APPP", label: translateB3RegisterKind("APPP", lng) },
+ ];
+ } else if (drawingUsage === "WOR") {
+ return [
+ { value: "WORK", label: translateB3RegisterKind("WORK", lng) },
+ { value: "WORP", label: translateB3RegisterKind("WORP", lng) },
+ ];
+ }
+ return [];
+}
+
+export function getB4DrawingUsageOptions(lng: string) {
+ return [
+ { value: "REC", label: translateB4DrawingUsage("REC", lng) },
+ ];
+}
+
+export function getB4RegisterKindOptions(drawingUsage: string, lng: string) {
+ if (drawingUsage === "REC") {
+ return [
+ { value: "RECP", label: translateB4RegisterKind("RECP", lng) },
+ { value: "RECW", label: translateB4RegisterKind("RECW", lng) },
+ ];
+ } else if (drawingUsage === "SUB") {
+ return [
+ { value: "SUBP", label: translateB4RegisterKind("SUBP", lng) },
+ { value: "SUBW", label: translateB4RegisterKind("SUBW", lng) },
+ ];
+ }
+ return [];
+}
+
diff --git a/lib/dolce/utils/date-formatter.ts b/lib/dolce/utils/date-formatter.ts
new file mode 100644
index 00000000..83e78b0d
--- /dev/null
+++ b/lib/dolce/utils/date-formatter.ts
@@ -0,0 +1,54 @@
+/**
+ * DOLCE 날짜 포맷팅 유틸리티
+ *
+ * SWP의 날짜 포맷팅 함수를 재사용
+ * 모든 날짜는 KST (Korea Standard Time, GMT+9) 타임존
+ */
+
+import { formatSwpDate } from "@/lib/swp/utils";
+
+/**
+ * SWP와 동일한 방식
+ */
+export function formatDolceDateTime(dateStr: string | null): string {
+ if (!dateStr) return "-";
+ return formatSwpDate(dateStr);
+}
+
+/**
+ * YYYYMMDD 형식을 YYYY-MM-DD로 변환
+ *
+ * @param dateStr "20170220" 형식
+ * @returns "2017-02-20"
+ */
+export function formatDolceDateYYYYMMDD(dateStr: string | null): string | null {
+ if (!dateStr || dateStr.length !== 8) return null;
+
+ try {
+ const year = dateStr.substring(0, 4);
+ const month = dateStr.substring(4, 6);
+ const day = dateStr.substring(6, 8);
+
+ return `${year}-${month}-${day}`;
+ } catch {
+ return dateStr;
+ }
+}
+
+/**
+ * 통합 날짜 포맷팅
+ *
+ * @param dateStr 날짜 문자열 (다양한 형식 지원)
+ * @returns 포맷팅된 날짜 문자열
+ */
+export function formatDolceDate(dateStr: string | null): string {
+ if (!dateStr) return "-";
+
+ // YYYYMMDD 형식 (8자리 숫자)
+ if (/^\d{8}$/.test(dateStr)) {
+ return formatDolceDateYYYYMMDD(dateStr) || dateStr;
+ }
+
+ // 날짜+시간 형식
+ return formatDolceDateTime(dateStr);
+}
--
cgit v1.2.3