Files
sam-react-prod/src/stores/menuStore.ts

66 lines
1.8 KiB
TypeScript
Raw Normal View History

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { LucideIcon } from 'lucide-react';
// localStorage 저장용 (icon을 문자열로 저장)
export interface SerializableMenuItem {
id: string;
label: string;
iconName: string; // 문자열로 저장 (예: 'dashboard', 'folder')
path: string;
children?: SerializableMenuItem[];
}
// 실제 사용용 (icon을 컴포넌트로 사용)
export interface MenuItem {
id: string;
label: string;
icon: LucideIcon;
path: string;
component?: React.ComponentType;
children?: MenuItem[];
}
interface MenuState {
activeMenu: string;
menuItems: MenuItem[];
sidebarCollapsed: boolean;
_hasHydrated: boolean;
setActiveMenu: (menuId: string) => void;
setMenuItems: (items: MenuItem[]) => void;
toggleSidebar: () => void;
setSidebarCollapsed: (collapsed: boolean) => void;
setHasHydrated: (hydrated: boolean) => void;
}
export const useMenuStore = create<MenuState>()(
persist(
(set) => ({
activeMenu: 'dashboard',
menuItems: [],
sidebarCollapsed: false,
_hasHydrated: false,
setActiveMenu: (menuId: string) => set({ activeMenu: menuId }),
setMenuItems: (items: MenuItem[]) => set({ menuItems: items }),
toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),
setSidebarCollapsed: (collapsed: boolean) => set({ sidebarCollapsed: collapsed }),
setHasHydrated: (hydrated: boolean) => set({ _hasHydrated: hydrated }),
}),
{
name: 'sam-menu',
// menuItems는 함수(icon)를 포함하므로 localStorage에서 제외
partialize: (state) => ({
activeMenu: state.activeMenu,
sidebarCollapsed: state.sidebarCollapsed,
}),
onRehydrateStorage: () => (state) => {
state?.setHasHydrated(true);
},
}
)
);