From 786576bb76d76e339b1ac23479ae090dbff76b4b Mon Sep 17 00:00:00 2001
From: kjs
Date: Thu, 6 Nov 2025 14:46:15 +0900
Subject: [PATCH] =?UTF-8?q?=EC=BB=A4=EB=B0=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/components/admin/MenuManagement.tsx | 6 +-
frontend/components/admin/MenuTable.tsx | 5 +-
.../table-category/CategoryValueManager.tsx | 188 +++++++++++-------
frontend/lib/utils/multilang.ts | 53 ++++-
4 files changed, 172 insertions(+), 80 deletions(-)
diff --git a/frontend/components/admin/MenuManagement.tsx b/frontend/components/admin/MenuManagement.tsx
index 0dc30248..6671504e 100644
--- a/frontend/components/admin/MenuManagement.tsx
+++ b/frontend/components/admin/MenuManagement.tsx
@@ -22,7 +22,7 @@ import {
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { useMenu } from "@/contexts/MenuContext";
-import { useMenuManagementText, setTranslationCache } from "@/lib/utils/multilang";
+import { useMenuManagementText, setTranslationCache, getMenuTextSync } from "@/lib/utils/multilang";
import { useMultiLang } from "@/hooks/useMultiLang";
import { apiClient } from "@/lib/api/client";
@@ -545,9 +545,9 @@ export const MenuManagement: React.FC = () => {
// uiTexts에서 번역 텍스트 찾기
let text = uiTexts[key];
- // uiTexts에 없으면 fallback 또는 키 사용
+ // uiTexts에 없으면 getMenuTextSync로 기본 한글 텍스트 가져오기
if (!text) {
- text = fallback || key;
+ text = getMenuTextSync(key, userLang) || fallback || key;
}
// 파라미터 치환
diff --git a/frontend/components/admin/MenuTable.tsx b/frontend/components/admin/MenuTable.tsx
index eb790e93..55269e97 100644
--- a/frontend/components/admin/MenuTable.tsx
+++ b/frontend/components/admin/MenuTable.tsx
@@ -7,7 +7,7 @@ import { Badge } from "@/components/ui/badge";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { toast } from "sonner";
-import { MENU_MANAGEMENT_KEYS } from "@/lib/utils/multilang";
+import { MENU_MANAGEMENT_KEYS, getMenuTextSync } from "@/lib/utils/multilang";
interface MenuTableProps {
menus: MenuItem[];
@@ -39,7 +39,8 @@ export const MenuTable: React.FC = ({
}) => {
// 다국어 텍스트 가져오기 함수
const getText = (key: string, fallback?: string): string => {
- return uiTexts[key] || fallback || key;
+ // uiTexts에서 먼저 찾고, 없으면 기본 한글 텍스트를 가져옴
+ return uiTexts[key] || getMenuTextSync(key, "KR") || fallback || key;
};
// 다국어 텍스트 표시 함수 (기본값 처리)
diff --git a/frontend/components/table-category/CategoryValueManager.tsx b/frontend/components/table-category/CategoryValueManager.tsx
index b03b809d..0b7eecc3 100644
--- a/frontend/components/table-category/CategoryValueManager.tsx
+++ b/frontend/components/table-category/CategoryValueManager.tsx
@@ -49,25 +49,33 @@ export const CategoryValueManager: React.FC = ({
const [editingValue, setEditingValue] = useState(
null
);
+ const [showInactive, setShowInactive] = useState(false); // 비활성 항목 표시 옵션 (기본: 숨김)
// 카테고리 값 로드
useEffect(() => {
loadCategoryValues();
}, [tableName, columnName]);
- // 검색 필터링
+ // 검색 필터링 + 비활성 필터링
useEffect(() => {
+ let filtered = values;
+
+ // 비활성 항목 필터링 (기본: 활성만 표시, 체크하면 비활성도 표시)
+ if (!showInactive) {
+ filtered = filtered.filter((v) => v.isActive !== false);
+ }
+
+ // 검색어 필터링
if (searchQuery) {
- const filtered = values.filter(
+ filtered = filtered.filter(
(v) =>
v.valueCode.toLowerCase().includes(searchQuery.toLowerCase()) ||
v.valueLabel.toLowerCase().includes(searchQuery.toLowerCase())
);
- setFilteredValues(filtered);
- } else {
- setFilteredValues(values);
}
- }, [searchQuery, values]);
+
+ setFilteredValues(filtered);
+ }, [searchQuery, values, showInactive]);
const loadCategoryValues = async () => {
setIsLoading(true);
@@ -264,10 +272,27 @@ export const CategoryValueManager: React.FC = ({
총 {filteredValues.length}개 항목
-
+
+ {/* 비활성 항목 표시 옵션 */}
+
+ setShowInactive(checked as boolean)}
+ />
+
+
+
+
+
{/* 검색바 */}
@@ -294,73 +319,90 @@ export const CategoryValueManager: React.FC = ({
) : (
- {filteredValues.map((value) => (
-
-
handleSelectValue(value.valueId!)}
- />
-
-
-
- {value.valueCode}
-
-
- {value.valueLabel}
-
- {value.description && (
-
- - {value.description}
-
- )}
- {value.isDefault && (
-
- 기본값
-
- )}
- {value.color && (
-
- )}
-
-
-
-
- handleToggleActive(
- value.valueId!,
- value.isActive !== false
- )
- }
- className="data-[state=checked]:bg-emerald-500"
+ {filteredValues.map((value) => {
+ const isInactive = value.isActive === false;
+
+ return (
+
+
handleSelectValue(value.valueId!)}
/>
-
+
+ {/* 색상 표시 (앞쪽으로 이동) */}
+ {value.color && (
+
+ )}
+
+ {/* 라벨 */}
+
+ {value.valueLabel}
+
+
+ {/* 설명 */}
+ {value.description && (
+
+ - {value.description}
+
+ )}
+
+ {/* 기본값 배지 */}
+ {value.isDefault && (
+
+ 기본값
+
+ )}
+
+ {/* 비활성 배지 */}
+ {isInactive && (
+
+ 비활성
+
+ )}
+
-
+
+
+ handleToggleActive(
+ value.valueId!,
+ value.isActive !== false
+ )
+ }
+ className="data-[state=checked]:bg-emerald-500"
+ />
+
+
+
+
+
-
- ))}
+ );
+ })}
)}
diff --git a/frontend/lib/utils/multilang.ts b/frontend/lib/utils/multilang.ts
index 1f9ef866..2bbb0e6b 100644
--- a/frontend/lib/utils/multilang.ts
+++ b/frontend/lib/utils/multilang.ts
@@ -288,9 +288,19 @@ function getDefaultText(key: string): string {
[MENU_MANAGEMENT_KEYS.USER_MENU]: "사용자 메뉴",
[MENU_MANAGEMENT_KEYS.ADMIN_DESCRIPTION]: "시스템 관리 및 설정 메뉴",
[MENU_MANAGEMENT_KEYS.USER_DESCRIPTION]: "일반 사용자 업무 메뉴",
+ [MENU_MANAGEMENT_KEYS.LIST_TITLE]: "메뉴 목록",
+ [MENU_MANAGEMENT_KEYS.LIST_TOTAL]: "전체",
+ [MENU_MANAGEMENT_KEYS.LIST_SEARCH_RESULT]: "검색 결과",
+ [MENU_MANAGEMENT_KEYS.FILTER_COMPANY]: "회사 필터",
+ [MENU_MANAGEMENT_KEYS.FILTER_COMPANY_ALL]: "전체",
+ [MENU_MANAGEMENT_KEYS.FILTER_COMPANY_COMMON]: "공통",
+ [MENU_MANAGEMENT_KEYS.FILTER_COMPANY_SEARCH]: "회사 검색...",
+ [MENU_MANAGEMENT_KEYS.FILTER_SEARCH]: "검색",
+ [MENU_MANAGEMENT_KEYS.FILTER_SEARCH_PLACEHOLDER]: "메뉴명 검색...",
+ [MENU_MANAGEMENT_KEYS.FILTER_RESET]: "초기화",
[MENU_MANAGEMENT_KEYS.BUTTON_ADD]: "추가",
[MENU_MANAGEMENT_KEYS.BUTTON_ADD_TOP_LEVEL]: "최상위 메뉴 추가",
- [MENU_MANAGEMENT_KEYS.BUTTON_ADD_SUB]: "하위 메뉴 추가",
+ [MENU_MANAGEMENT_KEYS.BUTTON_ADD_SUB]: "하위",
[MENU_MANAGEMENT_KEYS.BUTTON_EDIT]: "수정",
[MENU_MANAGEMENT_KEYS.BUTTON_DELETE]: "삭제",
[MENU_MANAGEMENT_KEYS.BUTTON_DELETE_SELECTED]: "선택 삭제",
@@ -340,9 +350,48 @@ function getDefaultText(key: string): string {
[MENU_MANAGEMENT_KEYS.STATUS_ACTIVE]: "활성화",
[MENU_MANAGEMENT_KEYS.STATUS_INACTIVE]: "비활성화",
[MENU_MANAGEMENT_KEYS.STATUS_UNSPECIFIED]: "미지정",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_LOADING]: "로딩 중...",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_DELETE_PROCESSING]: "메뉴를 삭제하는 중...",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_SAVE_SUCCESS]: "메뉴가 성공적으로 저장되었습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_SAVE_FAILED]: "메뉴 저장에 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_DELETE_SUCCESS]: "메뉴가 성공적으로 삭제되었습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_DELETE_FAILED]: "메뉴 삭제에 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_DELETE_BATCH_SUCCESS]: "{count}개의 메뉴가 성공적으로 삭제되었습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_DELETE_BATCH_PARTIAL]: "{success}개 삭제됨, {failed}개 실패",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_STATUS_TOGGLE_SUCCESS]: "메뉴 상태가 변경되었습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_MENU_STATUS_TOGGLE_FAILED]: "메뉴 상태 변경에 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_MENU_NAME_REQUIRED]: "메뉴명을 입력하세요.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_COMPANY_REQUIRED]: "회사를 선택하세요.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_VALIDATION_SELECT_MENU_DELETE]: "삭제할 메뉴를 선택하세요.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_MENU_LIST]: "메뉴 목록을 불러오는데 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_MENU_INFO]: "메뉴 정보를 불러오는데 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_COMPANY_LIST]: "회사 목록을 불러오는데 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.MESSAGE_ERROR_LOAD_LANG_KEY_LIST]: "다국어 키 목록을 불러오는데 실패했습니다.",
+ [MENU_MANAGEMENT_KEYS.UI_EXPAND]: "펼치기",
+ [MENU_MANAGEMENT_KEYS.UI_COLLAPSE]: "접기",
+ [MENU_MANAGEMENT_KEYS.UI_MENU_COLLAPSE]: "메뉴 접기",
+ [MENU_MANAGEMENT_KEYS.UI_LANGUAGE]: "언어",
+ // 추가 매핑: key 문자열 자체도 한글로 매핑
+ "menu.type.title": "메뉴 타입",
+ "menu.management.admin": "관리자",
+ "menu.management.admin.description": "시스템 관리 및 설정 메뉴",
+ "menu.management.user": "사용자",
+ "menu.management.user.description": "일반 사용자 업무 메뉴",
+ "menu.list.title": "메뉴 목록",
+ "filter.company.all": "전체",
+ "filter.search.placeholder": "메뉴명 검색...",
+ "filter.reset": "초기화",
+ "button.add.top.level": "최상위 메뉴 추가",
+ "button.delete.selected": "선택 삭제",
+ "table.header.menu.name": "메뉴명",
+ "table.header.sequence": "순서",
+ "table.header.company": "회사",
+ "table.header.menu.url": "URL",
+ "table.header.status": "상태",
+ "table.header.actions": "작업",
};
- return defaultTexts[key] || key;
+ return defaultTexts[key] || "";
}
/**