import { useState, useEffect, useRef } from "react"; import AppBar from "@mui/material/AppBar"; import Toolbar from "@mui/material/Toolbar"; import Button from "@mui/material/Button"; import IconButton from "@mui/material/IconButton"; import Box from "@mui/material/Box"; import Header from "../Header"; import SearchIcon from "@mui/icons-material/Search"; import LocalMallIcon from '@mui/icons-material/LocalMall'; import AccountCircleIcon from "@mui/icons-material/AccountCircle"; import logoSrc from "../../assets/images/amberlogo.png"; import { styled } from '@mui/material/styles'; import { MenuItem, Select, FormControl, Badge, Typography } from '@mui/material'; import MobileNav from "./components/MobileNav"; import SideCart from "../SideCart/SideCart"; import MenuIcon from "@mui/icons-material/Menu"; import SearchProduct from "../SearchProduct" import CategoryIcon from '@mui/icons-material/Category'; import HomeIcon from '@mui/icons-material/Home'; import BrushIcon from '@mui/icons-material/Brush'; import LoyaltyIcon from '@mui/icons-material/Loyalty'; import Grid from '@mui/material/Grid2'; import { useSelector, useDispatch } from 'react-redux'; import { fetchProducts } from "../../redux/slices/productSlice"; import ProductService from "../../services/ProductService"; import { Swiper, SwiperSlide } from 'swiper/react'; import { Scrollbar, A11y, Navigation } from 'swiper/modules'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; function calculateTotalQuantity(cartItems) { return cartItems.reduce((total, item) => total + item.quantity, 0); } const LanguageSelect = styled(Select)(({ theme }) => ({ backgroundColor: 'black', color: 'white', border: '1px solid black', fontSize: 12, '& .MuiSelect-icon': { color: 'white', }, '&:hover': { backgroundColor: 'white', color: 'black', }, '& .MuiMenuItem-root': { backgroundColor: 'black', color: 'white', }, '& .MuiMenuItem-root:hover': { backgroundColor: 'white', color: 'black', }, })); const LanguageSelectItem = styled(MenuItem)(() => ({ backgroundColor: 'black', color: 'white', '&:hover': { backgroundColor: 'white', color: 'black', }, })); const COLLECTION_PRIORITY_BY_TYPE = { apparel: [ "EID'S TIME FOR LOVE COLLECTION", "ND X MARII FOR AMBER", "MIRAGE COLLECTION", "SOMEWHERE SOMEHOW SOMEONE", "OASIS ABAYA COLLECTION", "RAYA ROMANTICS COLLECTION 2025", "CASUAL WEAR", "AINA ABDUL MERCHANDISE", "ATMA SARI", "FLOWER POWER", "AMBER SCARVES FLOWER POWER SERIES", ], }; const normalizeTitle = (value = "") => value.trim().toUpperCase(); const getProductTypeMenuLabel = (productType = "") => { return normalizeTitle(productType) === "BEAUTY" ? "Essentials" : productType; }; const NAV_MENU_STRUCTURE = [ { productType: "Apparel", label: "APPAREL", groups: [ { label: "Casual", children: [ { label: "ND X Marii for Amber", titles: ["ND X MARII FOR AMBER"] }, { label: "Somewhere Somehow Someone", titles: ["SOMEWHERE SOMEHOW SOMEONE"] }, { label: "Flower Power", titles: ["FLOWER POWER"] }, ], }, { label: "Traditional", children: [ { label: "Eid's Time For Love", titles: ["EID'S TIME FOR LOVE"] }, { label: "Raya Romantics", titles: ["RAYA ROMANTICS COLLECTION 2025"] }, { label: "Atma Sari", titles: ["ATMA SARI"] }, { label: "Oasis abaya collection", titles: ["OASIS ABAYA COLLECTION", "MIRAGE COLLECTION"] }, ], }, ], }, { productType: "BEAUTY", label: "Essentials", children: [ { label: "Cosmetics", titles: ["COSMETICS"] }, { label: "Hand & Body Lotion", titles: ["HAND & BODY LOTION"] }, ], }, ]; const sortCollectionsByPriority = (collection = [], productType = "") => { const typeKey = (productType || "").trim().toLowerCase(); const priorityList = COLLECTION_PRIORITY_BY_TYPE[typeKey] || []; const priorityMap = new Map( priorityList.map((title, index) => [normalizeTitle(title), index]) ); return [...collection].sort((a, b) => { const aTitle = normalizeTitle(a?.title || ""); const bTitle = normalizeTitle(b?.title || ""); const aPriority = priorityMap.has(aTitle) ? priorityMap.get(aTitle) : Number.MAX_SAFE_INTEGER; const bPriority = priorityMap.has(bTitle) ? priorityMap.get(bTitle) : Number.MAX_SAFE_INTEGER; if (aPriority !== bPriority) { return aPriority - bPriority; } const aUpdatedAt = a?.updatedAt ? Date.parse(a.updatedAt) : 0; const bUpdatedAt = b?.updatedAt ? Date.parse(b.updatedAt) : 0; if (aUpdatedAt !== bUpdatedAt) { return bUpdatedAt - aUpdatedAt; } return aTitle.localeCompare(bTitle); }); }; function mapProductTypesWithCollections(products) { // Create a Map to group collections by productType const productTypeMap = new Map(); products.forEach(product => { const { productType, collections } = product; // If productType already exists, merge its collections if (productTypeMap.has(productType)) { const existingCollections = productTypeMap.get(productType); const newCollections = collections.map(collection => collection); productTypeMap.set(productType, [...new Set([...existingCollections, ...newCollections])]); } else { // Add a new productType with its collections productTypeMap.set(productType, collections.map(collection => collection)); } }); // Convert the Map into the desired array structure return Array.from(productTypeMap, ([productType, collection]) => ({ productType, collection })); } function getUniqueCollections(data) { return data.map(item => { // Use a Map to store unique collection titles with their corresponding image const uniqueCollectionsMap = new Map(); item.collection.forEach(({ title, image, updatedAt }) => { if (!uniqueCollectionsMap.has(title)) { uniqueCollectionsMap.set(title, { title, image, updatedAt }); } }); // Convert the Map back to an array return { productType: item.productType, collection: sortCollectionsByPriority( Array.from(uniqueCollectionsMap.values()), item.productType ) }; }); } const Navbar = () => { const swiperRef = useRef(null); // Create a ref for the Swiper instance const childTransitionTimerRef = useRef(null); const [showHeader, setShowHeader] = useState(true); const [showSearch, setShowSearch] = useState(false); const [isAtTop, setIsAtTop] = useState(false); const [isProductPage, setIsProductPage] = useState(false); const [lastScrollPos, setLastScrollPos] = useState(0); const [language, setLanguage] = useState('English'); const dispatch = useDispatch(); const cart = useSelector((state) => state.cart.cart) const products = useSelector((state) => state.products.products.data) const [cartAmount, setCartAmount] = useState(0); const [openSideMenu, setOpenSideMenu] = useState(false); const [openSideCart, setOpenSideCart] = useState(false); const [navItem, setNavItem] = useState([]); const [navItemCompanyInfo, setNavItemCompanyInfo] = useState([]); const [activeMenu, setActiveMenu] = useState(null); const [activeGroup, setActiveGroup] = useState(null); const [displayCollection, setDisplayCollection] = useState({ productType: null, list: [] }) useEffect(() => { dispatch(fetchProducts()) if (window.location.pathname === "/") setIsAtTop(true); const handleScroll = () => { if (window.location.pathname === "/") setIsAtTop(window.scrollY < 20); }; window.addEventListener("scroll", handleScroll); // Cleanup on component unmount return () => { window.removeEventListener("scroll", handleScroll); }; }, []) useEffect(() => { if (!cart?.lines?.nodes) return // don't need to do anything if we have no cart data setCartAmount(calculateTotalQuantity(cart?.lines?.nodes)) }, [cart]) useEffect(() => { //Navbar item are based on products type, thus get all the item and then we should be good if (products.length > 0) { let navItemData = mapProductTypesWithCollections(products) navItemData = getUniqueCollections(navItemData) navItemData = navItemData.filter(({ productType }) => normalizeTitle(productType) !== "HOME") setNavItem(navItemData) // extra info for the navbar setNavItemCompanyInfo([]); /* setNavItemCompanyInfo([{ name:"DELIVERY INFORMATION", link:"/delivery_info" }, { name:"SALE TERMS & CONDITIONS", link:"/sale_terms_and_condition" }, { name:"RETURNS & REFUNDS", link:"/return_and_exchange" }, { name:"CONTACT US", link:"/contact_us" }]); */ } }, [products]) const handleChange = (event) => { setLanguage(event.target.value); }; useEffect(() => { const handleScroll = () => { const currentScrollPos = window.scrollY; if (currentScrollPos > lastScrollPos && currentScrollPos > 50) setShowHeader(false) else setShowHeader(true) setLastScrollPos(currentScrollPos); }; window.addEventListener("scroll", handleScroll); return () => { window.removeEventListener("scroll", handleScroll); }; }, [lastScrollPos]); const renderCollectionDisplay = (colletion) => { return ( { sessionStorage.setItem('amber-select-collection', JSON.stringify(colletion)) sessionStorage.setItem('amber-select-product-type', displayCollection.productType) window.location.href = `/products`; }} > {colletion?.title?.toUpperCase()} ) } const swipeToLeft = () => { if (swiperRef.current) { swiperRef.current.slidePrev(); // Move to the previous slide } }; const swipeToRight = () => { if (swiperRef.current) { swiperRef.current.slideNext(); // Move to the previous slide } }; const displayCollectionList = (collection = [], productType) => { const sortedCollection = sortCollectionsByPriority(collection, productType); setDisplayCollection([]) setTimeout(() => { setDisplayCollection({ productType, list: sortedCollection }) }, 100); } const hideCollectionList = () => { setDisplayCollection([]) } const handleGroupMouseEnter = (groupLabel) => { if (activeGroup === groupLabel) return; if (childTransitionTimerRef.current) { clearTimeout(childTransitionTimerRef.current); } setActiveGroup(null); childTransitionTimerRef.current = setTimeout(() => { setActiveGroup(groupLabel); }, 40); } const navigateToMenuItem = (productType, item = null) => { sessionStorage.setItem('amber-select-product-type', productType) sessionStorage.removeItem('amber-select-collection') sessionStorage.removeItem('amber-select-collections') if (item) { sessionStorage.setItem('amber-select-collection', JSON.stringify({ title: item.label, image: null })) sessionStorage.setItem('amber-select-collections', JSON.stringify(item.titles || [])) } window.location.href = `/products`; } return ( <> { hideCollectionList() setActiveMenu(null) setActiveGroup(null) }} > {/* Conditionally render the Header */} {showHeader &&
} {/* SIDEBAR BUTTON */} setOpenSideMenu(true)} className="navItem" sx={{ backgroundColor: "transparent", color: (isAtTop) ? "white" : "black", "&:hover": { backgroundColor: "rgba(0, 0, 0, 0.1)", }, }} > {/* Left Section: Logo */} Logo {/* Center Section: Nav Items */} {NAV_MENU_STRUCTURE.map((menu) => ( { if (childTransitionTimerRef.current) { clearTimeout(childTransitionTimerRef.current); } setActiveMenu(menu.label); setActiveGroup(null); }} > {( <> {menu.groups ? ( <> {menu.groups.map((group) => ( ))} {activeGroup && ( {menu.groups .find((group) => group.label === activeGroup) ?.children.map((item) => ( ))} )} ) : ( {menu.children.map((item) => ( ))} )} )} ))} {/* {navItem.map(({ productType, collection }) => ())} {navItemCompanyInfo.map(({ name, link }) => ())} */} {/* Right Section: Search and Profile */} {/* English Malay Chinese */} { setShowSearch(true) }}> { setOpenSideCart(true) }} badgeContent={cartAmount} color="primary"> {/* */} {/* On Hover Collection */} 0) ? "block" : "none" }}> (swiperRef.current = swiper)} > {displayCollection?.list?.map((colletion) => { return renderCollectionDisplay(colletion) })} {showSearch && { setShowSearch(false) }} />} { setOpenSideMenu(false) }} /> { setOpenSideCart(false) }} /> ); }; export default Navbar;