ERP-node/frontend/contexts/MenuContext.tsx

118 lines
4.1 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
"use client";
import React, { createContext, useContext, useState, useEffect, ReactNode } from "react";
import type { MenuItem } from "@/lib/api/menu";
import { menuApi } from "@/lib/api/menu"; // API 호출 활성화
import { toast } from "sonner";
import { useAuth } from "@/hooks/useAuth"; // user 정보 가져오기
2025-08-21 09:41:46 +09:00
interface MenuContextType {
adminMenus: MenuItem[];
userMenus: MenuItem[];
loading: boolean;
refreshMenus: () => Promise<void>;
}
const MenuContext = createContext<MenuContextType | undefined>(undefined);
export function MenuProvider({ children }: { children: ReactNode }) {
const [adminMenus, setAdminMenus] = useState<MenuItem[]>([]);
const [userMenus, setUserMenus] = useState<MenuItem[]>([]);
const [loading, setLoading] = useState(true);
const { user } = useAuth(); // user 정보 가져오기
2025-08-21 09:41:46 +09:00
const convertMenuData = (data: any[]): MenuItem[] => {
return data.map((item) => ({
objid: item.OBJID || item.objid,
parent_obj_id: item.PARENT_OBJ_ID || item.parent_obj_id,
menu_name_kor: item.MENU_NAME_KOR || item.menu_name_kor,
menu_url: item.MENU_URL || item.menu_url,
menu_desc: item.MENU_DESC || item.menu_desc,
seq: item.SEQ || item.seq,
menu_type: item.MENU_TYPE || item.menu_type,
status: item.STATUS || item.status,
lev: item.LEV || item.lev,
lpad_menu_name_kor: item.LPAD_MENU_NAME_KOR || item.lpad_menu_name_kor,
status_title: item.STATUS_TITLE || item.status_title,
writer: item.WRITER || item.writer,
regdate: item.REGDATE || item.regdate,
company_code: item.COMPANY_CODE || item.company_code,
company_name: item.COMPANY_NAME || item.company_name,
// 다국어 관련 필드 추가
lang_key: item.LANG_KEY || item.lang_key,
lang_key_desc: item.LANG_KEY_DESC || item.lang_key_desc,
translated_name: item.TRANSLATED_NAME || item.translated_name,
translated_desc: item.TRANSLATED_DESC || item.translated_desc,
}));
};
const loadMenus = async () => {
try {
setLoading(true);
2025-08-26 18:33:04 +09:00
// 사용자 로케일이 로드될 때까지 잠시 대기
let retryCount = 0;
const maxRetries = 20; // 최대 2초 대기 (100ms * 20)
while (retryCount < maxRetries) {
if (typeof window !== "undefined") {
const hasGlobalLang = !!(window as any).__GLOBAL_USER_LANG;
const hasStoredLang = !!localStorage.getItem("userLocale");
if (hasGlobalLang || hasStoredLang) {
break;
}
}
await new Promise((resolve) => setTimeout(resolve, 100));
retryCount++;
}
if (retryCount >= maxRetries) {
console.warn("⚠️ 사용자 로케일 로드 타임아웃, 기본값으로 진행");
}
2025-08-21 09:41:46 +09:00
// 관리자 메뉴와 사용자 메뉴를 병렬로 로드
// 좌측 사이드바용: active만 표시
2025-08-21 09:41:46 +09:00
const [adminResponse, userResponse] = await Promise.all([menuApi.getAdminMenus(), menuApi.getUserMenus()]);
if (adminResponse.success && adminResponse.data) {
const convertedAdminMenus = convertMenuData(adminResponse.data);
setAdminMenus(convertedAdminMenus);
}
if (userResponse.success && userResponse.data) {
const convertedUserMenus = convertMenuData(userResponse.data);
setUserMenus(convertedUserMenus);
}
} catch (error) {
console.error("메뉴 로드 오류:", error);
toast.error("메뉴 목록을 불러오는데 실패했습니다.");
} finally {
setLoading(false);
}
};
const refreshMenus = async () => {
await loadMenus();
};
useEffect(() => {
// user.companyCode가 변경되면 메뉴 다시 로드
// console.log("🔄 MenuContext: user.companyCode 변경 감지, 메뉴 재로드", user?.companyCode);
2025-08-21 09:41:46 +09:00
loadMenus();
}, [user?.companyCode]); // companyCode 변경 시 재로드
2025-08-21 09:41:46 +09:00
return (
<MenuContext.Provider value={{ adminMenus, userMenus, loading, refreshMenus }}>{children}</MenuContext.Provider>
);
}
export function useMenu() {
const context = useContext(MenuContext);
if (context === undefined) {
throw new Error("useMenu must be used within a MenuProvider");
}
return context;
}