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] || ""; } /**