From 02b1cf005cf3e1df64183d20ba42930eb2767a9f Mon Sep 17 00:00:00 2001 From: dujinkim Date: Thu, 21 Aug 2025 06:57:36 +0000 Subject: (대표님, 최겸) 설계메뉴추가, 작업사항 업데이트 설계메뉴 - 문서관리 설계메뉴 - 벤더 데이터 gtc 메뉴 업데이트 정보시스템 - 메뉴리스트 및 정보 업데이트 파일 라우트 업데이트 엑셀임포트 개선 기본계약 개선 벤더 가입과정 변경 및 개선 벤더 기본정보 - pq 돌체 오류 수정 및 개선 벤더 로그인 과정 이메일 오류 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendor-table/basic-contract-columns.tsx | 96 ++++++++++++++++++---- 1 file changed, 78 insertions(+), 18 deletions(-) (limited to 'lib/basic-contract/vendor-table/basic-contract-columns.tsx') 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 | 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[] { +export function getColumns({ setRowAction, locale = 'ko', t }: GetColumnsProps): ColumnDef[] { + const fallback = fallbackTranslations[locale as keyof typeof fallbackTranslations] || fallbackTranslations.ko; + // ---------------------------------------------------------------- // 1) select 컬럼 (체크박스) // ---------------------------------------------------------------- @@ -77,7 +131,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef 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 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 handleFileDownload(filePath, fileName)} - title={`${fileName} 다운로드`} + onClick={() => handleFileDownload(filePath, fileName, t, locale)} + title={`${fileName} ${downloadText}`} className="hover:bg-muted" disabled={!filePath || !fileName} > - 다운로드 + {downloadText} ); }, @@ -124,7 +179,6 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef { - // 날짜 형식 처리 + // 날짜 형식 처리 - 로케일 적용 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 ( - {status} + {statusText} ) } @@ -175,8 +235,7 @@ export function getColumns({ setRowAction }: GetColumnsProps): ColumnDef