summaryrefslogtreecommitdiff
path: root/lib/basic-contract/vendor-table/basic-contract-columns.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/basic-contract/vendor-table/basic-contract-columns.tsx')
-rw-r--r--lib/basic-contract/vendor-table/basic-contract-columns.tsx96
1 files changed, 78 insertions, 18 deletions
diff --git a/lib/basic-contract/vendor-table/basic-contract-columns.tsx b/lib/basic-contract/vendor-table/basic-contract-columns.tsx
index c9e8da53..1b11285c 100644
--- a/lib/basic-contract/vendor-table/basic-contract-columns.tsx
+++ b/lib/basic-contract/vendor-table/basic-contract-columns.tsx
@@ -32,14 +32,65 @@ import { BasicContractView } from "@/db/schema"
interface GetColumnsProps {
setRowAction: React.Dispatch<React.SetStateAction<DataTableRowAction<BasicContractView> | null>>
+ locale?: string
+ t: (key: string) => string // 번역 함수
}
+// 기본 번역값들 (fallback)
+const fallbackTranslations = {
+ ko: {
+ download: "다운로드",
+ selectAll: "전체 선택",
+ selectRow: "행 선택",
+ fileInfoMissing: "파일 정보가 없습니다.",
+ fileDownloadError: "파일 다운로드 중 오류가 발생했습니다.",
+ statusValues: {
+ PENDING: "서명대기",
+ COMPLETED: "서명완료"
+ }
+ },
+ en: {
+ download: "Download",
+ selectAll: "Select all",
+ selectRow: "Select row",
+ fileInfoMissing: "File information is missing.",
+ fileDownloadError: "An error occurred while downloading the file.",
+ statusValues: {
+ PENDING: "Pending",
+ COMPLETED: "Completed"
+ }
+ }
+};
+
+// 안전한 번역 함수
+const safeTranslate = (t: (key: string) => string, key: string, locale: string = 'ko', fallback?: string): string => {
+ try {
+ const translated = t(key);
+ // 번역 키가 그대로 반환되는 경우 (번역 실패) fallback 사용
+ if (translated === key && fallback) {
+ return fallback;
+ }
+ return translated || fallback || key;
+ } catch (error) {
+ console.warn(`Translation failed for key: ${key}`, error);
+ return fallback || key;
+ }
+};
+
/**
* 파일 다운로드 함수
*/
-const handleFileDownload = async (filePath: string | null, fileName: string | null) => {
+const handleFileDownload = async (
+ filePath: string | null,
+ fileName: string | null,
+ t: (key: string) => string,
+ locale: string = 'ko'
+) => {
+ const fallback = fallbackTranslations[locale as keyof typeof fallbackTranslations] || fallbackTranslations.ko;
+
if (!filePath || !fileName) {
- toast.error("파일 정보가 없습니다.");
+ const message = safeTranslate(t, "basicContracts.fileInfoMissing", locale, fallback.fileInfoMissing);
+ toast.error(message);
return;
}
@@ -57,14 +108,17 @@ const handleFileDownload = async (filePath: string | null, fileName: string | nu
}
} catch (error) {
console.error("파일 다운로드 오류:", error);
- toast.error("파일 다운로드 중 오류가 발생했습니다.");
+ const message = safeTranslate(t, "basicContracts.fileDownloadError", locale, fallback.fileDownloadError);
+ toast.error(message);
}
};
/**
* tanstack table 컬럼 정의 (중첩 헤더 버전)
*/
-export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicContractView>[] {
+export function getColumns({ setRowAction, locale = 'ko', t }: GetColumnsProps): ColumnDef<BasicContractView>[] {
+ const fallback = fallbackTranslations[locale as keyof typeof fallbackTranslations] || fallbackTranslations.ko;
+
// ----------------------------------------------------------------
// 1) select 컬럼 (체크박스)
// ----------------------------------------------------------------
@@ -77,7 +131,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
- aria-label="Select all"
+ aria-label={safeTranslate(t, "basicContracts.selectAll", locale, fallback.selectAll)}
className="translate-y-0.5"
/>
),
@@ -85,7 +139,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
- aria-label="Select row"
+ aria-label={safeTranslate(t, "basicContracts.selectRow", locale, fallback.selectRow)}
className="translate-y-0.5"
/>
),
@@ -105,18 +159,19 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
// PENDING 상태일 때는 원본 PDF 파일 (signedFilePath), COMPLETED일 때는 서명된 파일 (signedFilePath)
const filePath = contract.signedFilePath;
const fileName = contract.signedFileName;
+ const downloadText = safeTranslate(t, "basicContracts.download", locale, fallback.download);
return (
<Button
variant="ghost"
size="icon"
- onClick={() => handleFileDownload(filePath, fileName)}
- title={`${fileName} 다운로드`}
+ onClick={() => handleFileDownload(filePath, fileName, t, locale)}
+ title={`${fileName} ${downloadText}`}
className="hover:bg-muted"
disabled={!filePath || !fileName}
>
<Paperclip className="h-4 w-4" />
- <span className="sr-only">다운로드</span>
+ <span className="sr-only">{downloadText}</span>
</Button>
);
},
@@ -124,7 +179,6 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
enableSorting: false,
}
-
// ----------------------------------------------------------------
// 4) 일반 컬럼들을 "그룹"별로 묶어 중첩 columns 생성
// ----------------------------------------------------------------
@@ -152,22 +206,28 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
type: cfg.type,
},
cell: ({ row, cell }) => {
- // 날짜 형식 처리
+ // 날짜 형식 처리 - 로케일 적용
if (cfg.id === "createdAt" || cfg.id === "updatedAt" || cfg.id === "completedAt") {
const dateVal = cell.getValue() as Date
- return formatDateTime(dateVal)
+ return formatDateTime(dateVal, locale)
}
- // Status 컬럼에 Badge 적용
+ // Status 컬럼에 Badge 적용 - 다국어 적용
if (cfg.id === "status") {
const status = row.getValue(cfg.id) as string
const isPending = status === "PENDING"
+ const statusText = safeTranslate(
+ t,
+ `basicContracts.statusValues.${status}`,
+ locale,
+ fallback.statusValues[status as keyof typeof fallback.statusValues] || status
+ );
return (
<Badge
variant={!isPending ? "default" : "secondary"}
>
- {status}
+ {statusText}
</Badge>
)
}
@@ -175,8 +235,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
// 나머지 컬럼은 그대로 값 표시
return row.getValue(cfg.id) ?? ""
},
- minSize: 80,
-
+ minSize: 80,
}
groupMap[groupName].push(childCol)
@@ -194,10 +253,11 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef<BasicCo
// 그룹 없음 → 그냥 최상위 레벨 컬럼
nestedColumns.push(...colDefs)
} else {
- // 상위 컬럼
+ // 상위 컬럼 - 그룹명 다국어 적용
+ const translatedGroupName = t(`basicContracts.groups.${groupName}`) || groupName;
nestedColumns.push({
id: groupName,
- header: groupName, // "Basic Info", "Metadata" 등
+ header: translatedGroupName,
columns: colDefs,
})
}