From 91ed5ccaa55efb09e4ebdfda8613cbc763126cea Mon Sep 17 00:00:00 2001 From: Rodolfo Ruiz Date: Thu, 28 Aug 2025 20:58:02 -0600 Subject: [PATCH] chore: add the new menu for private mode - admin --- src/components/AppHeader.jsx | 3 +- src/components/MenuDrawerPrivate.jsx | 299 +++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 src/components/MenuDrawerPrivate.jsx diff --git a/src/components/AppHeader.jsx b/src/components/AppHeader.jsx index 8ce313f..6c27a25 100644 --- a/src/components/AppHeader.jsx +++ b/src/components/AppHeader.jsx @@ -2,6 +2,7 @@ import { useState } from 'react'; import { AppBar, Toolbar, Typography, IconButton, Box, Avatar } from '@mui/material'; import MenuDrawer from './MenuDrawer'; +import MenuDrawerPrivate from './MenuDrawerPrivate'; import { useAuth } from '../context/AuthContext'; import { useNavigate } from 'react-router-dom'; @@ -86,7 +87,7 @@ export default function AppHeader({ zone = 'public', onSelectMenuItem }) { )} - setDrawerExpanded(expanded)} diff --git a/src/components/MenuDrawerPrivate.jsx b/src/components/MenuDrawerPrivate.jsx new file mode 100644 index 0000000..e43a992 --- /dev/null +++ b/src/components/MenuDrawerPrivate.jsx @@ -0,0 +1,299 @@ +// src/components/MenuDrawerPrivate.jsx +import React, { useMemo, useState, useEffect } from 'react'; +import { + Drawer, List, ListItemButton, ListItemIcon, ListItemText, + Collapse, IconButton, Tooltip, Box, useMediaQuery, InputBase +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; + +// MUI icons (you can replace with your PNGs later) +import InsightsIcon from '@mui/icons-material/Insights'; +import Inventory2Icon from '@mui/icons-material/Inventory2'; +import PeopleAltIcon from '@mui/icons-material/PeopleAlt'; +import BusinessIcon from '@mui/icons-material/Business'; +import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings'; +import SettingsIcon from '@mui/icons-material/Settings'; +import ExpandLess from '@mui/icons-material/ExpandLess'; +import ExpandMore from '@mui/icons-material/ExpandMore'; + +const OPEN_WIDTH = 400; +const MINI_WIDTH = 72; + +// ---- Hierarchy (from your diagram). Leaves are "CRUD" pages (clickables). ---- +const menuData = [ + { + title: 'Business Intelligence', + icon: , + children: [ + { title: 'Sales Report' }, + { title: 'Customer Insights' }, + { title: 'Customer Insights 2' }, + ] + }, + { + title: 'Products Management', + icon: , + children: [ + { + title: 'Catalog Management', + children: [ + { + title: 'Category Dictionary', + children: [ + { title: 'Categories' }, + { title: 'Products' }, + { title: 'All Assets Library' }, + { title: 'Media Management' }, + { title: 'Product Collections' }, + ] + } + ] + } + ] + }, + { + title: 'Customers', + icon: , + children: [ + { title: 'CRM' }, + { title: 'Customer List' }, + { + title: 'Projects', + children: [ + { title: 'Customer Collections' }, + { title: 'Sales' }, + { title: 'Quotes' }, + { title: 'Orders' }, + ] + } + ] + }, + { + title: 'Providers (Brands and Clients)', + icon: , + children: [ + { title: 'Brand Partners' }, + { title: 'Companies' }, + { title: 'Suppliers' }, + { title: 'Materials Providers' }, + ] + }, + { + title: 'Users', + icon: , + children: [ + { title: 'Users Management' }, + { title: 'Access Control' }, + { title: 'Roles' }, + { title: 'Permissions' }, + ] + }, + { + title: 'Settings', + icon: , + children: [ + { title: 'General Settings' }, + { title: 'WebApp Configuration' }, + { title: 'Mobile App Configuration' }, + ] + }, +]; + +export default function MenuDrawerPrivate({ + open, // optional: for mobile temporary drawer + onClose, // optional: for mobile temporary drawer + onSelect, // (title) => void + onExpandedChange, // (boolean) => void // optional: tell header if expanded/collapsed +}) { + const theme = useTheme(); + const isMobile = useMediaQuery('(max-width:900px)'); + + const [collapsed, setCollapsed] = useState(false); + // open states per branch key + const [openMap, setOpenMap] = useState({}); + + // keep collapsed in sync only if "open" prop provided (mobile) + useEffect(() => { + if (!isMobile) return; + if (typeof open === 'boolean') { + // temporary drawer: collapsed UI is not shown on mobile, treat as expanded + setCollapsed(false); + } + }, [open, isMobile]); + + // inform parent of expanded/collapsed (desktop) + useEffect(() => { + onExpandedChange?.(isMobile ? true : !collapsed); + }, [collapsed, isMobile, onExpandedChange]); + + const paperWidth = isMobile ? OPEN_WIDTH : (collapsed ? MINI_WIDTH : OPEN_WIDTH); + + const toggleCollapse = () => setCollapsed(c => !c); + + const handleToggleNode = (key) => { + // if rail collapsed, expand rail first to reveal submenu + if (!isMobile && collapsed) { + setCollapsed(false); + setOpenMap((m) => ({ ...m, [key]: true })); + return; + } + setOpenMap((m) => ({ ...m, [key]: !m[key] })); + }; + + const renderNode = (node, keyPrefix = '') => { + const key = `${keyPrefix}${node.title}`; + const hasChildren = !!node.children?.length; + + return ( + + + { + if (hasChildren) { + handleToggleNode(key); + } else { + onSelect?.(node.title); + if (isMobile) onClose?.(); + } + }} + sx={{ + px: collapsed ? 0 : 2, + minHeight: 48, + justifyContent: collapsed ? 'center' : 'flex-start', + }} + > + {node.icon && ( + + {node.icon} + + )} + + {!collapsed && ( + <> + + {hasChildren ? (openMap[key] ? : ) : null} + + )} + + + + {hasChildren && !collapsed && ( + + + {node.children.map((child, idx) => renderNode(child, `${key}-`))} + + + )} + + ); + }; + + return ( + + + + {!collapsed && ( + + Dream Views + + + + )} + + + {collapsed && ( + + Dream Views + + )} + + {/* Tree */} + + {menuData.map((node) => renderNode(node))} + + + + setCollapsed((c) => !c)} sx={{ + backgroundColor: 'transparent', + color: 'transparent', + '&:hover': { + backgroundColor: '#fff4ec', + borderColor: 'transparent' + }, + borderRadius: 0, + marginLeft: 2, + width: 40, + height: 40, + }}> + {collapsed + + + + ); +} \ No newline at end of file