2025-11-11 18:55:16 +09:00
|
|
|
import type { MenuItem, SerializableMenuItem } from '@/store/menuStore';
|
|
|
|
|
import {
|
|
|
|
|
LayoutDashboard,
|
|
|
|
|
Folder,
|
|
|
|
|
Settings,
|
|
|
|
|
Package,
|
|
|
|
|
Building2,
|
|
|
|
|
FileText,
|
|
|
|
|
Users,
|
|
|
|
|
Lock,
|
|
|
|
|
Building,
|
2025-12-04 12:48:41 +09:00
|
|
|
ShoppingCart,
|
|
|
|
|
Receipt,
|
|
|
|
|
Factory,
|
2025-11-11 18:55:16 +09:00
|
|
|
LucideIcon,
|
|
|
|
|
} from 'lucide-react';
|
|
|
|
|
|
|
|
|
|
// 아이콘 매핑 (string → component)
|
|
|
|
|
export const iconMap: Record<string, LucideIcon> = {
|
|
|
|
|
dashboard: LayoutDashboard,
|
|
|
|
|
folder: Folder,
|
|
|
|
|
settings: Settings,
|
|
|
|
|
inventory: Package, // Inventory 대신 Package 사용
|
|
|
|
|
business: Building2,
|
|
|
|
|
assignment: FileText,
|
|
|
|
|
people: Users,
|
|
|
|
|
lock: Lock,
|
|
|
|
|
corporate_fare: Building,
|
2025-12-04 12:48:41 +09:00
|
|
|
// 판매관리 관련 아이콘
|
|
|
|
|
shopping_cart: ShoppingCart,
|
|
|
|
|
sales: ShoppingCart,
|
|
|
|
|
receipt: Receipt,
|
|
|
|
|
quote: Receipt,
|
|
|
|
|
customers: Building2,
|
|
|
|
|
// 생산관리 관련 아이콘
|
|
|
|
|
factory: Factory,
|
|
|
|
|
production: Factory,
|
2025-11-11 18:55:16 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// API 메뉴 데이터 타입
|
|
|
|
|
interface ApiMenu {
|
|
|
|
|
id: number;
|
|
|
|
|
parent_id: number | null;
|
|
|
|
|
name: string;
|
|
|
|
|
url: string;
|
|
|
|
|
icon: string;
|
|
|
|
|
sort_order: number;
|
|
|
|
|
is_external: number;
|
|
|
|
|
external_url: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* API 메뉴 데이터를 SerializableMenuItem 구조로 변환 (localStorage 저장용)
|
|
|
|
|
*/
|
|
|
|
|
export function transformApiMenusToMenuItems(apiMenus: ApiMenu[]): SerializableMenuItem[] {
|
|
|
|
|
if (!apiMenus || !Array.isArray(apiMenus)) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parent_id가 null인 최상위 메뉴만 추출
|
|
|
|
|
const parentMenus = apiMenus
|
|
|
|
|
.filter((menu) => menu.parent_id === null)
|
|
|
|
|
.sort((a, b) => a.sort_order - b.sort_order);
|
|
|
|
|
|
|
|
|
|
// 각 부모 메뉴에 대해 자식 메뉴 찾기
|
|
|
|
|
const menuItems: SerializableMenuItem[] = parentMenus.map((parentMenu) => {
|
|
|
|
|
const children = apiMenus
|
|
|
|
|
.filter((menu) => menu.parent_id === parentMenu.id)
|
|
|
|
|
.sort((a, b) => a.sort_order - b.sort_order)
|
|
|
|
|
.map((childMenu) => ({
|
|
|
|
|
id: childMenu.id.toString(),
|
|
|
|
|
label: childMenu.name,
|
|
|
|
|
iconName: childMenu.icon || 'folder', // 문자열로 저장
|
|
|
|
|
path: childMenu.url || '#',
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: parentMenu.id.toString(),
|
|
|
|
|
label: parentMenu.name,
|
|
|
|
|
iconName: parentMenu.icon || 'folder', // 문자열로 저장
|
|
|
|
|
path: parentMenu.url || '#',
|
|
|
|
|
children: children.length > 0 ? children : undefined,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return menuItems;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SerializableMenuItem을 MenuItem으로 변환 (icon 문자열 → 컴포넌트)
|
|
|
|
|
*/
|
|
|
|
|
export function deserializeMenuItems(serializedMenus: SerializableMenuItem[]): MenuItem[] {
|
|
|
|
|
return serializedMenus.map((item) => ({
|
|
|
|
|
id: item.id,
|
|
|
|
|
label: item.label,
|
|
|
|
|
icon: iconMap[item.iconName] || Folder,
|
|
|
|
|
path: item.path,
|
|
|
|
|
children: item.children ? deserializeMenuItems(item.children) : undefined,
|
|
|
|
|
}));
|
|
|
|
|
}
|