import { useState } from 'react'; import { ADMIN_MENU } from './adminMenuConfig'; import type { AdminMenuItem } from './adminMenuConfig'; interface AdminSidebarProps { activeMenu: string; onSelect: (id: string) => void; } /** 관리자 좌측 사이드바 — 9-섹션 아코디언 */ const AdminSidebar = ({ activeMenu, onSelect }: AdminSidebarProps) => { const [expanded, setExpanded] = useState>(() => { // 초기: 첫 번째 섹션 열기 const init = new Set(); if (ADMIN_MENU.length > 0) init.add(ADMIN_MENU[0].id); return init; }); const toggle = (id: string) => { setExpanded((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); }; /** 재귀적으로 메뉴 아이템이 activeMenu를 포함하는지 확인 */ const containsActive = (item: AdminMenuItem): boolean => { if (item.id === activeMenu) return true; return item.children?.some((c) => containsActive(c)) ?? false; }; const renderLeaf = (item: AdminMenuItem, depth: number) => { const isActive = item.id === activeMenu; return ( ); }; const renderGroup = (item: AdminMenuItem, depth: number) => { const isOpen = expanded.has(item.id); const hasActiveChild = containsActive(item); return (
{isOpen && item.children && (
{item.children.map((child) => renderItem(child, depth + 1))}
)}
); }; const renderItem = (item: AdminMenuItem, depth: number) => { if (item.children && item.children.length > 0) { return renderGroup(item, depth); } return renderLeaf(item, depth); }; return (
{/* 헤더 */}
⚙️ 관리자 설정
{/* 메뉴 목록 */}
{ADMIN_MENU.map((section) => { const isOpen = expanded.has(section.id); const hasActiveChild = containsActive(section); return (
{/* 섹션 헤더 */} {/* 하위 메뉴 */} {isOpen && section.children && (
{section.children.map((child) => renderItem(child, 1))}
)}
); })}
); }; /** children 중 첫 번째 leaf 노드를 찾는다 */ function findFirstLeaf(items: AdminMenuItem[]): AdminMenuItem | null { for (const item of items) { if (!item.children || item.children.length === 0) return item; const found = findFirstLeaf(item.children); if (found) return found; } return null; } export default AdminSidebar;