ERP-node/frontend/hooks/useMenu.ts

167 lines
5.1 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
"use client";
import { useState, useEffect, useCallback } from "react";
import { useRouter } from "next/navigation";
import { MenuItem, MenuState } from "@/types/menu";
import { apiClient } from "@/lib/api/client";
2025-08-21 09:41:46 +09:00
/**
*
* - API apiClient를 ( /401 )
* - / (client.ts가 )
2025-08-21 09:41:46 +09:00
*/
export const useMenu = (user: any, authLoading: boolean) => {
const router = useRouter();
const [menuState, setMenuState] = useState<MenuState>({
menuList: [],
expandedMenus: new Set(),
isLoading: true,
});
/**
*
*/
const convertToUpperCaseKeys = useCallback((data: Record<string, unknown>[]): MenuItem[] => {
return data.map((item) => {
const converted: Record<string, unknown> = {};
Object.keys(item).forEach((key) => {
const upperKey = key.toUpperCase();
converted[upperKey] = item[key];
});
return converted as unknown as MenuItem;
});
}, []);
/**
*
*/
const buildMenuTree = useCallback((menuItems: MenuItem[]): MenuItem[] => {
const menuMap = new Map<string, MenuItem>();
const rootMenus: MenuItem[] = [];
menuItems.forEach((menu) => {
const objId = String(menu.OBJID);
const parentId = String(menu.PARENT_OBJ_ID);
menuMap.set(objId, { ...menu, OBJID: objId, PARENT_OBJ_ID: parentId, children: [] });
});
menuItems.forEach((menu) => {
const objId = String(menu.OBJID);
const parentId = String(menu.PARENT_OBJ_ID);
const menuItem = menuMap.get(objId)!;
if (parentId !== "-395553955") {
const parent = menuMap.get(parentId);
if (parent) {
parent.children = parent.children || [];
parent.children.push(menuItem);
}
} else {
rootMenus.push(menuItem);
}
});
return rootMenus.sort((a, b) => (a.SEQ || 0) - (b.SEQ || 0));
}, []);
/**
*
* - apiClient /401
* - ( client.ts )
2025-08-21 09:41:46 +09:00
*/
const loadMenuData = useCallback(async () => {
try {
const response = await apiClient.get("/admin/user-menus");
if (response.data?.success && response.data?.data) {
const convertedMenuData = convertToUpperCaseKeys(response.data.data || []);
setMenuState((prev: MenuState) => ({
...prev,
menuList: buildMenuTree(convertedMenuData),
isLoading: false,
}));
} else {
setMenuState((prev: MenuState) => ({ ...prev, isLoading: false }));
2025-08-21 09:41:46 +09:00
}
} catch {
// API 실패 시 빈 메뉴로 유지 (401은 client.ts 인터셉터가 리다이렉트 처리)
2025-08-21 09:41:46 +09:00
setMenuState((prev: MenuState) => ({ ...prev, isLoading: false }));
}
}, [convertToUpperCaseKeys, buildMenuTree]);
2025-08-21 09:41:46 +09:00
/**
*
*/
const toggleMenu = useCallback((menuId: string) => {
setMenuState((prev: MenuState) => {
const newExpanded = new Set(prev.expandedMenus);
if (newExpanded.has(menuId)) {
newExpanded.delete(menuId);
} else {
newExpanded.add(menuId);
}
return {
...prev,
expandedMenus: newExpanded,
};
});
}, []);
/**
*
*/
const handleMenuClick = useCallback(
2025-09-01 18:42:59 +09:00
async (menu: MenuItem) => {
2025-08-21 09:41:46 +09:00
if (menu.children && menu.children.length > 0) {
toggleMenu(String(menu.OBJID));
2025-09-01 18:42:59 +09:00
} else {
const menuName = menu.MENU_NAME_KOR || menu.menuNameKor || menu.TRANSLATED_NAME || "메뉴";
if (typeof window !== "undefined") {
localStorage.setItem("currentMenuName", menuName);
}
2025-09-01 18:42:59 +09:00
try {
const menuObjid = menu.OBJID || menu.objid;
if (menuObjid) {
const { menuScreenApi } = await import("@/lib/api/screen");
const assignedScreens = await menuScreenApi.getScreensByMenu(parseInt(menuObjid.toString()));
if (assignedScreens.length > 0) {
const firstScreen = assignedScreens[0];
router.push(`/screens/${firstScreen.screenId}?menuObjid=${menuObjid}`);
2025-09-01 18:42:59 +09:00
return;
}
}
} catch (error) {
console.warn("할당된 화면 조회 실패:", error);
}
if (menu.MENU_URL) {
router.push(menu.MENU_URL);
} else {
console.warn("메뉴에 URL이나 할당된 화면이 없습니다:", menu);
const { toast } = await import("sonner");
toast.warning("이 메뉴에는 연결된 페이지나 화면이 없습니다.");
}
2025-08-21 09:41:46 +09:00
}
},
[toggleMenu, router],
);
useEffect(() => {
if (user && !authLoading) {
loadMenuData();
}
}, [user, authLoading, loadMenuData]);
return {
menuList: menuState.menuList,
expandedMenus: menuState.expandedMenus,
isMenuLoading: menuState.isLoading,
handleMenuClick,
toggleMenu,
refreshMenus: loadMenuData,
2025-08-21 09:41:46 +09:00
};
};