import React, { useState, useEffect } from 'react'; interface MenuItem { menu_item_id: string; menu_title: string; menu_order: string; post_parent: string; actual_post_id: string; actual_post_title: string; post_type: string; post_status: string; slug: string; custom_url: string; object_type: string; parent_menu_item_id: string; } interface NestedMenuItem extends MenuItem { children?: NestedMenuItem[]; } interface NavigationMenuProps { menuData: MenuItem[]; } const NavigationMenu: React.FC = ({ menuData }) => { const [nestedMenu, setNestedMenu] = useState([]); const [currentMenu, setCurrentMenu] = useState(null); const [activeSubmenu, setActiveSubmenu] = useState(null); // Transform flat array into nested structure useEffect(() => { const buildNestedMenu = (items: MenuItem[]): NestedMenuItem[] => { const itemMap = new Map(); const rootItems: NestedMenuItem[] = []; // Create map of all items items.forEach(item => { itemMap.set(item.menu_item_id, { ...item, children: [] }); }); // Build hierarchy items.forEach(item => { const currentItem = itemMap.get(item.menu_item_id); if (!currentItem) return; if (item.parent_menu_item_id === "0") { rootItems.push(currentItem); } else { const parent = itemMap.get(item.parent_menu_item_id); if (parent) { if (!parent.children) parent.children = []; parent.children.push(currentItem); } } }); // Sort by menu_order const sortByOrder = (items: NestedMenuItem[]): NestedMenuItem[] => { return items.sort((a, b) => parseInt(a.menu_order) - parseInt(b.menu_order)); }; const sortedRoots = sortByOrder(rootItems); sortedRoots.forEach(item => { if (item.children) { item.children = sortByOrder(item.children); } }); return sortedRoots; }; setNestedMenu(buildNestedMenu(menuData)); }, [menuData]); // Close menu when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (!(event.target as Element).closest('.nav-menu-container')) { setCurrentMenu(null); setActiveSubmenu(null); } }; document.addEventListener('click', handleClickOutside); return () => document.removeEventListener('click', handleClickOutside); }, []); const handleMenuEnter = (menuId: string, hasChildren: boolean) => { if (hasChildren) { setCurrentMenu(menuId); setActiveSubmenu(null); } }; const handleMenuLeave = (item_id: string) => { // Small delay to allow moving to submenu if (item_id === currentMenu) { setCurrentMenu(null) setActiveSubmenu(null) } // setTimeout(() => { // if (!document.querySelector('.nav-menu-container:hover')) { // setCurrentMenu(null); // setActiveSubmenu(null); // } // }, 100); }; const handleSubmenuEnter = (submenuId: string) => { setActiveSubmenu(submenuId); }; const renderMenuItems = (items: NestedMenuItem[], level = 0) => { return items.map(item => { const hasChildren = item.children && item.children.length > 0; const isActive = currentMenu === item.menu_item_id; if (!hasChildren) { return ( {item.actual_post_title} ); } return (
handleMenuEnter(item.menu_item_id, true)} onMouseLeave={() => handleMenuLeave(item.menu_item_id)} > {/* First level dropdown */} {isActive && (
{item.children?.map(child => { const childHasChildren = child.children && child.children.length > 0; const isChildActive = activeSubmenu === child.menu_item_id; return (
handleSubmenuEnter(child.menu_item_id)} onMouseLeave={() => setActiveSubmenu(null)} > {!childHasChildren ? ( {child.actual_post_title} ) : ( <>
{child.actual_post_title}
{/* Second level dropdown - appears to the right */} {isChildActive && (
{child.children?.map(grandChild => ( {grandChild.actual_post_title} ))}
)} )}
); })}
)}
); }); }; return ( ); }; export default NavigationMenu;