| @@ -1,4 +1,4 @@ | |||
| import { Box, Button, ButtonGroup, Paper, Typography } from '@mui/material'; | |||
| import { Box, Button, ButtonGroup, Card, Typography } from '@mui/material'; | |||
| import Image from 'next/image'; | |||
| import PropType from 'prop-types'; | |||
| import { useState } from 'react'; | |||
| @@ -11,158 +11,159 @@ const CartCard = ({ product, initialQuantity, remove, updateQuantity }) => { | |||
| // }, [quantity]); | |||
| return ( | |||
| <Paper | |||
| <Card | |||
| sx={{ | |||
| p: 1, | |||
| width: { lg: '88%', xs: '73%', md: '80%' }, | |||
| mb: 2, | |||
| ml: 12, | |||
| ml: 10, | |||
| mr: { sm: 10, lg: 1 }, | |||
| backgroundColor: '#f2f2f2', | |||
| display: 'flex', | |||
| justifyContent: { xs: 'center', md: 'none' }, | |||
| p: 2, | |||
| mb: 2, | |||
| }} | |||
| elevation={3} | |||
| > | |||
| <Box sx={{ width: '30%', display: { xs: 'none', md: 'block' } }}> | |||
| <Image | |||
| src="/images/coffee-mug.svg" | |||
| alt="profile" | |||
| width={500} | |||
| height={300} | |||
| /> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| ml: -4, | |||
| mr: 2, | |||
| display: 'flex', | |||
| alignItems: 'center', | |||
| width: '30%', | |||
| }} | |||
| > | |||
| <Typography | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| height: 25, | |||
| fontWeight: 600, | |||
| ml: { xs: -1, sm: 0 }, | |||
| fontSize: { xs: 16, sm: 20 }, | |||
| }} | |||
| > | |||
| {product?.name} | |||
| </Typography> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| width: '20%', | |||
| justifyContent: 'center', | |||
| alignItems: 'center', | |||
| ml: { xs: 2, sm: 0 }, | |||
| flexDirection: { xs: 'column', md: 'row' }, | |||
| justifyContent: { xs: 'center' }, | |||
| }} | |||
| > | |||
| <Typography | |||
| <Box sx={{ display: { xs: 'none', md: 'flex', width: '20%' } }}> | |||
| <Image | |||
| src="/images/coffee-mug.svg" | |||
| alt="profile" | |||
| width={500} | |||
| height={300} | |||
| /> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| height: 16, | |||
| fontSize: 14, | |||
| display: 'flex', | |||
| alignItems: 'center', | |||
| justifyItems: 'center', | |||
| width: { md: '40%' }, | |||
| }} | |||
| > | |||
| Quantity | |||
| </Typography> | |||
| <ButtonGroup | |||
| size="small" | |||
| aria-label="small outlined button group" | |||
| <Typography | |||
| align="center" | |||
| sx={{ | |||
| mb: { xs: 10, sm: 5, md: 0 }, | |||
| mr: { md: 5 }, | |||
| width: '100%', | |||
| fontWeight: 600, | |||
| fontSize: { xs: 16, sm: 20 }, | |||
| }} | |||
| > | |||
| {product?.name} | |||
| </Typography> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| height: 35, | |||
| width: 125, | |||
| mt: 1, | |||
| backgroundColor: 'primary.main', | |||
| color: 'white', | |||
| border: 0, | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| justifyContent: 'center', | |||
| alignItems: 'center', | |||
| mb: { xs: 10, sm: 5, md: 0 }, | |||
| mr: { md: 5 }, | |||
| }} | |||
| > | |||
| <Button | |||
| <Typography | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 17, | |||
| width: 25, | |||
| }} | |||
| onClick={() => { | |||
| if (quantity > 0) { | |||
| updateQuantity(product?.customID, quantity - 1); | |||
| setQuantity((prevState) => prevState - 1); | |||
| } | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| height: 16, | |||
| fontSize: 14, | |||
| }} | |||
| > | |||
| - | |||
| </Button> | |||
| <Button | |||
| Quantity | |||
| </Typography> | |||
| <ButtonGroup | |||
| size="small" | |||
| aria-label="small outlined button group" | |||
| sx={{ | |||
| height: 35, | |||
| mt: 1, | |||
| backgroundColor: 'primary.main', | |||
| color: 'white', | |||
| fontSize: 15, | |||
| width: 25, | |||
| border: 0, | |||
| }} | |||
| > | |||
| {quantity} | |||
| </Button> | |||
| <Button | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 17, | |||
| width: 25, | |||
| }} | |||
| onClick={() => { | |||
| if (quantity > 0) { | |||
| updateQuantity(product?.customID, quantity - 1); | |||
| setQuantity((prevState) => prevState - 1); | |||
| } | |||
| }} | |||
| > | |||
| - | |||
| </Button> | |||
| <Button | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 15, | |||
| width: 25, | |||
| }} | |||
| > | |||
| {quantity} | |||
| </Button> | |||
| <Button | |||
| sx={{ | |||
| color: 'white', | |||
| fontSize: 17, | |||
| width: 25, | |||
| }} | |||
| onClick={() => { | |||
| updateQuantity(product?.customID, quantity + 1); | |||
| setQuantity((prevState) => prevState + 1); | |||
| }} | |||
| > | |||
| + | |||
| </Button> | |||
| </ButtonGroup> | |||
| <Button | |||
| sx={{ | |||
| height: 35, | |||
| mt: 1, | |||
| width: 125, | |||
| fontSize: 15, | |||
| textTransform: 'none', | |||
| backgroundColor: '#C6453E', | |||
| color: 'white', | |||
| fontSize: 17, | |||
| width: 25, | |||
| }} | |||
| onClick={() => { | |||
| updateQuantity(product?.customID, quantity + 1); | |||
| setQuantity((prevState) => prevState + 1); | |||
| }} | |||
| startIcon={ | |||
| <Image src="/images/x.svg" alt="remove" width={15} height={15} /> | |||
| } | |||
| onClick={() => remove(product.customID)} | |||
| > | |||
| + | |||
| Remove | |||
| </Button> | |||
| </ButtonGroup> | |||
| <Button | |||
| sx={{ | |||
| height: 35, | |||
| mt: 1, | |||
| width: 125, | |||
| fontSize: 15, | |||
| textTransform: 'none', | |||
| backgroundColor: '#C6453E', | |||
| color: 'white', | |||
| }} | |||
| startIcon={ | |||
| <Image src="/images/x.svg" alt="remove" width={15} height={15} /> | |||
| } | |||
| onClick={() => remove(product.customID)} | |||
| > | |||
| Remove | |||
| </Button> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| ml: { xs: 5, sm: 3 }, | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| width: '20%', | |||
| justifyContent: 'center', | |||
| alignItems: 'center', | |||
| }} | |||
| > | |||
| <Typography | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| height: 25, | |||
| fontSize: { xs: 15, md: 18 }, | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| justifyContent: 'center', | |||
| alignItems: 'center', | |||
| }} | |||
| > | |||
| Price: ${product?.price} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| height: 25, | |||
| fontSize: { xs: 15, md: 18 }, | |||
| }} | |||
| > | |||
| Price: ${product?.price} | |||
| </Typography> | |||
| </Box> | |||
| </Box> | |||
| </Paper> | |||
| </Card> | |||
| ); | |||
| }; | |||
| @@ -19,9 +19,7 @@ const DataCard = ({ data, quantity }) => { | |||
| <Box | |||
| sx={{ | |||
| width: '30%', | |||
| borderRadius: 4, | |||
| overflow: 'hidden', | |||
| display: { xs: 'none', lg: 'block' }, | |||
| display: { xs: 'none', lg: 'flex' }, | |||
| }} | |||
| > | |||
| <Image | |||
| @@ -33,35 +31,36 @@ const DataCard = ({ data, quantity }) => { | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| ml: 3, | |||
| ml: { xs: 0, md: 3 }, | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| width: { lg: '60%', sx: '100%' }, | |||
| }} | |||
| > | |||
| <Typography | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| height: 25, | |||
| fontWeight: 600, | |||
| fontSize: { md: 20, xs: 16 }, | |||
| }} | |||
| > | |||
| {data.name} - x{quantity} | |||
| {data.name} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| mt: { sm: 3, xs: 6 }, | |||
| fontSize: 14, | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| fontWeight: 600, | |||
| fontSize: { md: 20, xs: 16 }, | |||
| }} | |||
| > | |||
| {data.description} | |||
| x{quantity} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| mt: { lg: 3, xs: 1 }, | |||
| textAlign: 'right', | |||
| textAlign: 'center', | |||
| fontSize: 14, | |||
| }} | |||
| > | |||
| @@ -32,6 +32,7 @@ const CartContent = () => { | |||
| return ( | |||
| <Typography | |||
| sx={{ | |||
| mr: { sm: 10, lg: 1 }, | |||
| pl: 12, | |||
| mt: 6, | |||
| height: '100%', | |||
| @@ -52,9 +53,7 @@ const CartContent = () => { | |||
| {mapProductsToDom()} | |||
| </Grid> | |||
| <Grid item lg={4} xs={12}> | |||
| <Box | |||
| sx={{ width: { xs: '90%', lg: '80%' }, mt: 2, pl: { xs: 12, lg: 0 } }} | |||
| > | |||
| <Box sx={{ mr: { xs: 10 }, mt: 2, pl: { xs: 10, lg: 0 } }}> | |||
| <OrderSummaryCard | |||
| data={{ totalPrice: totalPrice, totalQuantity: totalQuantity }} | |||
| ></OrderSummaryCard> | |||
| @@ -1,3 +1,4 @@ | |||
| import NavigateNextIcon from '@mui/icons-material/NavigateNext'; | |||
| import { Breadcrumbs, Divider, Grid, Typography } from '@mui/material'; | |||
| import PropType from 'prop-types'; | |||
| @@ -18,12 +19,13 @@ const StepTitle = ({ title, breadcrumbsArray }) => { | |||
| <Grid item xs={12} sx={{ mt: 4 }}> | |||
| <Breadcrumbs | |||
| aria-label="breadcrumb" | |||
| separator="›" | |||
| separator={<NavigateNextIcon fontSize="small" />} | |||
| sx={{ pl: 12, fontSize: 20 }} | |||
| > | |||
| {breadcrumbsArray.map((entry, index) => { | |||
| return ( | |||
| <Typography | |||
| fontSize="20px" | |||
| key={index} | |||
| color={index === breadcrumbsArray.length - 1 ? 'red' : 'black'} | |||
| > | |||
| @@ -1,7 +1,11 @@ | |||
| const { CircularProgress } = require('@mui/material'); | |||
| const { CircularProgress, Box } = require('@mui/material'); | |||
| const LoadingSpinner = () => { | |||
| return <CircularProgress />; | |||
| return ( | |||
| <Box display="flex" justifyContent="center" sx={{ mt: 5 }}> | |||
| <CircularProgress /> | |||
| </Box> | |||
| ); | |||
| }; | |||
| export default LoadingSpinner; | |||
| @@ -19,7 +19,7 @@ const ProductCard = ({ product }) => { | |||
| width: '100%', | |||
| height: '100%', | |||
| border: 'none', | |||
| mb: '75px', | |||
| mb: '15px', | |||
| backgroundColor: '#F5ECD4', | |||
| }} | |||
| > | |||
| @@ -44,17 +44,32 @@ const ProductCard = ({ product }) => { | |||
| flexDirection: 'column', | |||
| }} | |||
| > | |||
| <Typography fontSize="24px" align="center" pt={1} pb={3}> | |||
| <Typography | |||
| sx={{ height: '100px' }} | |||
| fontSize="24px" | |||
| align="center" | |||
| pt={1} | |||
| pb={3} | |||
| > | |||
| {product.name} | |||
| </Typography> | |||
| <Typography align="center" fontSize="18px" m={2}> | |||
| {product.description} | |||
| <Typography | |||
| sx={{ height: '200px' }} | |||
| align="center" | |||
| fontSize="18px" | |||
| m={2} | |||
| > | |||
| {product.description.length > 250 | |||
| ? product.description.slice(0, 250) + '...' | |||
| : product.description} | |||
| </Typography> | |||
| <Typography fontSize="24px" align="center" pt={4}> | |||
| ${product.price} | |||
| </Typography> | |||
| <Box textAlign="center" mt={1}> | |||
| <Button | |||
| disableRipple | |||
| disableFocusRipple | |||
| disabled={inCart} | |||
| onClick={() => addProductToCart(1)} | |||
| sx={{ | |||
| @@ -4,11 +4,6 @@ import Image from 'next/image'; | |||
| import ProductCard from '../product-card/ProductCard'; | |||
| const ProductsGrid = ({ allProducts, hasNextPage, fetchNextPage }) => { | |||
| // 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' }}> | |||
| @@ -17,12 +12,6 @@ const ProductsGrid = ({ allProducts, hasNextPage, fetchNextPage }) => { | |||
| )) | |||
| ); | |||
| // 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 | |||
| sx={{ | |||
| @@ -22,22 +22,21 @@ const ProductInfo = ({ data, bColor, addProductToCart, inCart }) => { | |||
| sx={{ | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: { xs: 'center' }, | |||
| alignItems: { xs: 'center', md: 'flex-start' }, | |||
| width: { xs: '100%', md: '50%' }, | |||
| height: '100%', | |||
| }} | |||
| > | |||
| <Typography | |||
| variant="h3" | |||
| sx={{ height: 60, mt: { xs: 5 }, color: 'white' }} | |||
| > | |||
| <Typography variant="h3" sx={{ mt: { xs: 5 }, color: 'white' }}> | |||
| {data.name} | |||
| </Typography> | |||
| <Box | |||
| sx={{ | |||
| width: 100, | |||
| maxWidth: 100, | |||
| height: 60, | |||
| display: 'flex', | |||
| alignItems: { xs: 'center', md: 'flex-start' }, | |||
| justifyContent: { xs: 'center', md: 'flex-start' }, | |||
| width: '100%', | |||
| py: { xs: 2 }, | |||
| }} | |||
| > | |||
| <Image | |||
| @@ -61,7 +60,7 @@ const ProductInfo = ({ data, bColor, addProductToCart, inCart }) => { | |||
| mt: 4, | |||
| flexDirection: { xs: 'column', md: 'row' }, | |||
| alignItems: { xs: 'center' }, | |||
| justifyContent: { md: 'center' }, | |||
| justifyContent: { md: 'flex-start' }, | |||
| }} | |||
| > | |||
| <ButtonGroup | |||
| @@ -14,7 +14,6 @@ const ShippingData = ({ email, address, city, postcode, handleOpen }) => { | |||
| mt: 2, | |||
| ml: 12, | |||
| mb: 2, | |||
| width: { lg: '90%', xs: '80%' }, | |||
| borderRadius: 2, | |||
| p: 1, | |||
| }} | |||
| @@ -45,7 +44,6 @@ const ShippingData = ({ email, address, city, postcode, handleOpen }) => { | |||
| alignItems: 'center', | |||
| ml: 12, | |||
| mb: 2, | |||
| width: { lg: '90%', xs: '80%' }, | |||
| borderRadius: 2, | |||
| p: 1, | |||
| }} | |||
| @@ -5,6 +5,7 @@ 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 { useFetchSingleProduct } from '../../hooks/useFetchProductData'; | |||
| import { getProductData } from '../../requests/products/producDataRequest'; | |||
| @@ -46,27 +47,6 @@ const SingleProduct = () => { | |||
| return <Loader loading={isLoading} />; | |||
| } | |||
| // 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 | |||
| sx={{ | |||
| @@ -83,7 +63,7 @@ const SingleProduct = () => { | |||
| {data.product.name} | |||
| </Typography> | |||
| <Grid container spacing={2}> | |||
| <Grid item md={6} sm={12}> | |||
| <Grid sx={{ display: 'flex' }} item md={6} sm={12}> | |||
| <Image | |||
| src="/images/product-card-image.jpg" | |||
| alt="product" | |||
| @@ -156,9 +136,22 @@ const SingleProduct = () => { | |||
| fontSize: '32px', | |||
| }} | |||
| > | |||
| Other Product You May Like | |||
| Similar Products You May Like | |||
| </Typography> | |||
| <Grid container spacing={2}></Grid> | |||
| <Grid container spacing={2}> | |||
| {data.similarProducts.map((product) => ( | |||
| <Grid | |||
| key={product._id} | |||
| item | |||
| md={4} | |||
| sm={6} | |||
| xs={12} | |||
| sx={{ mb: '100px' }} | |||
| > | |||
| <ProductCard product={product} /> | |||
| </Grid> | |||
| ))} | |||
| </Grid> | |||
| </Container> | |||
| </Box> | |||
| ); | |||
| @@ -25,10 +25,6 @@ const Products = () => { | |||
| setSort(sort); | |||
| }; | |||
| if (isLoading) { | |||
| return <LoadingSpinner />; | |||
| } | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| @@ -47,13 +43,17 @@ const Products = () => { | |||
| sort={sort} | |||
| handleSortChange={handleSortChange} | |||
| /> | |||
| <ProductsGrid | |||
| allProducts={data} | |||
| sort={sort} | |||
| productType={filter} | |||
| fetchNextPage={fetchNextPage} | |||
| hasNextPage={hasNextPage} | |||
| /> | |||
| {isLoading ? ( | |||
| <LoadingSpinner /> | |||
| ) : ( | |||
| <ProductsGrid | |||
| allProducts={data} | |||
| sort={sort} | |||
| productType={filter} | |||
| fetchNextPage={fetchNextPage} | |||
| hasNextPage={hasNextPage} | |||
| /> | |||
| )} | |||
| </Box> | |||
| ); | |||
| }; | |||