prod-wag-backend-automate-s.../web_services/web-controllers/components/custom/menu/component.tsx

173 lines
6.6 KiB
TypeScript

'use client';
import { FC, useState, useEffect } from "react";
import { MenuProps } from "@/validations/mutual/dashboard/props";
import { langGetKey } from "@/lib/langGet";
import { parseURlFormString } from "@/lib/menuGet";
import FirstLayerDropdown from "./firstLayerComponent";
import SecondLayerDropdown from "./secondLayerComponent";
import ThirdLayerDropdown from "./thirdLayerComponent";
// Define types for menu structure
type ThirdLayerItem = Record<string, any>;
type SecondLayerItems = Record<string, ThirdLayerItem>;
type FirstLayerItems = Record<string, SecondLayerItems>;
type MenuStructure = FirstLayerItems;
const MenuComponent: FC<MenuProps> = ({ lang, menuItems, menuTranslationsFlatten, activePageUrl }) => {
// State for tracking expanded menu items
const [expandedFirstLayer, setExpandedFirstLayer] = useState<string | null>(null);
const [expandedSecondLayer, setExpandedSecondLayer] = useState<string | null>(null);
const [menuStructure, setMenuStructure] = useState<MenuStructure>({});
// Parse active URL to determine which menu items should be active
const activePathLayers = parseURlFormString(activePageUrl).data;
const activeFirstLayer = activePathLayers[0] || null;
const activeSecondLayer = activePathLayers[1] || null;
const activeThirdLayer = activePathLayers[2] || null;
// Initialize expanded state based on active path
useEffect(() => {
if (activeFirstLayer) {
setExpandedFirstLayer(activeFirstLayer);
if (activeSecondLayer) {
setExpandedSecondLayer(activeSecondLayer);
}
}
}, [activeFirstLayer, activeSecondLayer]);
// Process menu items into a hierarchical structure
useEffect(() => {
const processedStructure: MenuStructure = {};
Object.entries(menuItems).forEach(([path, _]: [string, any]) => {
const layers = parseURlFormString(path).data;
const firstLayer = layers[0];
const secondLayer = layers[1];
const thirdLayer = layers[2];
// Create first layer if it doesn't exist
if (!processedStructure[firstLayer]) {
processedStructure[firstLayer] = {};
}
// Create second layer if it doesn't exist
if (!processedStructure[firstLayer][secondLayer]) {
processedStructure[firstLayer][secondLayer] = {};
}
// Add third layer
processedStructure[firstLayer][secondLayer][thirdLayer] = {};
});
setMenuStructure(processedStructure);
}, [menuItems]);
// Handle click on first layer menu item
const handleFirstLayerClick = (key: string) => {
if (expandedFirstLayer === key) {
// If already expanded, collapse it
setExpandedFirstLayer(null);
setExpandedSecondLayer(null);
} else {
// Otherwise expand it
setExpandedFirstLayer(key);
setExpandedSecondLayer(null);
}
};
// Handle click on second layer menu item
const handleSecondLayerClick = (key: string) => {
if (expandedSecondLayer === key) {
// If already expanded, collapse it
setExpandedSecondLayer(null);
} else {
// Otherwise expand it
setExpandedSecondLayer(key);
}
};
// Render third layer menu items
const renderThirdLayerItems = (firstLayerKey: string, secondLayerKey: string, thirdLayerItems: ThirdLayerItem) => {
const baseUrl = `/${firstLayerKey}/${secondLayerKey}`;
return Object.keys(thirdLayerItems).map(thirdLayerKey => {
const isActive =
activeFirstLayer === firstLayerKey &&
activeSecondLayer === secondLayerKey &&
activeThirdLayer === thirdLayerKey;
const url = `/${lang}${baseUrl}/${thirdLayerKey}`;
return (
<div key={`${thirdLayerKey}-item`} className="ml-2 my-1">
<ThirdLayerDropdown
isActive={isActive}
innerText={langGetKey(menuTranslationsFlatten, thirdLayerKey)}
url={url}
/>
</div>
);
});
};
// Render second layer menu items
const renderSecondLayerItems = (firstLayerKey: string, secondLayerItems: SecondLayerItems) => {
return Object.entries(secondLayerItems).map(([secondLayerKey, thirdLayerItems]) => {
const isActive = activeFirstLayer === firstLayerKey && activeSecondLayer === secondLayerKey;
const isExpanded = expandedSecondLayer === secondLayerKey;
return (
<div key={`${secondLayerKey}-item`} className="ml-2 my-1">
<SecondLayerDropdown
isActive={isActive}
isExpanded={isExpanded}
innerText={langGetKey(menuTranslationsFlatten, secondLayerKey)}
onClick={() => handleSecondLayerClick(secondLayerKey)}
/>
{isExpanded && (
<div className="ml-2 mt-1">
{renderThirdLayerItems(firstLayerKey, secondLayerKey, thirdLayerItems)}
</div>
)}
</div>
);
});
};
// Render first layer menu items
const renderFirstLayerItems = () => {
return Object.entries(menuStructure).map(([firstLayerKey, secondLayerItems]) => {
const isActive = activeFirstLayer === firstLayerKey;
const isExpanded = expandedFirstLayer === firstLayerKey;
return (
<div key={`${firstLayerKey}-item`} className="mb-2">
<FirstLayerDropdown
isActive={isActive}
isExpanded={isExpanded}
innerText={langGetKey(menuTranslationsFlatten, firstLayerKey)}
onClick={() => handleFirstLayerClick(firstLayerKey)}
/>
{isExpanded && (
<div className="mt-1">
{renderSecondLayerItems(firstLayerKey, secondLayerItems)}
</div>
)}
</div>
);
});
};
return (
<div className="fixed top-24 p-5 left-0 right-0 w-80 border-emerald-150 border-r-2 overflow-y-auto h-[calc(100vh-6rem)]">
<div className="flex flex-col">
{renderFirstLayerItems()}
</div>
</div>
);
};
export default MenuComponent;