Amber Shopify Project created using ReactJS+React-Redux with GraphQL API integration. Storefront Shopify API: https://github.com/Shopify/shopify-app-js/tree/main/packages/api-clients/storefront-api-client#readme
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. import { useState, useEffect, useRef } from "react";
  2. import AppBar from "@mui/material/AppBar";
  3. import Toolbar from "@mui/material/Toolbar";
  4. import Button from "@mui/material/Button";
  5. import IconButton from "@mui/material/IconButton";
  6. import Box from "@mui/material/Box";
  7. import Header from "../Header";
  8. import SearchIcon from "@mui/icons-material/Search";
  9. import LocalMallIcon from '@mui/icons-material/LocalMall';
  10. import AccountCircleIcon from "@mui/icons-material/AccountCircle";
  11. import logoSrc from "../../assets/images/amberlogo.png";
  12. import { styled } from '@mui/material/styles';
  13. import { MenuItem, Select, FormControl, Badge, Typography } from '@mui/material';
  14. import MobileNav from "./components/MobileNav";
  15. import SideCart from "../SideCart/SideCart";
  16. import MenuIcon from "@mui/icons-material/Menu";
  17. import SearchProduct from "../SearchProduct"
  18. import CategoryIcon from '@mui/icons-material/Category';
  19. import HomeIcon from '@mui/icons-material/Home';
  20. import BrushIcon from '@mui/icons-material/Brush';
  21. import LoyaltyIcon from '@mui/icons-material/Loyalty';
  22. import Grid from '@mui/material/Grid2';
  23. import { useSelector, useDispatch } from 'react-redux';
  24. import { fetchProducts } from "../../redux/slices/productSlice";
  25. import ProductService from "../../services/ProductService";
  26. import { Swiper, SwiperSlide } from 'swiper/react';
  27. import { Scrollbar, A11y, Navigation } from 'swiper/modules';
  28. import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
  29. import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
  30. function calculateTotalQuantity(cartItems) {
  31. return cartItems.reduce((total, item) => total + item.quantity, 0);
  32. }
  33. const LanguageSelect = styled(Select)(({ theme }) => ({
  34. backgroundColor: 'black',
  35. color: 'white',
  36. border: '1px solid black',
  37. fontSize: 12,
  38. '& .MuiSelect-icon': {
  39. color: 'white',
  40. },
  41. '&:hover': {
  42. backgroundColor: 'white',
  43. color: 'black',
  44. },
  45. '& .MuiMenuItem-root': {
  46. backgroundColor: 'black',
  47. color: 'white',
  48. },
  49. '& .MuiMenuItem-root:hover': {
  50. backgroundColor: 'white',
  51. color: 'black',
  52. },
  53. }));
  54. const LanguageSelectItem = styled(MenuItem)(() => ({
  55. backgroundColor: 'black',
  56. color: 'white',
  57. '&:hover': {
  58. backgroundColor: 'white',
  59. color: 'black',
  60. },
  61. }));
  62. const COLLECTION_PRIORITY_BY_TYPE = {
  63. apparel: [
  64. "EID'S TIME FOR LOVE COLLECTION",
  65. "ND X MARII FOR AMBER",
  66. "MIRAGE COLLECTION",
  67. "SOMEWHERE SOMEHOW SOMEONE",
  68. "OASIS ABAYA COLLECTION",
  69. "RAYA ROMANTICS COLLECTION 2025",
  70. "CASUAL WEAR",
  71. "AINA ABDUL MERCHANDISE",
  72. "ATMA SARI",
  73. "FLOWER POWER",
  74. "AMBER SCARVES FLOWER POWER SERIES",
  75. ],
  76. };
  77. const normalizeTitle = (value = "") => value.trim().toUpperCase();
  78. const getProductTypeMenuLabel = (productType = "") => {
  79. return normalizeTitle(productType) === "BEAUTY" ? "Essentials" : productType;
  80. };
  81. const NAV_MENU_STRUCTURE = [
  82. {
  83. productType: "Apparel",
  84. label: "APPAREL",
  85. groups: [
  86. {
  87. label: "Casual",
  88. children: [
  89. { label: "ND X Marii for Amber", titles: ["ND X MARII FOR AMBER"] },
  90. { label: "Somewhere Somehow Someone", titles: ["SOMEWHERE SOMEHOW SOMEONE"] },
  91. { label: "Flower Power", titles: ["FLOWER POWER"] },
  92. ],
  93. },
  94. {
  95. label: "Traditional",
  96. children: [
  97. { label: "Eid's Time For Love", titles: ["EID'S TIME FOR LOVE"] },
  98. { label: "Raya Romantics", titles: ["RAYA ROMANTICS COLLECTION 2025"] },
  99. { label: "Atma Sari", titles: ["ATMA SARI"] },
  100. { label: "Oasis abaya collection", titles: ["OASIS ABAYA COLLECTION", "MIRAGE COLLECTION"] },
  101. ],
  102. },
  103. ],
  104. },
  105. {
  106. productType: "BEAUTY",
  107. label: "Essentials",
  108. children: [
  109. { label: "Cosmetics", titles: ["COSMETICS"] },
  110. { label: "Hand & Body Lotion", titles: ["HAND & BODY LOTION"] },
  111. ],
  112. },
  113. ];
  114. const sortCollectionsByPriority = (collection = [], productType = "") => {
  115. const typeKey = (productType || "").trim().toLowerCase();
  116. const priorityList = COLLECTION_PRIORITY_BY_TYPE[typeKey] || [];
  117. const priorityMap = new Map(
  118. priorityList.map((title, index) => [normalizeTitle(title), index])
  119. );
  120. return [...collection].sort((a, b) => {
  121. const aTitle = normalizeTitle(a?.title || "");
  122. const bTitle = normalizeTitle(b?.title || "");
  123. const aPriority = priorityMap.has(aTitle)
  124. ? priorityMap.get(aTitle)
  125. : Number.MAX_SAFE_INTEGER;
  126. const bPriority = priorityMap.has(bTitle)
  127. ? priorityMap.get(bTitle)
  128. : Number.MAX_SAFE_INTEGER;
  129. if (aPriority !== bPriority) {
  130. return aPriority - bPriority;
  131. }
  132. const aUpdatedAt = a?.updatedAt ? Date.parse(a.updatedAt) : 0;
  133. const bUpdatedAt = b?.updatedAt ? Date.parse(b.updatedAt) : 0;
  134. if (aUpdatedAt !== bUpdatedAt) {
  135. return bUpdatedAt - aUpdatedAt;
  136. }
  137. return aTitle.localeCompare(bTitle);
  138. });
  139. };
  140. function mapProductTypesWithCollections(products) {
  141. // Create a Map to group collections by productType
  142. const productTypeMap = new Map();
  143. products.forEach(product => {
  144. const { productType, collections } = product;
  145. // If productType already exists, merge its collections
  146. if (productTypeMap.has(productType)) {
  147. const existingCollections = productTypeMap.get(productType);
  148. const newCollections = collections.map(collection => collection);
  149. productTypeMap.set(productType, [...new Set([...existingCollections, ...newCollections])]);
  150. } else {
  151. // Add a new productType with its collections
  152. productTypeMap.set(productType, collections.map(collection => collection));
  153. }
  154. });
  155. // Convert the Map into the desired array structure
  156. return Array.from(productTypeMap, ([productType, collection]) => ({ productType, collection }));
  157. }
  158. function getUniqueCollections(data) {
  159. return data.map(item => {
  160. // Use a Map to store unique collection titles with their corresponding image
  161. const uniqueCollectionsMap = new Map();
  162. item.collection.forEach(({ title, image, updatedAt }) => {
  163. if (!uniqueCollectionsMap.has(title)) {
  164. uniqueCollectionsMap.set(title, { title, image, updatedAt });
  165. }
  166. });
  167. // Convert the Map back to an array
  168. return {
  169. productType: item.productType,
  170. collection: sortCollectionsByPriority(
  171. Array.from(uniqueCollectionsMap.values()),
  172. item.productType
  173. )
  174. };
  175. });
  176. }
  177. const Navbar = () => {
  178. const swiperRef = useRef(null); // Create a ref for the Swiper instance
  179. const childTransitionTimerRef = useRef(null);
  180. const [showHeader, setShowHeader] = useState(true);
  181. const [showSearch, setShowSearch] = useState(false);
  182. const [isAtTop, setIsAtTop] = useState(false);
  183. const [isProductPage, setIsProductPage] = useState(false);
  184. const [lastScrollPos, setLastScrollPos] = useState(0);
  185. const [language, setLanguage] = useState('English');
  186. const dispatch = useDispatch();
  187. const cart = useSelector((state) => state.cart.cart)
  188. const products = useSelector((state) => state.products.products.data)
  189. const [cartAmount, setCartAmount] = useState(0);
  190. const [openSideMenu, setOpenSideMenu] = useState(false);
  191. const [openSideCart, setOpenSideCart] = useState(false);
  192. const [navItem, setNavItem] = useState([]);
  193. const [navItemCompanyInfo, setNavItemCompanyInfo] = useState([]);
  194. const [activeMenu, setActiveMenu] = useState(null);
  195. const [activeGroup, setActiveGroup] = useState(null);
  196. const [displayCollection, setDisplayCollection] = useState({
  197. productType: null,
  198. list: []
  199. })
  200. useEffect(() => {
  201. dispatch(fetchProducts())
  202. if (window.location.pathname === "/") setIsAtTop(true);
  203. const handleScroll = () => {
  204. if (window.location.pathname === "/") setIsAtTop(window.scrollY < 20);
  205. };
  206. window.addEventListener("scroll", handleScroll);
  207. // Cleanup on component unmount
  208. return () => {
  209. window.removeEventListener("scroll", handleScroll);
  210. };
  211. }, [])
  212. useEffect(() => {
  213. if (!cart?.lines?.nodes) return // don't need to do anything if we have no cart data
  214. setCartAmount(calculateTotalQuantity(cart?.lines?.nodes))
  215. }, [cart])
  216. useEffect(() => {
  217. //Navbar item are based on products type, thus get all the item and then we should be good
  218. if (products.length > 0) {
  219. let navItemData = mapProductTypesWithCollections(products)
  220. navItemData = getUniqueCollections(navItemData)
  221. navItemData = navItemData.filter(({ productType }) => normalizeTitle(productType) !== "HOME")
  222. setNavItem(navItemData)
  223. // extra info for the navbar
  224. setNavItemCompanyInfo([]);
  225. /*
  226. setNavItemCompanyInfo([{
  227. name:"DELIVERY INFORMATION",
  228. link:"/delivery_info"
  229. },
  230. {
  231. name:"SALE TERMS & CONDITIONS",
  232. link:"/sale_terms_and_condition"
  233. },
  234. {
  235. name:"RETURNS & REFUNDS",
  236. link:"/return_and_exchange"
  237. },
  238. {
  239. name:"CONTACT US",
  240. link:"/contact_us"
  241. }]);
  242. */
  243. }
  244. }, [products])
  245. const handleChange = (event) => {
  246. setLanguage(event.target.value);
  247. };
  248. useEffect(() => {
  249. const handleScroll = () => {
  250. const currentScrollPos = window.scrollY;
  251. if (currentScrollPos > lastScrollPos && currentScrollPos > 50) setShowHeader(false)
  252. else setShowHeader(true)
  253. setLastScrollPos(currentScrollPos);
  254. };
  255. window.addEventListener("scroll", handleScroll);
  256. return () => {
  257. window.removeEventListener("scroll", handleScroll);
  258. };
  259. }, [lastScrollPos]);
  260. const renderCollectionDisplay = (colletion) => {
  261. return (
  262. <SwiperSlide>
  263. <Box
  264. className="animate__animated animate__fadeIn animate__fast"
  265. sx={{
  266. backgroundImage: `url(${colletion?.image?.url})`,
  267. backgroundSize: "cover",
  268. backgroundRepeat: "no-repeat",
  269. backgroundPosition: "center center",
  270. height: "100%",
  271. paddingTop: "85%",
  272. position: "relative",
  273. cursor: "pointer",
  274. transition: "transform 0.3s ease",
  275. }}
  276. onClick={() => {
  277. sessionStorage.setItem('amber-select-collection', JSON.stringify(colletion))
  278. sessionStorage.setItem('amber-select-product-type', displayCollection.productType)
  279. window.location.href = `/products`;
  280. }}
  281. ></Box>
  282. <Typography
  283. variant="body1"
  284. sx={{
  285. mt:1,
  286. color: "black",
  287. fontWeight: "100",
  288. fontSize: {
  289. xs: "0.73rem",
  290. sm: "0.73rem",
  291. md: "0.875rem",
  292. },
  293. }}
  294. >
  295. {colletion?.title?.toUpperCase()}
  296. </Typography>
  297. </SwiperSlide>
  298. )
  299. }
  300. const swipeToLeft = () => {
  301. if (swiperRef.current) {
  302. swiperRef.current.slidePrev(); // Move to the previous slide
  303. }
  304. };
  305. const swipeToRight = () => {
  306. if (swiperRef.current) {
  307. swiperRef.current.slideNext(); // Move to the previous slide
  308. }
  309. };
  310. const displayCollectionList = (collection = [], productType) => {
  311. const sortedCollection = sortCollectionsByPriority(collection, productType);
  312. setDisplayCollection([])
  313. setTimeout(() => {
  314. setDisplayCollection({
  315. productType,
  316. list: sortedCollection
  317. })
  318. }, 100);
  319. }
  320. const hideCollectionList = () => {
  321. setDisplayCollection([])
  322. }
  323. const handleGroupMouseEnter = (groupLabel) => {
  324. if (activeGroup === groupLabel) return;
  325. if (childTransitionTimerRef.current) {
  326. clearTimeout(childTransitionTimerRef.current);
  327. }
  328. setActiveGroup(null);
  329. childTransitionTimerRef.current = setTimeout(() => {
  330. setActiveGroup(groupLabel);
  331. }, 40);
  332. }
  333. const navigateToMenuItem = (productType, item = null) => {
  334. sessionStorage.setItem('amber-select-product-type', productType)
  335. sessionStorage.removeItem('amber-select-collection')
  336. sessionStorage.removeItem('amber-select-collections')
  337. if (item) {
  338. sessionStorage.setItem('amber-select-collection', JSON.stringify({
  339. title: item.label,
  340. image: null
  341. }))
  342. sessionStorage.setItem('amber-select-collections', JSON.stringify(item.titles || []))
  343. }
  344. window.location.href = `/products`;
  345. }
  346. return (
  347. <>
  348. <AppBar position="fixed"
  349. sx={{
  350. zIndex: 998,
  351. backgroundColor: (isAtTop) ? "rgba(0, 0, 0, 0)" : "rgba(255, 255, 255, 0.3)",
  352. backdropFilter: (isAtTop) ? "none" : "blur(10px)",
  353. boxShadow: 0,
  354. transition: "all 0.2s ease-in-out",
  355. ":hover": {
  356. backgroundColor: "rgba(255,255,255,1) !important",
  357. backdropFilter: "none !important",
  358. '& .navItem': {
  359. color: "black !important"
  360. },
  361. '& .navItem:hover': {
  362. color: "#95AAC5 !important"
  363. },
  364. }
  365. }}
  366. onMouseLeave={() => {
  367. hideCollectionList()
  368. setActiveMenu(null)
  369. setActiveGroup(null)
  370. }}
  371. >
  372. {/* Conditionally render the Header */}
  373. {showHeader && <Header />}
  374. <Toolbar sx={{
  375. px: {
  376. xs: 2,
  377. md: 6,
  378. lg: 6
  379. },
  380. py: 0.5
  381. }} disableGutters>
  382. <Box sx={{ display: "flex", alignItems: "center", width: "100%", position: "relative", justifyContent: "space-between" }}>
  383. {/* SIDEBAR BUTTON */}
  384. <Box sx={{
  385. display: {
  386. xs: "block",
  387. md: "block",
  388. lg: "none"
  389. }
  390. }}>
  391. <IconButton
  392. onClick={() => setOpenSideMenu(true)}
  393. className="navItem"
  394. sx={{
  395. backgroundColor: "transparent",
  396. color: (isAtTop) ? "white" : "black",
  397. "&:hover": {
  398. backgroundColor: "rgba(0, 0, 0, 0.1)",
  399. },
  400. }}
  401. >
  402. <MenuIcon fontSize="large" />
  403. </IconButton>
  404. </Box>
  405. {/* Left Section: Logo */}
  406. <Box
  407. sx={{
  408. mr: {
  409. xs: 0,
  410. sm: 0,
  411. md: 10,
  412. lg: 10,
  413. xl: 10
  414. },
  415. display: {
  416. xs: (isProductPage) ? "flex" : "none",
  417. md: (isProductPage) ? "flex" : "none",
  418. lg: "flex"
  419. },
  420. }}
  421. >
  422. <a href="/">
  423. <img src={logoSrc} alt="Logo"
  424. style={{
  425. width: 130,
  426. height: 20,
  427. }} />
  428. </a>
  429. </Box>
  430. {/* Center Section: Nav Items */}
  431. <Box
  432. sx={{
  433. flexGrow: 1,
  434. display: {
  435. xs: "none",
  436. md: "none",
  437. lg: "flex"
  438. },
  439. gap: 2
  440. }}
  441. >
  442. {NAV_MENU_STRUCTURE.map((menu) => (
  443. <Box
  444. key={menu.label}
  445. sx={{ position: "relative" }}
  446. onMouseEnter={() => {
  447. if (childTransitionTimerRef.current) {
  448. clearTimeout(childTransitionTimerRef.current);
  449. }
  450. setActiveMenu(menu.label);
  451. setActiveGroup(null);
  452. }}
  453. >
  454. <Button
  455. sx={{
  456. position: "relative",
  457. ':hover': {
  458. backgroundColor: "rgba(0,0,0,0)",
  459. }
  460. }}
  461. color="inherit"
  462. onClick={() => {
  463. if (!menu.groups && !menu.children) {
  464. navigateToMenuItem(menu.productType)
  465. }
  466. }}
  467. >
  468. <Typography variant="body2"
  469. className="navItem"
  470. sx={{
  471. fontSize: {
  472. xs: "0.73rem",
  473. sm: "0.73rem",
  474. md: "0.875rem",
  475. },
  476. color: (isAtTop) ? "white" : "black",
  477. transition: "all 0.3s ease-in-out",
  478. ":hover": {
  479. color: "#95AAC5 !important"
  480. },
  481. "&::after": {
  482. content: '""',
  483. position: "absolute",
  484. left: "50%",
  485. transform: "translateX(-50%)",
  486. bottom: 2,
  487. width: activeMenu === menu.label ? "70%" : "0%",
  488. height: "2px",
  489. backgroundColor: "#95AAC5",
  490. transition: "width 0.3s ease-in-out",
  491. },
  492. ":hover::after": {
  493. width: "70%",
  494. },
  495. }}>{menu.label}</Typography>
  496. </Button>
  497. {(
  498. <>
  499. <Box
  500. sx={{
  501. position: "absolute",
  502. top: "100%",
  503. left: 0,
  504. width: menu.groups ? (activeGroup ? 560 : 260) : 260,
  505. height: 28,
  506. zIndex: 1000,
  507. backgroundColor: "transparent",
  508. visibility: activeMenu === menu.label ? "visible" : "hidden",
  509. pointerEvents: activeMenu === menu.label ? "auto" : "none",
  510. }}
  511. />
  512. <Box
  513. sx={{
  514. position: "absolute",
  515. top: 60,
  516. left: 0,
  517. width: menu.groups ? (activeGroup ? 560 : 260) : 260,
  518. backgroundColor: "#FFF",
  519. color: "#000",
  520. border: "1px solid rgba(0,0,0,0.08)",
  521. borderTop: 0,
  522. boxShadow: "0 2px 6px rgba(0,0,0,0.12)",
  523. display: "flex",
  524. minHeight: "auto",
  525. zIndex: 1001,
  526. overflow: "hidden",
  527. opacity: activeMenu === menu.label ? 1 : 0,
  528. visibility: activeMenu === menu.label ? "visible" : "hidden",
  529. pointerEvents: activeMenu === menu.label ? "auto" : "none",
  530. clipPath: activeMenu === menu.label ? "polygon(0 0, 100% 0, 100% 100%, 0 100%)" : "polygon(0 0, 100% 0, 100% 0, 0 0)",
  531. transition: activeGroup ? "clip-path .45s ease-in-out, visibility .45s ease-in-out, opacity .45s ease-in-out, width .55s ease-in-out" : "clip-path .45s ease-in-out, visibility .45s ease-in-out, opacity .45s ease-in-out",
  532. }}
  533. >
  534. {menu.groups ? (
  535. <>
  536. <Box sx={{ width: 260, pb: 1.5, borderRight: "1px solid rgba(0,0,0,0.12)" }}>
  537. {menu.groups.map((group) => (
  538. <Button
  539. key={group.label}
  540. fullWidth
  541. onMouseEnter={() => handleGroupMouseEnter(group.label)}
  542. sx={{
  543. justifyContent: "space-between",
  544. color: activeGroup === group.label ? "#95AAC5" : "#000",
  545. textTransform: "none",
  546. fontSize: "0.875rem",
  547. py: 1.5,
  548. px: 3,
  549. '&:hover': {
  550. backgroundColor: "transparent",
  551. color: "#95AAC5",
  552. }
  553. }}
  554. >
  555. {group.label?.toUpperCase()}
  556. <KeyboardArrowRightIcon sx={{ fontSize: 20 }} />
  557. </Button>
  558. ))}
  559. </Box>
  560. {activeGroup && (
  561. <Box key={activeGroup} sx={{
  562. pb: 1.5,
  563. px: 3,
  564. width: 300,
  565. clipPath: "polygon(0 0, 100% 0, 100% 100%, 0 100%)",
  566. overflow: "hidden",
  567. position: "relative",
  568. animation: "childCardReveal .55s ease-in-out",
  569. "@keyframes childCardReveal": {
  570. "0%": {
  571. clipPath: "polygon(0 0, 0 0, 0 100%, 0 100%)",
  572. },
  573. "100%": {
  574. clipPath: "polygon(0 0, 100% 0, 100% 100%, 0 100%)",
  575. },
  576. },
  577. }}>
  578. {menu.groups
  579. .find((group) => group.label === activeGroup)
  580. ?.children.map((item) => (
  581. <Button
  582. key={item.label}
  583. fullWidth
  584. onClick={() => navigateToMenuItem(menu.productType, item)}
  585. sx={{
  586. justifyContent: "flex-start",
  587. color: "#000",
  588. textTransform: "none",
  589. fontSize: "0.875rem",
  590. py: 1.1,
  591. px: 0,
  592. '&:hover': {
  593. backgroundColor: "transparent",
  594. color: "#95AAC5",
  595. }
  596. }}
  597. >
  598. {item.label?.toUpperCase()}
  599. </Button>
  600. ))}
  601. </Box>
  602. )}
  603. </>
  604. ) : (
  605. <Box sx={{ pb: 1.5, px: 3, width: 260 }}>
  606. {menu.children.map((item) => (
  607. <Button
  608. key={item.label}
  609. fullWidth
  610. onClick={() => navigateToMenuItem(menu.productType, item)}
  611. sx={{
  612. justifyContent: "flex-start",
  613. color: "#000",
  614. textTransform: "none",
  615. fontSize: "0.875rem",
  616. py: 1.1,
  617. px: 0,
  618. '&:hover': {
  619. backgroundColor: "transparent",
  620. color: "#95AAC5",
  621. }
  622. }}
  623. >
  624. {item.label?.toUpperCase()}
  625. </Button>
  626. ))}
  627. </Box>
  628. )}
  629. </Box>
  630. </>
  631. )}
  632. </Box>
  633. ))}
  634. {/*
  635. {navItem.map(({ productType, collection }) => (<Button
  636. sx={{
  637. position: "relative",
  638. ':hover': {
  639. backgroundColor: "rgba(0,0,0,0)",
  640. }
  641. }}
  642. color="inherit"
  643. onClick={() => {
  644. sessionStorage.setItem('amber-select-product-type', productType)
  645. sessionStorage.removeItem('amber-select-collection')
  646. window.location.href = `/products`;
  647. }}
  648. onMouseEnter={() => {
  649. displayCollectionList(collection, productType)
  650. }}
  651. >
  652. <Typography variant="body2"
  653. className="navItem"
  654. sx={{
  655. fontSize: {
  656. xs: "0.73rem",
  657. sm: "0.73rem",
  658. md: "0.875rem",
  659. },
  660. color: (isAtTop) ? "white" : "black",
  661. transition: "all 0.3s ease-in-out",
  662. ":hover": {
  663. color: "#95AAC5 !important"
  664. },
  665. "&::after": {
  666. content: '""',
  667. position: "absolute",
  668. left: "50%",
  669. transform: "translateX(-50%)",
  670. bottom: 2,
  671. width: "0%",
  672. height: "2px",
  673. backgroundColor: "#95AAC5",
  674. transition: "width 0.3s ease-in-out",
  675. },
  676. ":hover::after": {
  677. width: "50%",
  678. },
  679. }}>{getProductTypeMenuLabel(productType)}</Typography>
  680. </Button>))}
  681. {navItemCompanyInfo.map(({ name, link }) => (<Button
  682. sx={{
  683. position: "relative",
  684. ':hover': {
  685. backgroundColor: "rgba(0,0,0,0)",
  686. }
  687. }}
  688. color="inherit"
  689. onClick={() => {
  690. window.location.href = `${link}`;
  691. }}
  692. >
  693. <Typography variant="body2"
  694. className="navItem"
  695. sx={{
  696. fontSize: {
  697. xs: "0.73rem",
  698. sm: "0.73rem",
  699. md: "0.875rem",
  700. },
  701. color: (isAtTop) ? "white" : "black",
  702. transition: "all 0.3s ease-in-out",
  703. ":hover": {
  704. color: "#95AAC5 !important"
  705. },
  706. "&::after": {
  707. content: '""',
  708. position: "absolute",
  709. left: "50%",
  710. transform: "translateX(-50%)",
  711. bottom: 2,
  712. width: "0%",
  713. height: "2px",
  714. backgroundColor: "#95AAC5",
  715. transition: "width 0.3s ease-in-out",
  716. },
  717. ":hover::after": {
  718. width: "70%",
  719. },
  720. }}>{name}</Typography>
  721. </Button>))}
  722. */}
  723. </Box>
  724. {/* Right Section: Search and Profile */}
  725. <Box sx={{ display: "flex", alignItems: "center", gap: 1.2 }}>
  726. {/* <FormControl
  727. sx={{
  728. display: {
  729. xs: "none",
  730. lg: "block"
  731. }
  732. }}
  733. >
  734. <LanguageSelect
  735. value={language}
  736. onChange={handleChange}
  737. label=""
  738. MenuProps={{
  739. PaperProps: {
  740. style: {
  741. backgroundColor: 'black',
  742. color: 'white'
  743. },
  744. },
  745. }}
  746. >
  747. <LanguageSelectItem value="English">English</LanguageSelectItem>
  748. <LanguageSelectItem value="Malay">Malay</LanguageSelectItem>
  749. <LanguageSelectItem value="Chinese">Chinese</LanguageSelectItem>
  750. </LanguageSelect>
  751. </FormControl> */}
  752. <IconButton onClick={() => { setShowSearch(true) }}>
  753. <SearchIcon className="navItem" style={{
  754. transition: "all 0.3s ease-in-out",
  755. color: (isAtTop) ? "white" : "black",
  756. }} />
  757. </IconButton>
  758. <Badge
  759. sx={{ cursor: "pointer" }}
  760. onClick={() => { setOpenSideCart(true) }}
  761. badgeContent={cartAmount} color="primary">
  762. <LocalMallIcon className="navItem" style={{
  763. transition: "all 0.3s ease-in-out",
  764. color: (isAtTop) ? "white" : "black",
  765. }} />
  766. </Badge>
  767. {/* <IconButton color="inherit">
  768. <AccountCircleIcon sx={{ color: "white" }} />
  769. </IconButton> */}
  770. </Box>
  771. </Box>
  772. </Toolbar>
  773. {/* On Hover Collection */}
  774. <Box className="animate__animated animate__fadeIn" sx={{ backgroundColor: "white", position: "relative", py: 5, display: (displayCollection?.list?.length > 0) ? "block" : "none" }}>
  775. <ChevronLeftIcon
  776. style={{
  777. cursor: "pointer",
  778. color: "black",
  779. position: "absolute",
  780. top: "50%",
  781. fontSize: 50,
  782. left: 40,
  783. transform: "translateY(-50%)",
  784. }}
  785. onClick={swipeToLeft}
  786. />
  787. <Box sx={{ px: 20 }}>
  788. <Swiper
  789. modules={[Navigation, Scrollbar, A11y]}
  790. spaceBetween={20}
  791. slidesPerView={4}
  792. pagination={{ clickable: true }}
  793. scrollbar={{ draggable: true }}
  794. onSwiper={(swiper) => (swiperRef.current = swiper)}
  795. >
  796. {displayCollection?.list?.map((colletion) => {
  797. return renderCollectionDisplay(colletion)
  798. })}
  799. </Swiper>
  800. </Box>
  801. <KeyboardArrowRightIcon
  802. style={{
  803. cursor: "pointer",
  804. color: "black",
  805. fontSize: 50,
  806. position: "absolute",
  807. top: "50%",
  808. right: 40,
  809. transform: "translateY(-50%)",
  810. }}
  811. onClick={swipeToRight}
  812. />
  813. </Box>
  814. </AppBar>
  815. {showSearch && <SearchProduct onClose={() => { setShowSearch(false) }} />}
  816. <MobileNav open={openSideMenu} menu={NAV_MENU_STRUCTURE} infomenu={navItemCompanyInfo} onClose={() => { setOpenSideMenu(false) }} />
  817. <SideCart open={openSideCart} onClose={() => { setOpenSideCart(false) }} />
  818. </>
  819. );
  820. };
  821. export default Navbar;