"use client"; import React from "react"; import { MenuItem } from "@/lib/api/menu"; import { Button } from "@/components/ui/button"; 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, getMenuTextSync } from "@/lib/utils/multilang"; interface MenuTableProps { menus: MenuItem[]; title: string; onAddMenu: (parentId: string, menuType: string, level: number) => void; onEditMenu: (menuId: string) => void; onToggleStatus: (menuId: string) => void; selectedMenus: Set; onMenuSelectionChange: (menuId: string, checked: boolean) => void; onSelectAllMenus: (checked: boolean) => void; expandedMenus: Set; onToggleExpand: (menuId: string) => void; // 다국어 텍스트 props 추가 uiTexts: Record; } export const MenuTable: React.FC = ({ menus, title, onAddMenu, onEditMenu, onToggleStatus, selectedMenus, onMenuSelectionChange, onSelectAllMenus, expandedMenus, onToggleExpand, uiTexts, }) => { // 다국어 텍스트 가져오기 함수 const getText = (key: string, fallback?: string): string => { // uiTexts에서 먼저 찾고, 없으면 기본 한글 텍스트를 가져옴 return uiTexts[key] || getMenuTextSync(key, "KR") || fallback || key; }; // 다국어 텍스트 표시 함수 (기본값 처리) const getDisplayText = (menu: MenuItem) => { // 다국어 텍스트가 있으면 사용, 없으면 기본 텍스트 사용 if (menu.translated_name || menu.TRANSLATED_NAME) { return menu.translated_name || menu.TRANSLATED_NAME; } return menu.menu_name_kor || menu.MENU_NAME_KOR || "No menu name"; }; const getDisplayDesc = (menu: MenuItem) => { if (menu.translated_desc || menu.TRANSLATED_DESC) { return menu.translated_desc || menu.TRANSLATED_DESC; } return menu.menu_desc || menu.MENU_DESC || ""; }; // 계층 표시 함수 const getTreeIndentation = (level: number) => { return " ".repeat(level); }; // 레벨 배지 함수 const getLevelBadge = (level: number) => { switch (level) { case 0: return "bg-primary/20 text-primary"; case 1: return "bg-success/20 text-success"; case 2: return "bg-warning/20 text-warning"; default: return "bg-muted/50 text-muted-foreground"; } }; // 토글 상태에 따라 메뉴를 필터링하는 함수 const getFilteredMenus = () => { const filtered: MenuItem[] = []; for (let i = 0; i < menus.length; i++) { const menu = menus[i]; const menuId = menu.objid || menu.OBJID; const level = menu.lev || menu.LEV || 1; // 최상위 메뉴는 항상 표시 if (level === 1) { filtered.push(menu); continue; } // 하위 메뉴는 상위 메뉴가 확장되어 있을 때만 표시 let shouldShow = true; let currentLevel: number = level; let currentMenu = menu; // 상위 메뉴들을 확인하여 모두 확장되어 있는지 체크 while (currentLevel > 1) { // 현재 메뉴의 상위 메뉴 찾기 const parentMenu = menus.find( (m) => (m.objid || m.OBJID) === (currentMenu.parent_obj_id || currentMenu.PARENT_OBJ_ID), ); if (!parentMenu) break; const parentId = parentMenu.objid || parentMenu.OBJID; if (!parentId || !expandedMenus.has(parentId)) { shouldShow = false; break; } currentMenu = parentMenu; const nextLevel = currentMenu.lev || currentMenu.LEV; if (nextLevel === undefined) break; currentLevel = nextLevel; } if (shouldShow) { filtered.push(menu); } } return filtered; }; const getStatusBadge = (status: string, menuId: string) => { return ( ); }; return (
{title &&

{title}

}
(menu.lev || menu.LEV || 0) > 1).length && menus.filter((menu) => (menu.lev || menu.LEV || 0) > 1).length > 0 } onChange={(e) => onSelectAllMenus(e.target.checked)} className="h-4 w-4" /> {getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_MENU_NAME)} {getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_SEQUENCE)} {getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_COMPANY)} {getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_MENU_URL)} {getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_STATUS)} {getText(MENU_MANAGEMENT_KEYS.TABLE_HEADER_ACTIONS)} {getFilteredMenus().map((menu) => { const objid = menu.objid || menu.OBJID || ""; const lev = menu.lev || menu.LEV || 0; const menuNameKor = menu.menu_name_kor || menu.MENU_NAME_KOR || "No menu name"; const seq = menu.seq || menu.SEQ || 0; const companyCode = menu.company_code || menu.COMPANY_CODE || ""; const companyName = menu.company_name || menu.COMPANY_NAME || companyCode || getMenuTextSync(MENU_MANAGEMENT_KEYS.STATUS_UNSPECIFIED); const menuUrl = menu.menu_url || menu.MENU_URL || ""; const status = menu.status || menu.STATUS || ""; const menuType = menu.menu_type || menu.MENU_TYPE || ""; const parentObjId = menu.parent_obj_id || menu.PARENT_OBJ_ID || ""; return ( onMenuSelectionChange(objid, e.target.checked)} onClick={(e) => e.stopPropagation()} className="h-4 w-4" />
{getTreeIndentation(lev)} L{lev}
{getDisplayText(menu)} {/* 하위 메뉴가 있는 경우에만 토글 버튼 표시 */} {menus.some((m) => (m.parent_obj_id || m.PARENT_OBJ_ID) === objid) && ( )}
{seq} {companyCode === "*" ? getText(MENU_MANAGEMENT_KEYS.FILTER_COMPANY_COMMON) : companyName || getText(MENU_MANAGEMENT_KEYS.STATUS_UNSPECIFIED)}
{menuUrl ? (
30 ? "truncate" : "" }`} onClick={() => { navigator.clipboard.writeText(menuUrl); toast.success("URL copied to clipboard!"); }} > {menuUrl}
{menuUrl.length > 30 && (
Full URL
{menuUrl}
Click to copy
)}
) : ( - )}
{getStatusBadge(status, objid)}
{lev === 1 && ( )} {lev === 2 && ( <> )} {lev > 2 && ( )}
); })}
); };