2f398ae0b3
- 제어모드 IDE: ControlCardPanel, control/ide/* (Canvas/LeftRail/RightRail/PanZoomStage/V3RuleNode 등), schemas, lib/api/control - 레지스트리 정리: aggregation-widget, status-count, section-card/paper, table-list(legacy/v2), tabs-widget 폐기 → table/_shared/ 로 통합 - InvLegacyButtonConfigPanel cp 마이그레이션 - canonical data view cleanup 후속 노트
99 lines
3.6 KiB
TypeScript
99 lines
3.6 KiB
TypeScript
"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 정보 가져오기
|
|
|
|
interface MenuContextType {
|
|
admin_menus: MenuItem[];
|
|
user_menus: 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 정보 가져오기
|
|
|
|
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,
|
|
// 아이콘 필드
|
|
menu_icon: item.MENU_ICON || item.menu_icon,
|
|
// 다국어 관련 필드
|
|
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);
|
|
|
|
// 관리자 메뉴와 사용자 메뉴를 병렬로 로드
|
|
// 좌측 사이드바용: active만 표시
|
|
// 로케일은 useAuth.fetchCurrentUser 가 /auth/me 응답에서 세팅 완료 후 user.company_code 가 채워지므로
|
|
// 이 함수가 호출되는 시점에는 항상 __GLOBAL_USER_LANG 이 세팅되어 있음 → 별도 대기 불필요
|
|
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(() => {
|
|
if (!user?.company_code) return;
|
|
loadMenus();
|
|
}, [user?.company_code]);
|
|
|
|
return (
|
|
<MenuContext.Provider value={{ admin_menus: adminMenus, user_menus: 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;
|
|
}
|