"use client"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Shield, User, LogOut, Menu, X, Home, Settings, BarChart3, FileText, Users, Package, Wrench, ChevronDown, ChevronRight, } from "lucide-react"; import { useMenu } from "@/contexts/MenuContext"; import { useAuth } from "@/hooks/useAuth"; import { MenuItem } from "@/lib/api/menu"; // useAuth의 UserInfo 타입을 확장 interface ExtendedUserInfo { userId: string; userName: string; userNameEng?: string; userNameCn?: string; deptCode?: string; deptName?: string; positionCode?: string; positionName?: string; email?: string; tel?: string; cellPhone?: string; userType?: string; userTypeName?: string; authName?: string; partnerCd?: string; isAdmin: boolean; sabun?: string; photo?: string | null; companyCode?: string; locale?: string; } // useAuth의 UserInfo 타입을 사용하므로 별도 정의 불필요 interface MainLayoutProps { children: React.ReactNode; } // 메뉴 아이콘 매핑 함수 const getMenuIcon = (menuName: string) => { const name = menuName.toLowerCase(); if (name.includes("대시보드") || name.includes("dashboard")) return ; if (name.includes("관리자") || name.includes("admin")) return ; if (name.includes("사용자") || name.includes("user")) return ; if (name.includes("프로젝트") || name.includes("project")) return ; if (name.includes("제품") || name.includes("product")) return ; if (name.includes("설정") || name.includes("setting")) return ; if (name.includes("로그") || name.includes("log")) return ; if (name.includes("메뉴") || name.includes("menu")) return ; return ; }; // 메뉴 데이터를 UI용으로 변환하는 함수 const convertMenuToUI = (menus: MenuItem[], userInfo: ExtendedUserInfo | null, parentId: string = "0"): any[] => { return menus .filter((menu) => (menu.parent_obj_id || menu.PARENT_OBJ_ID) === parentId) .filter((menu) => (menu.status || menu.STATUS) === "active") .sort((a, b) => (a.seq || a.SEQ || 0) - (b.seq || b.SEQ || 0)) .map((menu) => { const menuId = menu.objid || menu.OBJID; // 사용자 locale 기준으로 번역 처리 const getDisplayText = (menu: MenuItem) => { // 다국어 텍스트가 있으면 사용, 없으면 기본 텍스트 사용 if (menu.translated_name || menu.TRANSLATED_NAME) { return menu.translated_name || menu.TRANSLATED_NAME; } const baseName = menu.menu_name_kor || menu.MENU_NAME_KOR || "메뉴명 없음"; // 사용자 정보에서 locale 가져오기 const userLocale = userInfo?.locale || "ko"; if (userLocale === "EN") { // 영어 번역 const translations: { [key: string]: string } = { 관리자: "Administrator", 사용자: "User Management", 메뉴: "Menu Management", 대시보드: "Dashboard", 권한: "Permission Management", 코드: "Code Management", 설정: "Settings", 로그: "Log Management", 프로젝트: "Project Management", 제품: "Product Management", }; for (const [korean, english] of Object.entries(translations)) { if (baseName.includes(korean)) { return baseName.replace(korean, english); } } } else if (userLocale === "JA") { // 일본어 번역 const translations: { [key: string]: string } = { 관리자: "管理者", 사용자: "ユーザー管理", 메뉴: "メニュー管理", 대시보드: "ダッシュボード", 권한: "権限管理", 코드: "コード管理", 설정: "設定", 로그: "ログ管理", 프로젝트: "プロジェクト管理", 제품: "製品管理", }; for (const [korean, japanese] of Object.entries(translations)) { if (baseName.includes(korean)) { return baseName.replace(korean, japanese); } } } else if (userLocale === "ZH") { // 중국어 번역 const translations: { [key: string]: string } = { 관리자: "管理员", 사용자: "用户管理", 메뉴: "菜单管理", 대시보드: "仪表板", 권한: "权限管理", 코드: "代码管理", 설정: "设置", 로그: "日志管理", 프로젝트: "项目管理", 제품: "产品管理", }; for (const [korean, chinese] of Object.entries(translations)) { if (baseName.includes(korean)) { return baseName.replace(korean, chinese); } } } return baseName; }; const menuName = getDisplayText(menu); const menuUrl = menu.menu_url || menu.MENU_URL; console.log( `메뉴 ${menuId}: 번역명="${menu.translated_name || menu.TRANSLATED_NAME}", 기본명="${menu.menu_name_kor || menu.MENU_NAME_KOR}", 최종명="${menuName}"`, ); const children = convertMenuToUI(menus, userInfo, menuId); return { id: menuId, title: menuName, icon: getMenuIcon(menuName || ""), path: menuUrl, children: children.length > 0 ? children : undefined, }; }); }; export default function MainLayout({ children }: MainLayoutProps) { const router = useRouter(); const { adminMenus, userMenus, loading: menuLoading } = useMenu(); const { user, loading: authLoading, logout } = useAuth(); const [sidebarOpen, setSidebarOpen] = useState(true); const [expandedMenus, setExpandedMenus] = useState([]); // 사용자의 회사 코드에 따라 메뉴 필터링 const filterMenusByCompany = (menus: MenuItem[]) => { console.log("=== 메뉴 필터링 시작 ==="); console.log("사용자 정보:", user); console.log("사용자 회사 코드:", (user as ExtendedUserInfo)?.companyCode); console.log("전체 메뉴 수:", menus.length); console.log("현재 경로:", window.location.pathname); // 모든 메뉴 표시 (원래 상태로 복원) console.log("모든 메뉴 표시"); return menus; }; // 활성 메뉴만 필터링하여 UI용으로 변환 (언어 변경 시 재계산) const activeMenus = [...adminMenus, ...userMenus].filter((menu) => (menu.status || menu.STATUS) === "active"); const filteredMenus = filterMenusByCompany(activeMenus); const menuItems = convertMenuToUI(filteredMenus, user); // 디버깅 로그 추가 console.log("=== MainLayout 메뉴 디버깅 ==="); console.log("adminMenus 개수:", adminMenus.length); console.log("userMenus 개수:", userMenus.length); console.log("activeMenus 개수:", activeMenus.length); console.log("filteredMenus 개수:", filteredMenus.length); console.log("menuItems 개수:", menuItems.length); // 번역 데이터 확인 if (menuItems.length > 0) { console.log("첫 번째 메뉴 아이템:", { id: menuItems[0].id, title: menuItems[0].title, hasChildren: !!menuItems[0].children, }); } if (adminMenus.length > 0) { console.log("첫 번째 adminMenu:", adminMenus[0]); } if (userMenus.length > 0) { console.log("첫 번째 userMenu:", userMenus[0]); } // useAuth 훅에서 인증 상태를 관리하므로 별도 인증 확인 불필요 // useEffect(() => { // checkAuthStatus(); // }, []); // 키보드 단축키로 사이드바 토글 useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { // Ctrl+B 또는 Cmd+B로 사이드바 토글 if ((event.ctrlKey || event.metaKey) && event.key === "b") { event.preventDefault(); setSidebarOpen((prev) => !prev); } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, []); const handleLogout = async () => { await logout(); }; const toggleMenu = (menuId: string) => { setExpandedMenus((prev) => (prev.includes(menuId) ? prev.filter((id) => id !== menuId) : [...prev, menuId])); }; const handleMenuClick = (path?: string) => { if (path) { router.push(path); } }; if (authLoading) { return (

로딩 중...

); } if (!user) { return null; } return (
{/* 상단 헤더 */}

PLM 솔루션

{user.userName} {user.deptName && ({user.deptName})}
{/* 모바일 사이드바 오버레이 */} {sidebarOpen && (
setSidebarOpen(false)} /> )} {/* 왼쪽 사이드바 */} {/* 가운데 컨텐츠 영역 */}
{children}
); }