Android_Retail/src/Components/Menu/SideMenuPozo.jsx

538 lines
17 KiB
JavaScript

import React, { useState, useEffect, useRef } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useSelector } from 'react-redux';
import {
FaBars,
FaThLarge,
FaHome,
FaCog,
FaChartBar,
FaFileAlt,
FaMobileAlt,
FaSignOutAlt,
FaSignInAlt,
FaArrowRight,
FaCaretRight,
} from 'react-icons/fa';
import {
MdSettings,
MdOutlineReport,
MdOutlineHome,
MdOutlineKeyboardArrowDown,
MdOutlineKeyboardArrowRight,
} from 'react-icons/md';
import { BiLogOut, BiLogIn } from 'react-icons/bi';
import {
AiOutlineAppstore,
AiOutlineSetting,
AiOutlineBarChart,
AiOutlineFileText,
} from 'react-icons/ai';
import { GiHamburgerMenu } from 'react-icons/gi';
import './SideMenuPozo.scss';
import { FaCaretDown } from 'react-icons/fa';
import { useDispatch } from 'react-redux';
import { useContext } from 'react';
import { AuthContext } from '../../AuthContext';
import PozoMenu from './PozoMenu';
import { getSession } from '../../Services/Others';
import {
changePreviewComponents,
changeSelectedPrintdummyData,
getTemplate,
} from '../../Features/ThemeChange/ThemeChange';
import {
changeBookingType,
changeOrderCardDetails,
changeReorderHoldDetails,
changeProductCategorie,
changeCustomerID,
changeSelectedCustId,
changeSelectedOption,
ChangeOverAllDiscSales,
ChangeOverAllDiscEstimate,
changeSummeryTotalAmount,
changeSearchedData,
changeBtoBQuickProductTransfer,
changeTipAmount,
GlobalDineinDefault,
changePreviousOrderOfferDetail,
changePreviousOrderPayment,
changeBillEditingMode,
} from '../../Features/BookingScreen/BookingData/BookingData';
import {
changeWholeSaleAuctionSelectedData,
changeWholeSaleGradeListData,
} from '../../Features/WholeSale/WholesaleData';
import { ChangeTotalAmount } from '../../Features/ExteraCharges/ExtraCharges';
import * as Offer from '../../Features/Offer/Offer';
import { FiMenu } from 'react-icons/fi';
import POZOMIND from '../../Images/PozomindWLogo.png';
import {
ChangeFullFreeProductList,
changeFullOfferAppliedProducts,
changeLoyaltyConsumedQuantities,
} from '../../Features/Offer/Offernew/BookingOffernew';
const subDirectory = import.meta.env.BASE_URL;
// Filter functions (copied from AppPage.jsx)
function filterMenuItems(menu, configList) {
if (!Array.isArray(menu)) return [];
return menu
.filter((item) => {
if (!item) return false;
if (item.label === 'Sign Out') return true;
// For nested children, filter recursively
let filteredChildren = item.children
? filterMenuItems(item.children, configList)
: undefined;
// Employee access: ConfigName
const config = configList?.find(
(config) =>
config.ConfigName === item.label && config.ReadAccess === 'Y'
);
// If this item or any of its children are accessible, include it
return config || (filteredChildren && filteredChildren.length > 0);
})
.map((item) => ({
...item,
children: item.children
? filterMenuItems(item.children, configList)
: undefined,
}));
}
function filterSadminUserMenuItems(menu, configList) {
if (!Array.isArray(menu)) return [];
return menu
.filter((item) => {
if (!item) return false;
if (item.label === 'Sign Out') return true;
let filteredChildren = item.children
? filterSadminUserMenuItems(item.children, configList)
: undefined;
// Super admin user access: MenuName
const config = configList?.find(
(config) => config.MenuName === item.label && config.ReadAccess === 'Y'
);
return config || (filteredChildren && filteredChildren.length > 0);
})
.map((item) => ({
...item,
children: item.children
? filterSadminUserMenuItems(item.children, configList)
: undefined,
}));
}
// Capitalize helper
function capitalizeWords(str) {
if (typeof str !== 'string') return '';
return str.replace(
/\w\S*/g,
(txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
);
}
// Recursively capitalize all menu item labels, filtering out falsy items and items without a label
function capitalizeMenuLabels(items) {
return (items || [])
.filter(
(item) =>
item && typeof item.label === 'string' && item.label.trim() !== ''
)
.map((item) => ({
...item,
label: capitalizeWords(item.label),
children: item.children ? capitalizeMenuLabels(item.children) : undefined,
}));
}
const SideMenuPozo = ({ items = [] }) => {
const {
freeProductsCount,
setFreeProductsCount,
UserType,
Access,
SadminuserAccess,
} = useContext(AuthContext);
const dispatch = useDispatch();
const navigate = useNavigate();
const location = useLocation();
const [openKeys, setOpenKeys] = useState([]);
const [collapsed, setCollapsed] = useState(window.innerWidth < 768);
const [dropdownPosition, setDropdownPosition] = useState({});
const menuRef = useRef();
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const AppId = getSession('AppId');
const DineinDefault = useSelector(GlobalDineinDefault);
const [collapse, setCollapse] = useState(false);
useEffect(() => {
const handleResize = () => {
setCollapse(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => {
const handleResize = () => {
setCollapsed(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => {
const handleClickOutside = (e) => {
if (menuRef.current && !menuRef.current.contains(e.target)) {
setOpenKeys([]);
setDropdownPosition({});
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
useEffect(() => {
const handleClickOutside = (event) => {
if (window.innerWidth < 768) {
if (menuRef.current && !menuRef.current.contains(event.target)) {
setCollapse(true);
}
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
// Debug current pathname
useEffect(() => {
console.log('Current pathname:', location.pathname);
}, [location.pathname]);
const isSelected = (key) => location.pathname === key;
const isOpen = (key) => openKeys.includes(key);
// Check if any child of this item is selected (for parent menu highlighting)
const hasSelectedChild = (item) => {
if (!item.children) return false;
return item.children.some((child) => {
if (child.children) {
return hasSelectedChild(child);
}
return location.pathname === child.key;
});
};
// Check if a dropdown item is currently selected
const isDropdownItemSelected = (item) => {
return location.pathname === item.key;
};
const navigatefun = async (e) => {
dispatch(changePreviewComponents({}));
dispatch(changeSelectedPrintdummyData(false));
dispatch(changeWholeSaleGradeListData([]));
dispatch(changeWholeSaleAuctionSelectedData([]));
dispatch(
changeBtoBQuickProductTransfer({
action: false,
selectedProducts: [],
})
);
if (e == `${subDirectory}sales/dine-in`) {
dispatch(changeTipAmount(0));
dispatch(changeBookingType('Dine In'));
dispatch(changeOrderCardDetails([]));
dispatch(changeReorderHoldDetails({}));
dispatch(changeProductCategorie(null));
dispatch(changeCustomerID(null));
dispatch(changeSelectedCustId(null));
dispatch(changeSelectedOption(null));
dispatch(ChangeOverAllDiscSales(0));
dispatch(ChangeOverAllDiscEstimate(0));
dispatch(Offer.changeSalesWiseOfferAmount(0));
dispatch(Offer.changeOverallOfferAmount(0));
dispatch(changeSummeryTotalAmount(0));
dispatch(Offer.changeOrderOfferDetail([]));
setFreeProductsCount(0);
dispatch(Offer.changeloyaltyPointsDiscountAmount(0));
dispatch(ChangeTotalAmount([]));
dispatch(ChangeFullFreeProductList([]));
dispatch(changeFullOfferAppliedProducts([]));
dispatch(changeBillEditingMode(false));
await dispatch(changePreviousOrderPayment([]));
await dispatch(changePreviousOrderOfferDetail([]));
dispatch(changeLoyaltyConsumedQuantities({}));
}
if (e == `${subDirectory}sales`) {
dispatch(changeTipAmount(0));
dispatch(changeSearchedData(''));
dispatch(changeBookingType('TakeAway'));
dispatch(changeOrderCardDetails([]));
dispatch(changeReorderHoldDetails({}));
dispatch(changeProductCategorie(null));
dispatch(changeCustomerID(null));
dispatch(changeSelectedCustId(null));
dispatch(changeSelectedOption(null));
dispatch(ChangeOverAllDiscSales(0));
dispatch(ChangeOverAllDiscEstimate(0));
dispatch(Offer.changeSalesWiseOfferAmount(0));
dispatch(Offer.changeOverallOfferAmount(0));
dispatch(changeSummeryTotalAmount(0));
dispatch(Offer.changeOrderOfferDetail([]));
setFreeProductsCount(0);
dispatch(Offer.changeloyaltyPointsDiscountAmount(0));
dispatch(Offer.changeCoupenCodeAmount(0));
dispatch(ChangeFullFreeProductList([]));
dispatch(changeFullOfferAppliedProducts([]));
dispatch(changeBillEditingMode(false));
await dispatch(changePreviousOrderPayment([]));
await dispatch(changePreviousOrderOfferDetail([]));
dispatch(ChangeTotalAmount([]));
dispatch(changeLoyaltyConsumedQuantities({}));
}
if (e == `${subDirectory}saleslayouts/print-selection`) {
dispatch(changeSelectedPrintdummyData(true));
}
navigate(e);
};
const handleMenuClick = (item, parentKeys = [], event, level = 0) => {
if (item.children) {
if (openKeys.includes(item.key)) {
setOpenKeys(openKeys.filter((k) => k !== item.key));
const newPositions = { ...dropdownPosition };
delete newPositions[item.key];
setDropdownPosition(newPositions);
} else {
// For top level (level 0), close all other open menus
// For nested levels, keep parent chain but close siblings
let newOpenKeys;
if (level === 0) {
// Close all other top-level menus
newOpenKeys = [];
} else {
// Keep only the parent chain, remove siblings
newOpenKeys = openKeys.filter((key) => {
// Keep if it's in the parent chain
return parentKeys.includes(key);
});
}
// Calculate position for dropdown
const rect = event.currentTarget.getBoundingClientRect();
let position;
if (level === 0) {
position = {
top: rect.top,
left: collapsed ? rect.right + 1 : 10,
};
} else {
position = {
top: rect.top,
left: rect.right + 1,
};
}
setDropdownPosition((prev) => ({ ...prev, [item.key]: position }));
setOpenKeys([...newOpenKeys, item.key]);
}
} else {
if (DineinDefault && item.key == `${subDirectory}sales`) {
navigatefun(`${subDirectory}sales/dine-in`);
setOpenKeys([]);
} else {
navigatefun(item.key);
setOpenKeys([]);
}
}
};
console.log(items, Access, 'Employee items');
// Filter menu items based on access
let filteredMenuItems = (items || []).filter(Boolean);
if (UserType === 'Employee' && Array.isArray(Access) && Access.length > 0) {
filteredMenuItems = filterMenuItems(filteredMenuItems, Access);
} else if (
UserType === 'Super Admin User' &&
Array.isArray(SadminuserAccess) &&
SadminuserAccess.length > 0
) {
filteredMenuItems = filterSadminUserMenuItems(
filteredMenuItems,
SadminuserAccess
);
}
// Capitalize all labels, filter out items without a label
const menuItemsWithCapitalizedLabels =
capitalizeMenuLabels(filteredMenuItems);
const bottomKeys = ['Support', 'Settings', 'Download', 'Sign Out'];
const bottomMenuItems = menuItemsWithCapitalizedLabels.filter((item) =>
bottomKeys.includes(item.label)
);
const mainMenuItems = menuItemsWithCapitalizedLabels.filter(
(item) => !bottomKeys.includes(item.label)
);
// Recursive render for menu and submenus
const renderMenuItems = (items, parentKeys = [], level = 0) => (
<div className={`side-menu-list${level > 0 ? ' nested-list' : ''}`}>
{(items || []).filter(Boolean).map((item) => (
<div key={item.key}>
<div
className={`${level > 0 ? 'dropdown-submenu-item' : 'menu-item'}${isSelected(item.key) || (level === 0 && hasSelectedChild(item)) ? ' selecteded' : ''}${isOpen(item.key) ? ' open' : ''}${item.children ? ' has-children' : ''}`}
onClick={(e) => {
e.stopPropagation();
handleMenuClick(item, parentKeys, e, level);
}}
// style={{ paddingLeft: `${level * 10 + 1}px` }}
>
{item.icon && level === 0 && (
<span
className="menu-icon"
style={{
fontSize: collapse ? '1.5rem' : '',
}}
>
{item.icon}
</span>
)}
{!collapse && <span className="menu-label">{item.label}</span>}
{!collapse && (
<span className="menu-labelDot">
{isDropdownItemSelected(item) ? '●' : ''}
</span>
)}
{item.children && !collapse && (
<span className="menu-arrow">
{level === 0 ? (
<FaCaretRight size={14} />
) : (
<MdOutlineKeyboardArrowRight />
)}
</span>
)}
</div>
{item.children && isOpen(item.key) && !collapse && (
<div className={`dropdown-submenu${level > 0 ? ' nested' : ''}`}>
{renderMenuItems(
item.children,
[...parentKeys, item.key],
level + 1
)}
</div>
)}
</div>
))}
</div>
);
// Custom onClick handler for PozoMenu
const handlePozoMenuClick = (e) => {
console.log('PozoMenu clicked:', e);
navigatefun(e.key);
};
// Get current selected key based on location
const getCurrentSelectedKey = () => {
return location.pathname;
};
const isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
const isAndroid = /Android/i.test(navigator.userAgent);
return (
<div
className={`SideMenuPozo-Master${collapse ? ' collapsed' : ''}`}
ref={menuRef}
style={{ height: isMobile ? '88%' : '' }}
>
<div
style={{
width: '100%',
display: 'flex',
flexDirection: 'column',
gap: '6px',
height: '68vh',
overflow: 'auto',
}}
>
<div className="paypreLogoDiv">
<div className="shopNameNav" style={{ width: '100%' }}>
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: '4px',
padding: '0px 10px',
justifyContent: 'space-between',
}}
>
<FiMenu
size={26}
onClick={() => setCollapse((prev) => !prev)}
style={{ cursor: 'pointer' }}
/>
{collapse ? (
''
) : (
// <img src={POZOMIND} alt="PozoMindLogo" width="80px" height={"45px"} className='PozoMindLogo' />
<div>PozoApp</div>
)}
</div>
{/* <div> */}
{/* <div>{branchName}</div> */}
<p>{/* {'Palacode'} , {'Tamilnadu'} , {'India'} */}</p>
{/* </div> */}
</div>
</div>
{/* Top Menu using PozoMenu */}
<div className="top-menu">
<PozoMenu
items={mainMenuItems}
mode="vertical"
collapse={collapse}
selectedKey={getCurrentSelectedKey()}
style={{
width: collapse ? '60px' : '200px',
background: 'transparent',
boxShadow: 'none',
}}
onClick={handlePozoMenuClick}
/>
</div>
</div>
{/* Bottom Menu using PozoMenu */}
<div
className="bottom-menu"
style={{
height: isMobile ? '30vh' : '',
}}
>
<PozoMenu
items={bottomMenuItems}
mode="vertical"
collapse={collapse}
selectedKey={getCurrentSelectedKey()}
isBottomMenu={true}
style={{
width: collapse ? '60px' : '200px',
background: 'transparent',
boxShadow: 'none',
}}
onClick={handlePozoMenuClick}
/>
</div>
</div>
);
};
export default SideMenuPozo;