diff --git a/backend-node/src/controllers/multilangController.ts b/backend-node/src/controllers/multilangController.ts index ec5fa949..39aa2eac 100644 --- a/backend-node/src/controllers/multilangController.ts +++ b/backend-node/src/controllers/multilangController.ts @@ -758,7 +758,7 @@ export const getLangText = async ( * 다국어 텍스트 배치 조회 API */ export const getBatchTranslations = async ( - req: AuthenticatedRequest, + req: Request, res: Response ): Promise => { try { @@ -780,7 +780,6 @@ export const getBatchTranslations = async ( menuCode: finalMenuCode, userLang: finalUserLang, keyCount: langKeys?.length || 0, - user: req.user, }); if (!langKeys || !Array.isArray(langKeys) || langKeys.length === 0) { diff --git a/backend-node/src/routes/multilangRoutes.ts b/backend-node/src/routes/multilangRoutes.ts index cf07b5bd..07280d40 100644 --- a/backend-node/src/routes/multilangRoutes.ts +++ b/backend-node/src/routes/multilangRoutes.ts @@ -24,7 +24,10 @@ import { const router = express.Router(); -// 모든 다국어 관리 라우트에 인증 미들웨어 적용 +// 다국어 배치 조회 API는 인증 없이 접근 가능 +router.post("/batch", getBatchTranslations); + +// 나머지 모든 다국어 관리 라우트에 인증 미들웨어 적용 router.use(authenticateToken); // 언어 관리 API @@ -45,6 +48,5 @@ router.put("/keys/:keyId/toggle", toggleLangKey); // 다국어 키 상태 토글 router.post("/keys/:keyId/texts", saveLangTexts); // 다국어 텍스트 저장/수정 router.get("/user-text/:companyCode/:menuCode/:langKey", getUserText); // 사용자별 다국어 텍스트 조회 router.get("/text/:companyCode/:langKey/:langCode", getLangText); // 특정 키의 다국어 텍스트 조회 -router.post("/batch", getBatchTranslations); // 다국어 텍스트 배치 조회 export default router; diff --git a/docs/다국어_시스템_가이드.md b/docs/다국어_시스템_가이드.md index e83096a9..3f5c63fe 100644 --- a/docs/다국어_시스템_가이드.md +++ b/docs/다국어_시스템_가이드.md @@ -21,7 +21,7 @@ ### 지원 언어 - **한국어 (KR)**: 기본 언어 -- **영어 (EN)**: 사용자 설정 가능 +- **영어 (US)**: 사용자 설정 가능 ### 주요 특징 @@ -72,7 +72,7 @@ ```sql CREATE TABLE public.language_master ( - lang_code varchar(10) NOT NULL PRIMARY KEY, -- 언어 코드 (KR, EN) + lang_code varchar(10) NOT NULL PRIMARY KEY, -- 언어 코드 (KR, US) lang_name varchar(50) NOT NULL, -- 언어명 (Korean, English) lang_native varchar(50) NOT NULL, -- 원어명 (한국어, English) is_active bpchar(1) DEFAULT 'Y', -- 활성화 여부 @@ -93,7 +93,7 @@ CREATE TABLE public.multi_lang_key_master ( lang_key varchar(100) NOT NULL, -- 다국어 키 (예: button.add) description text, -- 키 설명 is_active bpchar(1) DEFAULT 'Y', -- 활성화 여부 - menu_name varchar(50), -- 메뉴명 (사용하지 않음) + menu_name varchar(50), -- 메뉴명 (다국어 관리 화면에 어디에서 쓰이는지 보여지는 용도. 한국어로 어느 메뉴에 쓰이는지 작성) created_date timestamp DEFAULT CURRENT_TIMESTAMP, created_by varchar(50), updated_date timestamp DEFAULT CURRENT_TIMESTAMP, @@ -108,7 +108,7 @@ CREATE TABLE public.multi_lang_key_master ( CREATE TABLE public.multi_lang_text ( text_id serial4 NOT NULL PRIMARY KEY, -- 텍스트 ID (자동 증가) key_id int4 NOT NULL, -- 키 마스터의 key_id - lang_code varchar(10) NOT NULL, -- 언어 코드 (KR, EN) + lang_code varchar(10) NOT NULL, -- 언어 코드 (KR, US) lang_text text NOT NULL, -- 번역된 텍스트 is_active bpchar(1) DEFAULT 'Y', -- 활성화 여부 created_date timestamp DEFAULT CURRENT_TIMESTAMP, @@ -155,7 +155,7 @@ CREATE TABLE public.multi_lang_text ( ```sql INSERT INTO language_master (lang_code, lang_name, lang_native) VALUES ('KR', 'Korean', '한국어'), -('EN', 'English', 'English'); +('US', 'English', 'English'); ``` #### 2. 다국어 키 등록 @@ -184,7 +184,7 @@ WHERE km.lang_key IN ('button.add', 'button.edit', 'menu.title') -- 영어 번역 INSERT INTO multi_lang_text (key_id, lang_code, lang_text) -SELECT km.key_id, 'EN', +SELECT km.key_id, 'US', CASE km.lang_key WHEN 'button.add' THEN 'Add' WHEN 'button.edit' THEN 'Edit' @@ -209,7 +209,7 @@ export const useMultiLang = (options: { companyCode?: string } = {}) => { // 언어 변경 처리 return { - userLang, // 현재 사용자 언어 (KR, EN) + userLang, // 현재 사용자 언어 (KR, US) getText, // 다국어 텍스트 조회 함수 changeLang, // 언어 변경 함수 companyCode, // 회사 코드 @@ -229,7 +229,7 @@ export const useMultiLang = (options: { companyCode?: string } = {}) => { const { userLang, getText, changeLang } = useMultiLang({ companyCode: "*" }); // 언어 변경 -await changeLang("EN"); +await changeLang("US"); // 다국어 텍스트 조회 const text = await getText("menu.management", "button.add"); @@ -519,7 +519,7 @@ INSERT INTO multi_lang_text ( ) SELECT km.key_id, - 'EN', + 'US', CASE km.lang_key WHEN 'page.title' THEN 'My Page' WHEN 'page.description' THEN 'This is my page' @@ -622,7 +622,7 @@ INSERT INTO multi_lang_text ( ) SELECT km.key_id, - 'EN', + 'US', CASE km.lang_key WHEN 'menu.management.title' THEN 'Menu Management' WHEN 'button.add' THEN 'Add' @@ -727,7 +727,7 @@ INSERT INTO multi_lang_text ( ) SELECT km.key_id, - 'EN', + 'US', CASE km.lang_key WHEN 'new.feature.title' THEN 'New Feature' WHEN 'new.feature.description' THEN 'This is a new feature' diff --git a/frontend/app/(main)/admin/tableMng/page.tsx b/frontend/app/(main)/admin/tableMng/page.tsx index 369a3b71..36ddaba5 100644 --- a/frontend/app/(main)/admin/tableMng/page.tsx +++ b/frontend/app/(main)/admin/tableMng/page.tsx @@ -10,6 +10,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Search, Database, RefreshCw, Settings, Menu, X } from "lucide-react"; import { LoadingSpinner } from "@/components/common/LoadingSpinner"; import { toast } from "sonner"; +import { useMultiLang } from "@/hooks/useMultiLang"; +import { TABLE_MANAGEMENT_KEYS, WEB_TYPE_OPTIONS_WITH_KEYS } from "@/constants/tableManagement"; +import { apiClient } from "@/lib/api/client"; interface TableInfo { tableName: string; @@ -37,6 +40,7 @@ interface ColumnTypeInfo { } export default function TableManagementPage() { + const { userLang, getText } = useMultiLang({ companyCode: "*" }); const [tables, setTables] = useState([]); const [columns, setColumns] = useState([]); const [selectedTable, setSelectedTable] = useState(null); @@ -44,25 +48,60 @@ export default function TableManagementPage() { const [loading, setLoading] = useState(false); const [columnsLoading, setColumnsLoading] = useState(false); const [originalColumns, setOriginalColumns] = useState([]); // 원본 데이터 저장 + const [uiTexts, setUiTexts] = useState>({}); - // 웹 타입 옵션 - const webTypeOptions = [ - { value: "text", label: "text", description: "일반 텍스트 입력" }, - { value: "number", label: "number", description: "숫자 입력" }, - { value: "date", label: "date", description: "날짜 선택기" }, - { value: "code", label: "code", description: "코드 선택 (공통코드 지정)" }, - { value: "entity", label: "entity", description: "엔티티 참조 (참조테이블 지정)" }, - ]; + // 다국어 텍스트 로드 + useEffect(() => { + const loadTexts = async () => { + if (!userLang) return; + + try { + const response = await apiClient.post( + "/multilang/batch", + { + langKeys: Object.values(TABLE_MANAGEMENT_KEYS), + }, + { + params: { + companyCode: "*", + menuCode: "TABLE_MANAGEMENT", + userLang: userLang, + }, + }, + ); + + if (response.data.success) { + setUiTexts(response.data.data); + } + } catch (error) { + console.error("다국어 텍스트 로드 실패:", error); + } + }; + + loadTexts(); + }, [userLang]); + + // 텍스트 가져오기 함수 + const getTextFromUI = (key: string, fallback?: string) => { + return uiTexts[key] || fallback || key; + }; + + // 웹 타입 옵션 (다국어 적용) + const webTypeOptions = WEB_TYPE_OPTIONS_WITH_KEYS.map((option) => ({ + value: option.value, + label: getTextFromUI(option.labelKey, option.value), + description: getTextFromUI(option.descriptionKey, option.value), + })); // 참조 테이블 옵션 (실제 테이블 목록에서 가져옴) const referenceTableOptions = [ - { value: "none", label: "테이블 선택" }, + { value: "none", label: getTextFromUI(TABLE_MANAGEMENT_KEYS.LABEL_NONE, "선택 안함") }, ...tables.map((table) => ({ value: table.tableName, label: table.displayName || table.tableName })), ]; // 공통 코드 옵션 (예시 - 실제로는 API에서 가져와야 함) const commonCodeOptions = [ - { value: "none", label: "코드 선택" }, + { value: "none", label: getTextFromUI(TABLE_MANAGEMENT_KEYS.SELECT_CODE_PLACEHOLDER, "코드 선택") }, { value: "USER_STATUS", label: "사용자 상태" }, { value: "DEPT_TYPE", label: "부서 유형" }, { value: "PRODUCT_CATEGORY", label: "제품 카테고리" }, @@ -72,32 +111,14 @@ export default function TableManagementPage() { const loadTables = async () => { setLoading(true); try { - const response = await fetch("http://localhost:8080/api/table-management/tables"); + const response = await apiClient.get("/table-management/tables"); // 응답 상태 확인 - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - // 응답 텍스트를 먼저 확인 - const responseText = await response.text(); - console.log("Raw response:", responseText); - - // JSON 파싱 시도 - let result; - try { - result = JSON.parse(responseText); - } catch (parseError) { - console.error("JSON 파싱 오류:", parseError); - console.error("응답 텍스트:", responseText); - throw new Error("JSON 파싱에 실패했습니다."); - } - - if (result.success) { - setTables(result.data); + if (response.data.success) { + setTables(response.data.data); toast.success("테이블 목록을 성공적으로 로드했습니다."); } else { - toast.error(result.message || "테이블 목록 로드에 실패했습니다."); + toast.error(response.data.message || "테이블 목록 로드에 실패했습니다."); } } catch (error) { console.error("테이블 목록 로드 실패:", error); @@ -111,33 +132,15 @@ export default function TableManagementPage() { const loadColumnTypes = async (tableName: string) => { setColumnsLoading(true); try { - const response = await fetch(`http://localhost:8080/api/table-management/tables/${tableName}/columns`); + const response = await apiClient.get(`/table-management/tables/${tableName}/columns`); // 응답 상태 확인 - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - // 응답 텍스트를 먼저 확인 - const responseText = await response.text(); - console.log("Raw column response:", responseText); - - // JSON 파싱 시도 - let result; - try { - result = JSON.parse(responseText); - } catch (parseError) { - console.error("JSON 파싱 오류:", parseError); - console.error("응답 텍스트:", responseText); - throw new Error("JSON 파싱에 실패했습니다."); - } - - if (result.success) { - setColumns(result.data); - setOriginalColumns(result.data); // 원본 데이터 저장 + if (response.data.success) { + setColumns(response.data.data); + setOriginalColumns(response.data.data); // 원본 데이터 저장 toast.success("컬럼 정보를 성공적으로 로드했습니다."); } else { - toast.error(result.message || "컬럼 정보 로드에 실패했습니다."); + toast.error(response.data.message || "컬럼 정보 로드에 실패했습니다."); } } catch (error) { console.error("컬럼 타입 정보 로드 실패:", error); @@ -234,6 +237,54 @@ export default function TableManagementPage() { ); }; + // 컬럼 변경 핸들러 (인덱스 기반) + const handleColumnChange = (index: number, field: keyof ColumnTypeInfo, value: any) => { + setColumns((prev) => + prev.map((col, i) => { + if (i === index) { + return { + ...col, + [field]: value, + }; + } + return col; + }), + ); + }; + + // 개별 컬럼 저장 + const handleSaveColumn = async (column: ColumnTypeInfo) => { + if (!selectedTable) return; + + try { + const columnSetting = { + columnName: column.columnName, + columnLabel: column.displayName, + webType: column.webType, + detailSettings: column.detailSettings, + codeCategory: column.codeCategory, + codeValue: column.codeValue, + referenceTable: column.referenceTable, + referenceColumn: column.referenceColumn, + }; + + const response = await apiClient.post(`/table-management/tables/${selectedTable}/columns/settings`, [ + columnSetting, + ]); + + if (response.data.success) { + toast.success("컬럼 설정이 성공적으로 저장되었습니다."); + // 원본 데이터 업데이트 + setOriginalColumns((prev) => prev.map((col) => (col.columnName === column.columnName ? column : col))); + } else { + toast.error(response.data.message || "컬럼 설정 저장에 실패했습니다."); + } + } catch (error) { + console.error("컬럼 설정 저장 실패:", error); + toast.error("컬럼 설정 저장 중 오류가 발생했습니다."); + } + }; + // 모든 컬럼 설정 저장 const saveAllColumnSettings = async () => { if (!selectedTable || columns.length === 0) return; @@ -252,29 +303,18 @@ export default function TableManagementPage() { })); // 전체 테이블 설정을 한 번에 저장 - const response = await fetch( - `http://localhost:8080/api/table-management/tables/${selectedTable}/columns/settings`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(columnSettings), - }, + const response = await apiClient.post( + `/table-management/tables/${selectedTable}/columns/settings`, + columnSettings, ); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + if (response.data.success) { + // 저장 성공 후 원본 데이터 업데이트 + setOriginalColumns([...columns]); + toast.success(`${columns.length}개의 컬럼 설정이 성공적으로 저장되었습니다.`); + } else { + toast.error(response.data.message || "컬럼 설정 저장에 실패했습니다."); } - - const result = await response.json(); - if (!result.success) { - throw new Error(result.message || "컬럼 설정 저장에 실패했습니다."); - } - - // 저장 성공 후 원본 데이터 업데이트 - setOriginalColumns([...columns]); - toast.success(`${columns.length}개의 컬럼 설정이 성공적으로 저장되었습니다.`); } catch (error) { console.error("컬럼 설정 저장 실패:", error); toast.error("컬럼 설정 저장 중 오류가 발생했습니다."); @@ -296,173 +336,226 @@ export default function TableManagementPage() { }, []); return ( -
- {/* 헤더 영역 */} -
+
+ {/* 페이지 제목 */} +
-

데이터베이스 테이블 목록

-

데이터베이스 테이블과 컬럼 타입을 관리합니다.

-
-
- +

+ {getTextFromUI(TABLE_MANAGEMENT_KEYS.PAGE_TITLE, "테이블 타입 관리")} +

+

+ {getTextFromUI(TABLE_MANAGEMENT_KEYS.PAGE_DESCRIPTION, "데이터베이스 테이블과 컬럼의 타입을 관리합니다")} +

+
- {/* 검색 필터 */} -
- - setSearchTerm(e.target.value)} - className="pl-10" - /> -
+
+ {/* 테이블 목록 */} + + + + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.TABLE_NAME, "테이블 목록")} + + + + {/* 검색 */} +
+
+ + setSearchTerm(e.target.value)} + className="pl-10" + /> +
+
- {/* 메인 컨텐츠 영역 */} -
- {/* 좌측: 테이블 목록 */} -
- - - - - 데이터베이스 테이블 목록 - 테이블 목록 - - - + {/* 테이블 목록 */} +
{loading ? ( -
+
+ + {getTextFromUI(TABLE_MANAGEMENT_KEYS.MESSAGE_LOADING_TABLES, "테이블 로딩 중...")} + +
+ ) : tables.length === 0 ? ( +
+ {getTextFromUI(TABLE_MANAGEMENT_KEYS.MESSAGE_NO_TABLES, "테이블이 없습니다")}
) : ( -
- {filteredTables.length === 0 ? ( -
- {searchTerm ? "검색 결과가 없습니다." : "테이블이 없습니다."} -
- ) : ( - filteredTables.map((table) => ( -
handleTableSelect(table.tableName)} - className={`cursor-pointer rounded-lg border p-3 transition-colors ${ - selectedTable === table.tableName - ? "bg-primary/10 border-primary" - : "hover:bg-muted/50 border-border" - }`} - > -
-
-

{table.displayName}

-

{table.tableName}

-

{table.description}

-
- - {table.columnCount}개 - + tables + .filter( + (table) => + table.tableName.toLowerCase().includes(searchTerm.toLowerCase()) || + (table.displayName && table.displayName.toLowerCase().includes(searchTerm.toLowerCase())), + ) + .map((table) => ( +
handleTableSelect(table.tableName)} + > +
+
+

{table.displayName || table.tableName}

+

+ {table.description || getTextFromUI(TABLE_MANAGEMENT_KEYS.TABLE_DESCRIPTION, "설명 없음")} +

+ + {table.columnCount} {getTextFromUI(TABLE_MANAGEMENT_KEYS.TABLE_COLUMN_COUNT, "컬럼")} +
- )) - )} -
+
+ )) )} - - -
+
+ + - {/* 우측: 컬럼 타입 설정 */} -
- - - - {selectedTable ? ( -
- 컬럼 타입 설정 - - {selectedTableInfo?.displayName} - - ({selectedTableInfo?.tableName}) + {/* 컬럼 타입 관리 */} + + + + + {selectedTable ? ( + <> + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_NAME, "컬럼")} - {selectedTable} + + ) : ( + getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_NAME, "컬럼 타입 관리") + )} + + + + {!selectedTable ? ( +
+ {getTextFromUI(TABLE_MANAGEMENT_KEYS.SELECT_TABLE_PLACEHOLDER, "테이블을 선택해주세요")} +
+ ) : ( + <> + {columnsLoading ? ( +
+ + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.MESSAGE_LOADING_COLUMNS, "컬럼 정보 로딩 중...")}
+ ) : columns.length === 0 ? ( +
+ {getTextFromUI(TABLE_MANAGEMENT_KEYS.MESSAGE_NO_COLUMNS, "컬럼이 없습니다")} +
) : ( - "컬럼 타입 설정" - )} - - {selectedTable && ( -
-

{selectedTableInfo?.description}

- -
- )} - - - {!selectedTable ? ( -
- 좌측에서 테이블을 선택하세요 -
- ) : columnsLoading ? ( -
- -
- ) : ( -
- {/* 모바일: 카드 형태 */} -
- {columns.map((column) => ( -
-
-

{column.columnName}

- - {column.dbType} - -
- -
-
- - handleLabelChange(column.columnName, e.target.value)} - placeholder="라벨 입력" - className="text-sm" - /> -
- -
- - -
- - {column.webType === "code" && ( -
- +
+ + + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_NAME, "컬럼명")} + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_DISPLAY_NAME, "표시명")} + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_DB_TYPE, "DB 타입")} + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_WEB_TYPE, "웹 타입")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_DETAIL_SETTINGS, "상세 설정")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_DESCRIPTION, "설명")} + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_NULLABLE, "NULL 허용")} + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_DEFAULT_VALUE, "기본값")} + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_MAX_LENGTH, "최대 길이")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_NUMERIC_PRECISION, "정밀도")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_NUMERIC_SCALE, "소수점")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_CODE_CATEGORY, "코드 카테고리")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_CODE_VALUE, "코드 값")} + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_REFERENCE_TABLE, "참조 테이블")} + + + {getTextFromUI(TABLE_MANAGEMENT_KEYS.COLUMN_REFERENCE_COLUMN, "참조 컬럼")} + + Actions + + + + {columns.map((column, index) => ( + + {column.columnName} + + handleColumnChange(index, "displayName", e.target.value)} + placeholder={column.columnName} + className="w-32" + /> + + {column.dbType} + + + + + handleColumnChange(index, "detailSettings", e.target.value)} + placeholder="상세 설정" + className="w-32" + /> + + + handleColumnChange(index, "description", e.target.value)} + placeholder="설명" + className="w-32" + /> + + + + {column.isNullable === "YES" + ? getTextFromUI(TABLE_MANAGEMENT_KEYS.LABEL_YES, "예") + : getTextFromUI(TABLE_MANAGEMENT_KEYS.LABEL_NO, "아니오")} + + + {column.defaultValue || "-"} + {column.maxLength || "-"} + {column.numericPrecision || "-"} + {column.numericScale || "-"} + - - )} - - {column.webType === "entity" && ( -
- + + + handleColumnChange(index, "codeValue", e.target.value)} + placeholder="코드 값" + className="w-32" + /> + + -
- )} - - - ))} - - - {/* 태블릿/PC: 테이블 형태 */} -
-
- - - 컬럼명 - 라벨 - DB 타입 - 웹 타입 - 상세 설정 - - - - {columns.length === 0 ? ( - - - 컬럼 정보가 없습니다. + + + handleColumnChange(index, "referenceColumn", e.target.value)} + placeholder="참조 컬럼" + className="w-32" + /> + + + - ) : ( - columns.map((column) => ( - - {column.columnName} - - handleLabelChange(column.columnName, e.target.value)} - placeholder="라벨 입력" - className="w-24 text-xs md:w-32 md:text-sm" - /> - - - - {column.dbType} - - - - - - - {column.webType === "code" ? ( - - ) : column.webType === "entity" ? ( - - ) : ( - {column.detailSettings} - )} - - - )) - )} + ))}
-
- )} - - -
+ )} + + )} + +
); diff --git a/frontend/constants/tableManagement.ts b/frontend/constants/tableManagement.ts new file mode 100644 index 00000000..745b051d --- /dev/null +++ b/frontend/constants/tableManagement.ts @@ -0,0 +1,103 @@ +// 테이블 타입 관리 다국어 키 상수 +export const TABLE_MANAGEMENT_KEYS = { + // 페이지 제목 및 설명 + PAGE_TITLE: "table.management.page.title", + PAGE_DESCRIPTION: "table.management.page.description", + + // 테이블 관련 + TABLE_NAME: "table.management.table.name", + TABLE_DISPLAY_NAME: "table.management.table.display.name", + TABLE_DESCRIPTION: "table.management.table.description", + TABLE_COLUMN_COUNT: "table.management.table.column.count", + + // 컬럼 관련 + COLUMN_NAME: "table.management.column.name", + COLUMN_DISPLAY_NAME: "table.management.column.display.name", + COLUMN_DB_TYPE: "table.management.column.db.type", + COLUMN_WEB_TYPE: "table.management.column.web.type", + COLUMN_DETAIL_SETTINGS: "table.management.column.detail.settings", + COLUMN_DESCRIPTION: "table.management.column.description", + COLUMN_NULLABLE: "table.management.column.nullable", + COLUMN_DEFAULT_VALUE: "table.management.column.default.value", + COLUMN_MAX_LENGTH: "table.management.column.max.length", + COLUMN_NUMERIC_PRECISION: "table.management.column.numeric.precision", + COLUMN_NUMERIC_SCALE: "table.management.column.numeric.scale", + COLUMN_CODE_CATEGORY: "table.management.column.code.category", + COLUMN_CODE_VALUE: "table.management.column.code.value", + COLUMN_REFERENCE_TABLE: "table.management.column.reference.table", + COLUMN_REFERENCE_COLUMN: "table.management.column.reference.column", + + // 웹 타입 옵션 + WEB_TYPE_TEXT: "table.management.web.type.text", + WEB_TYPE_TEXT_DESC: "table.management.web.type.text.description", + WEB_TYPE_NUMBER: "table.management.web.type.number", + WEB_TYPE_NUMBER_DESC: "table.management.web.type.number.description", + WEB_TYPE_DATE: "table.management.web.type.date", + WEB_TYPE_DATE_DESC: "table.management.web.type.date.description", + WEB_TYPE_CODE: "table.management.web.type.code", + WEB_TYPE_CODE_DESC: "table.management.web.type.code.description", + WEB_TYPE_ENTITY: "table.management.web.type.entity", + WEB_TYPE_ENTITY_DESC: "table.management.web.type.entity.description", + + // 공통 UI 요소 + BUTTON_REFRESH: "table.management.button.refresh", + BUTTON_SAVE: "table.management.button.save", + BUTTON_CANCEL: "table.management.button.cancel", + BUTTON_EDIT: "table.management.button.edit", + + // 검색 및 필터 + SEARCH_PLACEHOLDER: "table.management.search.placeholder", + SELECT_TABLE_PLACEHOLDER: "table.management.select.table.placeholder", + SELECT_CODE_PLACEHOLDER: "table.management.select.code.placeholder", + + // 메시지 + MESSAGE_LOADING_TABLES: "table.management.message.loading.tables", + MESSAGE_LOADING_COLUMNS: "table.management.message.loading.columns", + MESSAGE_TABLES_LOADED: "table.management.message.tables.loaded", + MESSAGE_COLUMNS_LOADED: "table.management.message.columns.loaded", + MESSAGE_SAVE_SUCCESS: "table.management.message.save.success", + MESSAGE_SAVE_ERROR: "table.management.message.save.error", + MESSAGE_NO_TABLES: "table.management.message.no.tables", + MESSAGE_NO_COLUMNS: "table.management.message.no.columns", + + // 상태 및 라벨 + STATUS_ACTIVE: "table.management.status.active", + STATUS_INACTIVE: "table.management.status.inactive", + LABEL_YES: "table.management.label.yes", + LABEL_NO: "table.management.label.no", + LABEL_NONE: "table.management.label.none", + + // 도움말 및 설명 + HELP_WEB_TYPE: "table.management.help.web.type", + HELP_CODE_CATEGORY: "table.management.help.code.category", + HELP_REFERENCE_TABLE: "table.management.help.reference.table", +} as const; + +// 웹 타입 옵션을 다국어 키와 매핑 +export const WEB_TYPE_OPTIONS_WITH_KEYS = [ + { + value: "text", + labelKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_TEXT, + descriptionKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_TEXT_DESC, + }, + { + value: "number", + labelKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_NUMBER, + descriptionKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_NUMBER_DESC, + }, + { + value: "date", + labelKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_DATE, + descriptionKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_DATE_DESC, + }, + { + value: "code", + labelKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_CODE, + descriptionKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_CODE_DESC, + }, + { + value: "entity", + labelKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_ENTITY, + descriptionKey: TABLE_MANAGEMENT_KEYS.WEB_TYPE_ENTITY_DESC, + }, +] as const;