| @@ -18,6 +18,7 @@ const Hero = () => { | |||
| > | |||
| <Box | |||
| sx={{ | |||
| minWidth: '50%', | |||
| width: { xs: '100%', md: '50%' }, | |||
| height: '100%', | |||
| display: 'flex', | |||
| @@ -76,6 +77,7 @@ const Hero = () => { | |||
| }} | |||
| > | |||
| <Button | |||
| disableRipple | |||
| sx={{ | |||
| backgroundColor: '#CBA213', | |||
| mr: { md: 4 }, | |||
| @@ -90,6 +92,7 @@ const Hero = () => { | |||
| Explore the Shop | |||
| </Button> | |||
| <Button | |||
| disableRipple | |||
| sx={{ | |||
| display: { xs: 'none', sm: 'flex' }, | |||
| textTransform: 'none', | |||
| @@ -114,7 +117,12 @@ const Hero = () => { | |||
| backgroundColor: 'white', | |||
| }} | |||
| > | |||
| <Box sx={{ mt: 10, ml: -12 }}> | |||
| <Box | |||
| sx={{ ml: { md: -12 } }} | |||
| display="flex" | |||
| justifyContent="center" | |||
| alignItems="center" | |||
| > | |||
| <Image | |||
| src="/images/Hero-Image.png" | |||
| alt="profile" | |||
| @@ -1,12 +1,13 @@ | |||
| import { Box } from '@mui/material'; | |||
| import Footer from '../footer/Footer'; | |||
| import Navbar from '../navbar/Navbar'; | |||
| import MainNav from '../navbar/MainNav'; | |||
| function Layout(props) { | |||
| return ( | |||
| <> | |||
| <Box sx={{ width: '100%' }}> | |||
| <Navbar /> | |||
| {/* <Navbar /> */} | |||
| <MainNav /> | |||
| <main>{props.children}</main> | |||
| <Footer></Footer> | |||
| </Box> | |||
| @@ -0,0 +1,110 @@ | |||
| import Box from '@mui/material/Box'; | |||
| import Image from 'next/image'; | |||
| import Link from 'next/link'; | |||
| import { CART_PAGE, PROFILE_PAGE } from '../../../constants/pages'; | |||
| import { NavItemDesktop } from './NavItem'; | |||
| import { items } from './navItems'; | |||
| const DesktopNav = ({ router, totalQuantity, session, signOutHandler }) => { | |||
| return ( | |||
| <Box sx={{ display: { xs: 'none', md: 'flex' }, width: '100%' }}> | |||
| <Box | |||
| sx={{ | |||
| flexGrow: 1, | |||
| maxWidth: '50%', | |||
| height: 30, | |||
| display: 'flex', | |||
| justifyContent: 'space-between', | |||
| }} | |||
| > | |||
| {items.map((item) => ( | |||
| <NavItemDesktop | |||
| key={item.id} | |||
| router={router} | |||
| name={item.name} | |||
| url={item.url} | |||
| /> | |||
| ))} | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| flexGrow: 1, | |||
| maxWidth: '50%', | |||
| height: 30, | |||
| display: 'flex', | |||
| justifyContent: 'right', | |||
| pt: 0.5, | |||
| mr: 4, | |||
| }} | |||
| > | |||
| {session?.user?._id && ( | |||
| <Box | |||
| sx={{ | |||
| mx: 2, | |||
| mt: 0.1, | |||
| cursor: 'pointer', | |||
| }} | |||
| onClick={signOutHandler} | |||
| > | |||
| <Image | |||
| src="/images/logout.svg" | |||
| alt="profile" | |||
| width={18} | |||
| height={20} | |||
| /> | |||
| </Box> | |||
| )} | |||
| <Box | |||
| sx={{ | |||
| mx: 2, | |||
| cursor: 'pointer', | |||
| }} | |||
| > | |||
| <Link key="home" href={PROFILE_PAGE}> | |||
| <Image | |||
| src="/images/profile.svg" | |||
| alt="profile" | |||
| width={24} | |||
| height={24} | |||
| /> | |||
| </Link> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| mr: 6, | |||
| ml: 2, | |||
| cursor: 'pointer', | |||
| }} | |||
| > | |||
| <Link key="home" href={CART_PAGE}> | |||
| <Box> | |||
| {totalQuantity !== 0 && ( | |||
| <Box | |||
| sx={{ | |||
| color: 'white', | |||
| zIndex: 3, | |||
| width: 20, | |||
| height: 20, | |||
| borderRadius: 20, | |||
| textAlign: 'center', | |||
| px: 0.5, | |||
| ml: 2.2, | |||
| mt: -1, | |||
| fontSize: 17, | |||
| position: 'absolute', | |||
| backgroundColor: 'primary.main', | |||
| }} | |||
| > | |||
| {totalQuantity} | |||
| </Box> | |||
| )} | |||
| <Image src="/images/cart.svg" alt="cart" width={24} height={24} /> | |||
| </Box> | |||
| </Link> | |||
| </Box> | |||
| </Box> | |||
| </Box> | |||
| ); | |||
| }; | |||
| export default DesktopNav; | |||
| @@ -0,0 +1,99 @@ | |||
| import MenuIcon from '@mui/icons-material/Menu'; | |||
| import AppBar from '@mui/material/AppBar'; | |||
| import IconButton from '@mui/material/IconButton'; | |||
| import Toolbar from '@mui/material/Toolbar'; | |||
| import useMediaQuery from '@mui/material/useMediaQuery'; | |||
| import React, { useState } from 'react'; | |||
| //drawer elements used | |||
| import { signOut, useSession } from 'next-auth/react'; | |||
| import { useRouter } from 'next/router'; | |||
| import { useEffect } from 'react'; | |||
| import { useStore } from '../../../store/cart-context'; | |||
| import { useUserUpdate } from '../../../store/user-context'; | |||
| import DesktopNav from './DesktopNav'; | |||
| import MobileNav from './MobileNav'; | |||
| export default function MainNav() { | |||
| //react useState hook to save the current open/close state of the drawer, normally variables dissapear afte the function was executed | |||
| const [open, setState] = useState(false); | |||
| const matches = useMediaQuery('(min-width: 900px)'); | |||
| const router = useRouter(); | |||
| const { data: session } = useSession(); | |||
| const { totalQuantity } = useStore(); | |||
| const { clearUser } = useUserUpdate(); | |||
| const signOutHandler = async () => { | |||
| const data = await signOut({ redirect: false, callbackUrl: '/' }); | |||
| clearUser(); | |||
| router.push(data.url); | |||
| }; | |||
| //function that is being called every time the drawer should open or close, the keys tab and shift are excluded so the user can focus between the elements with the keys | |||
| const toggleDrawer = (open) => (event) => { | |||
| if ( | |||
| event.type === 'keydown' && | |||
| (event.key === 'Tab' || event.key === 'Shift') | |||
| ) { | |||
| return; | |||
| } | |||
| //changes the function state according to the value of open | |||
| setState(open); | |||
| }; | |||
| useEffect(() => { | |||
| if (matches) { | |||
| setState(false); | |||
| } | |||
| }, [matches]); | |||
| return ( | |||
| <AppBar | |||
| position="absolute" | |||
| sx={{ | |||
| zIndex: 100, | |||
| top: 20, | |||
| width: '100%', | |||
| backgroundColor: 'transparent', | |||
| boxShadow: 'none', | |||
| height: 40, | |||
| }} | |||
| > | |||
| <Toolbar sx={{ width: '100%' }}> | |||
| <DesktopNav | |||
| router={router} | |||
| totalQuantity={totalQuantity} | |||
| session={session} | |||
| signOutHandler={signOutHandler} | |||
| /> | |||
| <IconButton | |||
| edge="start" | |||
| color={router.pathname === '/' ? 'inherit' : 'primary'} | |||
| aria-label="open drawer" | |||
| onClick={toggleDrawer(true)} | |||
| sx={{ | |||
| mr: 2, | |||
| display: { | |||
| xs: 'block', | |||
| md: 'none', | |||
| }, | |||
| }} | |||
| > | |||
| <MenuIcon /> | |||
| </IconButton> | |||
| {/* The outside of the drawer */} | |||
| <MobileNav | |||
| session={session} | |||
| signOutHandler={signOutHandler} | |||
| toggleDrawer={toggleDrawer} | |||
| open={open} | |||
| /> | |||
| </Toolbar> | |||
| </AppBar> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,125 @@ | |||
| import CloseIcon from '@mui/icons-material/Close'; | |||
| import { Box, Button, Divider, Drawer, IconButton } from '@mui/material'; | |||
| import Image from 'next/image'; | |||
| import Link from 'next/link'; | |||
| import { CART_PAGE, PROFILE_PAGE } from '../../../constants/pages'; | |||
| import { NavItemMobile } from './NavItem'; | |||
| import { items } from './navItems'; | |||
| const MobileNav = ({ toggleDrawer, session, signOutHandler, open }) => { | |||
| return ( | |||
| <Drawer | |||
| PaperProps={{ | |||
| sx: { width: '50%' }, | |||
| }} | |||
| anchor="left" | |||
| open={open} | |||
| onClose={toggleDrawer(false)} | |||
| onOpen={toggleDrawer(true)} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| p: 2, | |||
| height: 1, | |||
| backgroundColor: '#fff', | |||
| }} | |||
| > | |||
| <Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 2 }}> | |||
| <IconButton disableRipple> | |||
| <CloseIcon color="primary" onClick={toggleDrawer(false)} /> | |||
| </IconButton> | |||
| {session?.user?._id && ( | |||
| <IconButton disableRipple onClick={signOutHandler}> | |||
| <Image | |||
| src="/images/logout.svg" | |||
| alt="profile" | |||
| width={18} | |||
| height={20} | |||
| /> | |||
| </IconButton> | |||
| )} | |||
| </Box> | |||
| <Divider sx={{ mb: session?.user?._id ? 0 : 2 }} /> | |||
| {session?.user?._id && ( | |||
| <> | |||
| <Box | |||
| display="flex" | |||
| flexDirection="column" | |||
| justifyContent="center" | |||
| alignItems="center" | |||
| > | |||
| <NavItemMobile | |||
| toggleDrawer={toggleDrawer} | |||
| name="Profile" | |||
| url={PROFILE_PAGE} | |||
| /> | |||
| </Box> | |||
| <Divider sx={{ mb: 2 }} /> | |||
| </> | |||
| )} | |||
| <Box | |||
| sx={{ mb: 2 }} | |||
| display="flex" | |||
| flexDirection="column" | |||
| justifyContent="center" | |||
| alignItems="center" | |||
| > | |||
| {items.map((item) => ( | |||
| <NavItemMobile | |||
| key={item.id} | |||
| toggleDrawer={toggleDrawer} | |||
| name={item.name} | |||
| url={item.url} | |||
| /> | |||
| ))} | |||
| <NavItemMobile | |||
| toggleDrawer={toggleDrawer} | |||
| name="Cart" | |||
| url={CART_PAGE} | |||
| /> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| justifyContent: 'center', | |||
| position: 'absolute', | |||
| bottom: '0', | |||
| left: '50%', | |||
| transform: 'translate(-50%, 0)', | |||
| }} | |||
| > | |||
| {!session?.user?._id && ( | |||
| <> | |||
| <Link href="/auth/register"> | |||
| <Button | |||
| onClick={toggleDrawer(false)} | |||
| variant="contained" | |||
| sx={{ m: 1, width: 0.5 }} | |||
| > | |||
| Register | |||
| </Button> | |||
| </Link> | |||
| <Link href="/auth"> | |||
| <Button | |||
| onClick={toggleDrawer(false)} | |||
| variant="outlined" | |||
| sx={{ m: 1, width: 0.5 }} | |||
| > | |||
| Login | |||
| </Button> | |||
| </Link> | |||
| </> | |||
| )} | |||
| </Box> | |||
| </Box> | |||
| </Drawer> | |||
| ); | |||
| }; | |||
| export default MobileNav; | |||
| @@ -0,0 +1,42 @@ | |||
| import { ListItemButton, ListItemText, Typography } from '@mui/material'; | |||
| import Link from 'next/link'; | |||
| export const NavItemMobile = ({ toggleDrawer, name, url }) => { | |||
| return ( | |||
| <ListItemButton> | |||
| <Link href={url}> | |||
| <ListItemText | |||
| onClick={toggleDrawer(false)} | |||
| primary={ | |||
| <Typography | |||
| sx={{ fontSize: '24px' }} | |||
| style={{ color: 'primary.main' }} | |||
| > | |||
| {name} | |||
| </Typography> | |||
| } | |||
| /> | |||
| </Link> | |||
| </ListItemButton> | |||
| ); | |||
| }; | |||
| export const NavItemDesktop = ({ url, router, name }) => { | |||
| return ( | |||
| <Link href={url}> | |||
| <Typography | |||
| textAlign="center" | |||
| sx={{ | |||
| mx: 'auto', | |||
| fontSize: { md: 20, lg: 20 }, | |||
| fontWeight: 500, | |||
| color: router.pathname === '/' ? 'white' : 'primary.main', | |||
| textDecoration: 'none', | |||
| cursor: 'pointer', | |||
| }} | |||
| > | |||
| {name} | |||
| </Typography> | |||
| </Link> | |||
| ); | |||
| }; | |||
| @@ -196,7 +196,7 @@ const Navbar = () => { | |||
| px: 0.5, | |||
| ml: 2.2, | |||
| mt: -1, | |||
| fontSize: 16, | |||
| fontSize: 17, | |||
| position: 'absolute', | |||
| backgroundColor: 'primary.main', | |||
| }} | |||
| @@ -0,0 +1,33 @@ | |||
| import { | |||
| BASE_PAGE, | |||
| CONTACT_PAGE, | |||
| PRODUCTS_PAGE, | |||
| } from '../../../constants/pages'; | |||
| export const items = [ | |||
| { | |||
| id: 1, | |||
| name: 'Home', | |||
| url: BASE_PAGE, | |||
| }, | |||
| { | |||
| id: 2, | |||
| name: 'Menu', | |||
| url: BASE_PAGE, | |||
| }, | |||
| { | |||
| id: 3, | |||
| name: 'About', | |||
| url: BASE_PAGE, | |||
| }, | |||
| { | |||
| id: 4, | |||
| name: 'Store', | |||
| url: PRODUCTS_PAGE, | |||
| }, | |||
| { | |||
| id: 5, | |||
| name: 'Contact', | |||
| url: CONTACT_PAGE, | |||
| }, | |||
| ]; | |||
| @@ -1,54 +1,27 @@ | |||
| import { Button, Container, Grid } from '@mui/material'; | |||
| import { Box } from '@mui/system'; | |||
| import Image from 'next/image'; | |||
| import { useMemo, useState } from 'react'; | |||
| import { useFetchProductsByCategory } from '../../hooks/useFetchProductData'; | |||
| import { compare } from '../../utils/helpers/sortHelpers'; | |||
| import ProductCard from '../product-card/ProductCard'; | |||
| const ProductsGrid = ({ | |||
| allProducts, | |||
| hasNextPage, | |||
| productType, | |||
| fetchNextPage, | |||
| sort, | |||
| }) => { | |||
| const productsPerPage = 9; | |||
| const [next, setNext] = useState(productsPerPage); | |||
| const ProductsGrid = ({ allProducts, hasNextPage, fetchNextPage }) => { | |||
| // const allItems = useMemo( | |||
| // () => allProducts?.pages?.flatMap((page) => page.product), | |||
| // [allProducts] | |||
| // ); | |||
| const { data: filteredData } = useFetchProductsByCategory(productType); | |||
| const allItems = useMemo( | |||
| () => allProducts?.pages?.flatMap((page) => page.product), | |||
| [allProducts] | |||
| const dataToDisplay = allProducts.pages.map((page) => | |||
| page.product.map((item) => ( | |||
| <Grid key={item._id} item md={4} sm={6} xs={12} sx={{ mb: '100px' }}> | |||
| <ProductCard product={item} /> | |||
| </Grid> | |||
| )) | |||
| ); | |||
| const dataToDisplay = | |||
| productType === 'All' || productType === '' | |||
| ? allItems.sort(compare('name', sort)).map((item) => ( | |||
| <Grid key={item._id} item md={4} sm={6} xs={12} sx={{ mb: '100px' }}> | |||
| <ProductCard product={item} /> | |||
| </Grid> | |||
| )) | |||
| : filteredData?.productsByCategory | |||
| .slice(0, next) | |||
| .sort(compare('name', sort)) | |||
| .map((item) => ( | |||
| <Grid | |||
| key={item._id} | |||
| item | |||
| md={4} | |||
| sm={6} | |||
| xs={12} | |||
| sx={{ mb: '100px' }} | |||
| > | |||
| <ProductCard product={item} /> | |||
| </Grid> | |||
| )); | |||
| const handleMoreProducts = () => { | |||
| setNext(next + productsPerPage); | |||
| }; | |||
| // const dataToDisplay = allProducts.map((item) => ( | |||
| // <Grid key={item._id} item md={4} sm={6} xs={12} sx={{ mb: '100px' }}> | |||
| // <ProductCard product={item} /> | |||
| // </Grid> | |||
| // )); | |||
| return ( | |||
| <Container | |||
| @@ -60,7 +33,7 @@ const ProductsGrid = ({ | |||
| {dataToDisplay} | |||
| </Grid> | |||
| <Box textAlign="center" mt={-5} mb={5}> | |||
| {hasNextPage && (productType === 'All' || productType === '') && ( | |||
| {hasNextPage && ( | |||
| <Button | |||
| onClick={fetchNextPage} | |||
| startIcon={ | |||
| @@ -85,32 +58,6 @@ const ProductsGrid = ({ | |||
| Load More | |||
| </Button> | |||
| )} | |||
| {filteredData && next < filteredData.productsByCategory.length && ( | |||
| <Button | |||
| onClick={handleMoreProducts} | |||
| startIcon={ | |||
| <Image | |||
| src="/images/arrow.svg" | |||
| alt="arrow down" | |||
| width={29} | |||
| height={29} | |||
| /> | |||
| } | |||
| sx={{ | |||
| backgroundColor: 'primary.main', | |||
| height: 50, | |||
| width: 150, | |||
| color: 'white', | |||
| ':hover': { | |||
| bgcolor: 'primary.main', // theme.palette.primary.main | |||
| color: 'white', | |||
| }, | |||
| }} | |||
| > | |||
| Load More | |||
| </Button> | |||
| )} | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| @@ -7,6 +7,16 @@ import { useState } from 'react'; | |||
| const ProductInfo = ({ data, bColor, addProductToCart, inCart }) => { | |||
| const [quantity, setQuantity] = useState(1); | |||
| const handleIncrement = () => { | |||
| setQuantity((prevState) => prevState + 1); | |||
| }; | |||
| const handleDecrement = () => { | |||
| if (quantity > 1) { | |||
| setQuantity((prevState) => prevState - 1); | |||
| } | |||
| }; | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| @@ -65,18 +75,20 @@ const ProductInfo = ({ data, bColor, addProductToCart, inCart }) => { | |||
| }} | |||
| > | |||
| <Button | |||
| disableRipple | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 20, | |||
| width: 50, | |||
| }} | |||
| onClick={() => { | |||
| setQuantity((prevState) => prevState - 1); | |||
| handleDecrement(); | |||
| }} | |||
| > | |||
| - | |||
| </Button> | |||
| <Button | |||
| disableRipple | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 17, | |||
| @@ -86,19 +98,21 @@ const ProductInfo = ({ data, bColor, addProductToCart, inCart }) => { | |||
| {quantity} | |||
| </Button> | |||
| <Button | |||
| disableRipple | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 20, | |||
| width: 50, | |||
| }} | |||
| onClick={() => { | |||
| setQuantity((prevState) => prevState + 1); | |||
| handleIncrement(); | |||
| }} | |||
| > | |||
| + | |||
| </Button> | |||
| </ButtonGroup> | |||
| <Button | |||
| disableRipple | |||
| sx={{ | |||
| mt: { xs: 2, md: 0 }, | |||
| ml: { md: 2 }, | |||
| @@ -1,21 +1,21 @@ | |||
| import { useInfiniteQuery } from '@tanstack/react-query'; | |||
| import { getAllProducts } from '../requests/products/productRequest'; | |||
| export const useInfiniteProducts = (filter) => { | |||
| export const useInfiniteProducts = (category, filter) => { | |||
| return useInfiniteQuery( | |||
| ['products'], | |||
| async ({ pageParam = 1 }) => await getAllProducts(pageParam), | |||
| ['products', category, filter], | |||
| async ({ pageParam = 1 }) => | |||
| await getAllProducts( | |||
| pageParam, | |||
| category === '' ? 'All' : category, | |||
| filter === '' ? 'asc' : filter | |||
| ), | |||
| { | |||
| getNextPageParam: (lastPage, pages) => { | |||
| const maxPages = Math.ceil(lastPage?.productCount / 9); | |||
| const nextPage = pages.length + 1; | |||
| if (nextPage <= maxPages) { | |||
| return nextPage; | |||
| if (lastPage.next !== null) { | |||
| return pages.length + 1; | |||
| } | |||
| }, | |||
| enabled: filter === 'All' || filter === '', | |||
| staleTime: 0, | |||
| cacheTime: 0, | |||
| } | |||
| ); | |||
| }; | |||
| @@ -1,5 +1,5 @@ | |||
| const Product = require('../../../models/product'); | |||
| import dbConnect from '../../../utils/helpers/dbHelpers'; | |||
| const Product = require('../../../../models/product'); | |||
| import dbConnect from '../../../../utils/helpers/dbHelpers'; | |||
| async function handler(req, res) { | |||
| const { method } = req; | |||
| @@ -5,15 +5,10 @@ import Image from 'next/image'; | |||
| import { useRouter } from 'next/router'; | |||
| import React, { useState } from 'react'; | |||
| import Loader from '../../components/loader/Loader'; | |||
| import ProductCard from '../../components/product-card/ProductCard'; | |||
| import TabPanel from '../../components/tab-panel/TabPanel'; | |||
| import { | |||
| useFetchSimilarProducts, | |||
| useFetchSingleProduct, | |||
| } from '../../hooks/useFetchProductData'; | |||
| import { useFetchSingleProduct } from '../../hooks/useFetchProductData'; | |||
| import { getProductData } from '../../requests/products/producDataRequest'; | |||
| import { useStore, useStoreUpdate } from '../../store/cart-context'; | |||
| import { shuffle } from '../../utils/helpers/shuffle'; | |||
| const SingleProduct = () => { | |||
| const { addCartValue } = useStoreUpdate(); | |||
| @@ -25,10 +20,7 @@ const SingleProduct = () => { | |||
| const { data, isLoading } = useFetchSingleProduct(customId); | |||
| const productCategory = data?.product.category; | |||
| const { data: similarProducts, isLoading: similarLoading } = | |||
| useFetchSimilarProducts(productCategory); | |||
| // const productCategory = data?.product.category; | |||
| const [value, setValue] = useState(0); | |||
| @@ -54,30 +46,26 @@ const SingleProduct = () => { | |||
| return <Loader loading={isLoading} />; | |||
| } | |||
| if (similarLoading) { | |||
| return <Loader loading={similarLoading} />; | |||
| } | |||
| const productsToShow = (id) => { | |||
| const filtered = shuffle(similarProducts?.productsByCategory) | |||
| .filter((product) => product.customID !== id) | |||
| .slice(0, 3) | |||
| .map((item) => ( | |||
| <Grid | |||
| key={item._id} | |||
| item | |||
| lg={4} | |||
| md={6} | |||
| sm={6} | |||
| xs={12} | |||
| sx={{ mb: '100px' }} | |||
| > | |||
| <ProductCard product={item} /> | |||
| </Grid> | |||
| )); | |||
| return filtered; | |||
| }; | |||
| // const productsToShow = (id) => { | |||
| // const filtered = shuffle(similarProducts?.productsByCategory) | |||
| // .filter((product) => product.customID !== id) | |||
| // .slice(0, 3) | |||
| // .map((item) => ( | |||
| // <Grid | |||
| // key={item._id} | |||
| // item | |||
| // lg={4} | |||
| // md={6} | |||
| // sm={6} | |||
| // xs={12} | |||
| // sx={{ mb: '100px' }} | |||
| // > | |||
| // <ProductCard product={item} /> | |||
| // </Grid> | |||
| // )); | |||
| // return filtered; | |||
| // }; | |||
| return ( | |||
| <Box | |||
| @@ -170,9 +158,7 @@ const SingleProduct = () => { | |||
| > | |||
| Other Product You May Like | |||
| </Typography> | |||
| <Grid container spacing={2}> | |||
| {productsToShow(customId)} | |||
| </Grid> | |||
| <Grid container spacing={2}></Grid> | |||
| </Container> | |||
| </Box> | |||
| ); | |||
| @@ -2,16 +2,18 @@ import { Box } from '@mui/system'; | |||
| import Head from 'next/head'; | |||
| import { useState } from 'react'; | |||
| import FilterSort from '../../components/filter-sort/FilterSort'; | |||
| import Loader from '../../components/loader/Loader'; | |||
| import LoadingSpinner from '../../components/loader/basic-spinner/LoadSpinner'; | |||
| import ProductsGrid from '../../components/products-grid/ProductsGrid'; | |||
| import ProductsHero from '../../components/products-hero/ProductsHero'; | |||
| import { useInfiniteProducts } from '../../hooks/useInfiniteQuery'; | |||
| const Products = () => { | |||
| const [filter, setFilter] = useState('All'); | |||
| const [sort, setSort] = useState('asc'); | |||
| const { data, isLoading, fetchNextPage, hasNextPage } = | |||
| useInfiniteProducts(filter); | |||
| const [filter, setFilter] = useState(''); | |||
| const [sort, setSort] = useState(''); | |||
| const { data, isLoading, fetchNextPage, hasNextPage } = useInfiniteProducts( | |||
| filter, | |||
| sort | |||
| ); | |||
| const handleProductTypeChange = (event) => { | |||
| const filterText = event.target.value; | |||
| @@ -24,7 +26,7 @@ const Products = () => { | |||
| }; | |||
| if (isLoading) { | |||
| return <Loader loading={isLoading} />; | |||
| return <LoadingSpinner />; | |||
| } | |||
| return ( | |||
| @@ -4,10 +4,10 @@ | |||
| viewBox="0 0 384.971 384.971" style="enable-background:new 0 0 384.971 384.971;" xml:space="preserve"> | |||
| <g> | |||
| <g id="Sign_Out"> | |||
| <path d="M180.455,360.91H24.061V24.061h156.394c6.641,0,12.03-5.39,12.03-12.03s-5.39-12.03-12.03-12.03H12.03 | |||
| <path fill='#664C47' d="M180.455,360.91H24.061V24.061h156.394c6.641,0,12.03-5.39,12.03-12.03s-5.39-12.03-12.03-12.03H12.03 | |||
| C5.39,0.001,0,5.39,0,12.031V372.94c0,6.641,5.39,12.03,12.03,12.03h168.424c6.641,0,12.03-5.39,12.03-12.03 | |||
| C192.485,366.299,187.095,360.91,180.455,360.91z"/> | |||
| <path d="M381.481,184.088l-83.009-84.2c-4.704-4.752-12.319-4.74-17.011,0c-4.704,4.74-4.704,12.439,0,17.179l62.558,63.46H96.279 | |||
| <path fill='#664C47' d="M381.481,184.088l-83.009-84.2c-4.704-4.752-12.319-4.74-17.011,0c-4.704,4.74-4.704,12.439,0,17.179l62.558,63.46H96.279 | |||
| c-6.641,0-12.03,5.438-12.03,12.151c0,6.713,5.39,12.151,12.03,12.151h247.74l-62.558,63.46c-4.704,4.752-4.704,12.439,0,17.179 | |||
| c4.704,4.752,12.319,4.752,17.011,0l82.997-84.2C386.113,196.588,386.161,188.756,381.481,184.088z"/> | |||
| </g> | |||
| @@ -1,10 +1,10 @@ | |||
| export const getAllProducts = async ({ | |||
| url, | |||
| export const getAllProducts = async ( | |||
| pageIndex, | |||
| category = 'All', | |||
| filter = 'asc', | |||
| }) => { | |||
| filter = 'asc' | |||
| ) => { | |||
| const response = await fetch( | |||
| `${url}&category=${category}&filterType=${filter}` | |||
| `http://localhost:3000/api/product?pageIndex=${pageIndex}&category=${category}&filterType=${filter}` | |||
| ); | |||
| const data = await response.json(); | |||