83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
import { ChevronDown, ChevronRight, Home, FileText, Users, BarChart3, Cog, GitBranch } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
import { MenuItem } from "@/types/menu";
|
|
import { MENU_ICONS, MESSAGES } from "@/constants/layout";
|
|
|
|
interface MainSidebarProps {
|
|
menuList: MenuItem[];
|
|
expandedMenus: Set<string>;
|
|
onMenuClick: (menu: MenuItem) => void;
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* 메뉴 아이콘 선택 함수
|
|
*/
|
|
const getMenuIcon = (menuName: string) => {
|
|
if (MENU_ICONS.HOME.some((keyword) => menuName.includes(keyword))) {
|
|
return <Home className="h-4 w-4" />;
|
|
}
|
|
if (MENU_ICONS.DOCUMENT.some((keyword) => menuName.includes(keyword))) {
|
|
return <FileText className="h-4 w-4" />;
|
|
}
|
|
if (MENU_ICONS.USERS.some((keyword) => menuName.includes(keyword))) {
|
|
return <Users className="h-4 w-4" />;
|
|
}
|
|
if (MENU_ICONS.STATISTICS.some((keyword) => menuName.includes(keyword))) {
|
|
return <BarChart3 className="h-4 w-4" />;
|
|
}
|
|
if (MENU_ICONS.SETTINGS.some((keyword) => menuName.includes(keyword))) {
|
|
return <Cog className="h-4 w-4" />;
|
|
}
|
|
if (MENU_ICONS.DATAFLOW.some((keyword) => menuName.includes(keyword))) {
|
|
return <GitBranch className="h-4 w-4" />;
|
|
}
|
|
return <FileText className="h-4 w-4" />;
|
|
};
|
|
|
|
/**
|
|
* 메인 사이드바 컴포넌트
|
|
*/
|
|
export function MainSidebar({ menuList, expandedMenus, onMenuClick, className = "" }: MainSidebarProps) {
|
|
/**
|
|
* 메뉴 아이템 렌더링
|
|
*/
|
|
const renderMenuItem = (menu: MenuItem, level: number = 0) => {
|
|
const hasChildren = menu.children && menu.children.length > 0;
|
|
const isExpanded = expandedMenus.has(String(menu.OBJID));
|
|
|
|
return (
|
|
<div key={String(menu.OBJID)}>
|
|
<button
|
|
onClick={() => onMenuClick(menu)}
|
|
className={cn(
|
|
"flex w-full cursor-pointer items-center justify-between rounded-lg px-3 py-2 text-sm transition-colors",
|
|
"hover:bg-accent hover:text-accent-foreground",
|
|
level > 0 && "ml-4",
|
|
)}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
{getMenuIcon(menu.MENU_NAME_KOR || menu.menuNameKor || "")}
|
|
<span>{menu.MENU_NAME_KOR || menu.menuNameKor || "메뉴"}</span>
|
|
</div>
|
|
{hasChildren && (isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />)}
|
|
</button>
|
|
|
|
{hasChildren && isExpanded && (
|
|
<div className="mt-1 ml-2 space-y-1">{menu.children!.map((child) => renderMenuItem(child, level + 1))}</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<nav className={cn("space-y-1 overflow-y-auto", className)}>
|
|
{menuList.length === 0 ? (
|
|
<div className="text-sm text-gray-500">{MESSAGES.NO_MENUS}</div>
|
|
) : (
|
|
menuList.map((menu) => renderMenuItem(menu))
|
|
)}
|
|
</nav>
|
|
);
|
|
}
|