|
@@ -1,118 +1,76 @@
|
|
|
-import Breadcrumb from "../components/Breadcrumbs";
|
|
|
import {
|
|
|
- Accordion,
|
|
|
- AccordionDetails,
|
|
|
- AccordionSummary, Box, Button,
|
|
|
- Card, CardActionArea, CardActions, CardContent, CardMedia,
|
|
|
- Container, Divider, FormControl,
|
|
|
- Grid, MenuItem, Select,
|
|
|
- Typography,
|
|
|
- useMediaQuery
|
|
|
+ Box,
|
|
|
+ Button,
|
|
|
+ Card,
|
|
|
+ CardActionArea,
|
|
|
+ CardActions,
|
|
|
+ CardContent,
|
|
|
+ CardMedia, Divider,
|
|
|
+ FormControl,
|
|
|
+ Grid, MenuItem, Pagination, Select,
|
|
|
+ Typography
|
|
|
} from "@mui/material";
|
|
|
-import {connect} from "react-redux";
|
|
|
-import {actionFullCatById, actionFullRootCats} from "../actions/ActionCategory";
|
|
|
import Link from "react-router-dom/es/Link";
|
|
|
-import Route from "react-router-dom/es/Route";
|
|
|
-import Switch from "react-router-dom/es/Switch";
|
|
|
-import {useEffect, useState} from "react";
|
|
|
-import {backURL} from "../actions/PathDB";
|
|
|
-import {actionCardRemove, actionCartAdd} from "../reducers/CartReducer";
|
|
|
-import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
|
+import {backURL} from "../../actions/PathDB";
|
|
|
+import imgNotFound from "../../img/catalog/imgNotFound.png";
|
|
|
+import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
|
|
|
+import AddShoppingCartIcon from "@mui/icons-material/AddShoppingCart";
|
|
|
+import FavoriteIcon from "@mui/icons-material/Favorite";
|
|
|
import FavoriteBorderIcon from "@mui/icons-material/FavoriteBorder";
|
|
|
-import AddShoppingCartIcon from '@mui/icons-material/AddShoppingCart';
|
|
|
-import {Pagination} from "@mui/material";
|
|
|
-import {actionWishListAdd, actionWishListRemove} from "../reducers/WishListReducer";
|
|
|
-import FavoriteIcon from '@mui/icons-material/Favorite';
|
|
|
-import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
|
|
|
-import imgNotFound from "../img/catalog/imgNotFound.png";
|
|
|
-import {NotFoundBlock} from "../components/NotFoundBlock";
|
|
|
-
|
|
|
-const CategoryItem = ({object: {_id, name, subCategories}={}}) => {
|
|
|
- const [expanded, setExpanded] = useState(false);
|
|
|
-
|
|
|
- const handleChange = (panel) => (event, isExpanded) => {
|
|
|
- setExpanded(isExpanded ? panel : false);
|
|
|
- };
|
|
|
-
|
|
|
- return (
|
|
|
- <>
|
|
|
- {subCategories === null || !subCategories ?
|
|
|
- <li>
|
|
|
- <Link style={{textDecoration: 'none'}} to={`/catalog/category/${_id}`}>
|
|
|
- <Typography
|
|
|
- variant='body1'
|
|
|
- color='#616161'
|
|
|
- marginBottom='10px'
|
|
|
- >
|
|
|
- {name}
|
|
|
- </Typography>
|
|
|
- </Link>
|
|
|
- </li>
|
|
|
- :
|
|
|
- <li>
|
|
|
- <Accordion style={{border: 'none', borderRadius: '0',marginTop: '-10px', boxShadow: 'none'}} expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
|
|
|
- <AccordionSummary
|
|
|
- sx={{padding: '0'}}
|
|
|
- expandIcon={<ExpandMoreIcon />}
|
|
|
- aria-controls="panel1bh-content"
|
|
|
- id="panel1bh-header"
|
|
|
- >
|
|
|
- <Link style={{textDecoration: 'none'}} to={`/catalog/category/${_id}`}>
|
|
|
- <Typography
|
|
|
- variant='body1'
|
|
|
- color='#616161'
|
|
|
- padding='0'
|
|
|
- >
|
|
|
- {name}
|
|
|
- </Typography>
|
|
|
- </Link>
|
|
|
- </AccordionSummary>
|
|
|
- <AccordionDetails>
|
|
|
- <ul style={{listStyle: 'none', padding: '0 0 0 10px', marginBottom: '10px'}}>
|
|
|
- {subCategories && Object.values(subCategories).map(item =>
|
|
|
- <CategoryItem key={item['_id']} object={item}/>
|
|
|
- )}
|
|
|
- </ul>
|
|
|
- </AccordionDetails>
|
|
|
- </Accordion>
|
|
|
- </li>
|
|
|
- }
|
|
|
- </>
|
|
|
- )
|
|
|
-}
|
|
|
-const CategoryAside = ({category}) => {
|
|
|
- return (
|
|
|
- <Grid sx={{backgroundColor: '#fff', padding: '30px'}} xs={12} lg={3} item>
|
|
|
- <Typography
|
|
|
- variant='h6'
|
|
|
- letterSpacing='3px'
|
|
|
- lineHeight='1.3em'
|
|
|
- marginBottom='20px'
|
|
|
- >
|
|
|
- PRODUCT CATEGORIES
|
|
|
- </Typography>
|
|
|
- <ul style={{listStyle: 'none', padding: '0'}}>
|
|
|
- {category && Object.values(category).map(item =>
|
|
|
- <CategoryItem key={item['_id']} object={item}/>
|
|
|
- )}
|
|
|
- </ul>
|
|
|
- </Grid>
|
|
|
- )
|
|
|
-}
|
|
|
+import {connect} from "react-redux";
|
|
|
+import {actionCardRemove, actionCartAdd} from "../../reducers/CartReducer";
|
|
|
+import {actionWishListAdd, actionWishListRemove} from "../../reducers/WishListReducer";
|
|
|
+import {useEffect, useState} from "react";
|
|
|
+import {NotFoundBlock} from "../../components/NotFoundBlock";
|
|
|
+import {actionFullCatById} from "../../actions/ActionCategory";
|
|
|
+import Switch from "react-router-dom/es/Switch";
|
|
|
+import Route from "react-router-dom/es/Route";
|
|
|
+import {CRRoute} from "../../components/CPRoute";
|
|
|
|
|
|
-const GoodCard = ({good:{_id, name, description, price, images}={}, wishlist={}, cart={}, onCartAdd, onWishListAdd, onCartRemove, onWishListRemove}) => {
|
|
|
+const GoodCard = ({good:{_id, name, description, price, images}={},
|
|
|
+ wishlist={},
|
|
|
+ cart={},
|
|
|
+ onCartAdd,
|
|
|
+ onWishListAdd,
|
|
|
+ onCartRemove,
|
|
|
+ onWishListRemove}) => {
|
|
|
return (
|
|
|
<Grid xs={12} lg={4} item margin='20px 0'>
|
|
|
- <Card sx={{ maxWidth: 345, height: '100%', display: 'flex', flexDirection: 'column', margin: 'auto 20px'}}>
|
|
|
- <CardActionArea sx={{padding: '0', flexGrow: '1', position: 'relative'}}>
|
|
|
- <Link to={`/good/${_id}`} style={{position: 'relative', textDecoration: 'none'}}>
|
|
|
- <CardMedia sx={{marginBottom: '20px', marginTop: '20px'}}
|
|
|
+ <Card
|
|
|
+ sx={{
|
|
|
+ maxWidth: 345,
|
|
|
+ height: '100%',
|
|
|
+ display: 'flex',
|
|
|
+ flexDirection: 'column',
|
|
|
+ margin: 'auto 20px'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <CardActionArea
|
|
|
+ sx={{
|
|
|
+ padding: '0',
|
|
|
+ flexGrow: '1',
|
|
|
+ position: 'relative'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Link
|
|
|
+ to={`/good/${_id}`}
|
|
|
+ style={{position: 'relative', textDecoration: 'none'}}
|
|
|
+ >
|
|
|
+ <CardMedia
|
|
|
+ sx={{marginBottom: '20px', marginTop: '20px'}}
|
|
|
component="img"
|
|
|
height="230"
|
|
|
image={images && images[0]?.url ? `${backURL}/${images[0]?.url}` : imgNotFound}
|
|
|
alt="Good title image"
|
|
|
/>
|
|
|
- <CardContent sx={{display: 'flex', flexDirection: 'column', height: '200px', justifyContent: 'space-between'}}>
|
|
|
+ <CardContent
|
|
|
+ sx={{
|
|
|
+ display: 'flex',
|
|
|
+ flexDirection: 'column',
|
|
|
+ height: '200px',
|
|
|
+ justifyContent: 'space-between'
|
|
|
+ }}
|
|
|
+ >
|
|
|
<Typography
|
|
|
textAlign='center'
|
|
|
fontFamily='sarif'
|
|
@@ -122,26 +80,58 @@ const GoodCard = ({good:{_id, name, description, price, images}={}, wishlist={},
|
|
|
sx={{textTransform: 'uppercase', flexGrow: '1'}}
|
|
|
color='#000'
|
|
|
>
|
|
|
- {name.length > 30 ? name.split(' ').splice(0, 6).join(' ') : name}
|
|
|
+ {name.length > 30 ? name.split(' ').splice(0, 6).join(' ') : name}
|
|
|
</Typography>
|
|
|
- <Typography textAlign='center' variant="body2" color='#616161' marginBottom='20px' sx={{ flexGrow: '0'}}>
|
|
|
+ <Typography
|
|
|
+ textAlign='center'
|
|
|
+ variant="body2"
|
|
|
+ color='#616161'
|
|
|
+ marginBottom='20px'
|
|
|
+ sx={{ flexGrow: '0'}}
|
|
|
+ >
|
|
|
{description && description.length > 60 ?
|
|
|
'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' :
|
|
|
description
|
|
|
}
|
|
|
</Typography>
|
|
|
- <Typography textAlign='center' variant="h5" color="#000" sx={{ flexGrow: '0'}}>
|
|
|
- $ {parseFloat(price).toFixed(2)}
|
|
|
+ <Typography
|
|
|
+ textAlign='center'
|
|
|
+ variant="h5"
|
|
|
+ color="#000"
|
|
|
+ sx={{ flexGrow: '0'}}>
|
|
|
+ $ {parseFloat(price || 0).toFixed(2)}
|
|
|
</Typography>
|
|
|
</CardContent>
|
|
|
</Link>
|
|
|
</CardActionArea>
|
|
|
<CardActions sx={{flexGrow: '0', justifyContent: 'space-between'}}>
|
|
|
- <Button onClick={() => {_id in cart ? onCartRemove({_id, name, price, images}) : onCartAdd({_id, name, price, images})}} size="small" color="primary">
|
|
|
- {_id in cart ? <ShoppingCartIcon/> : <AddShoppingCartIcon />}
|
|
|
+ <Button
|
|
|
+ onClick={() => {
|
|
|
+ _id in cart ?
|
|
|
+ onCartRemove({_id, name, price, images})
|
|
|
+ : onCartAdd({_id, name, price, images})}
|
|
|
+ }
|
|
|
+ size="small"
|
|
|
+ color="primary"
|
|
|
+ >
|
|
|
+ {_id in cart ?
|
|
|
+ <ShoppingCartIcon/>
|
|
|
+ : <AddShoppingCartIcon />
|
|
|
+ }
|
|
|
</Button>
|
|
|
- <Button onClick={() => {_id in wishlist ? onWishListRemove({_id, name, price, images}) : onWishListAdd({_id, name, price, images})}} size="small" color="primary">
|
|
|
- {_id in wishlist ? <FavoriteIcon/> : <FavoriteBorderIcon />}
|
|
|
+ <Button
|
|
|
+ onClick={() => {
|
|
|
+ _id in wishlist ?
|
|
|
+ onWishListRemove({_id, name, price, images})
|
|
|
+ : onWishListAdd({_id, name, price, images})}
|
|
|
+ }
|
|
|
+ size="small"
|
|
|
+ color="primary"
|
|
|
+ >
|
|
|
+ {_id in wishlist ?
|
|
|
+ <FavoriteIcon/>
|
|
|
+ : <FavoriteBorderIcon />
|
|
|
+ }
|
|
|
</Button>
|
|
|
</CardActions>
|
|
|
</Card>
|
|
@@ -149,10 +139,11 @@ const GoodCard = ({good:{_id, name, description, price, images}={}, wishlist={},
|
|
|
)
|
|
|
}
|
|
|
const CGoodCard = connect(state => ({wishlist: state.wishlist, cart: state.cart}),
|
|
|
- {onCartAdd: actionCartAdd, onWishListAdd: actionWishListAdd, onCartRemove: actionCardRemove, onWishListRemove: actionWishListRemove})(GoodCard)
|
|
|
+ {onCartAdd: actionCartAdd, onWishListAdd: actionWishListAdd, onCartRemove: actionCardRemove,
|
|
|
+ onWishListRemove: actionWishListRemove})(GoodCard)
|
|
|
|
|
|
const Goods = ({_id, category={}}) => {
|
|
|
- const itemsPerPage = 6
|
|
|
+ const itemsPerPage = 9
|
|
|
const [page, setPage] = useState(1)
|
|
|
const [count, setCount] = useState(1)
|
|
|
const [goods, setGoods] = useState([])
|
|
@@ -224,20 +215,34 @@ const Goods = ({_id, category={}}) => {
|
|
|
}).filter(item => item)
|
|
|
setGoods(arr)
|
|
|
}, [_id, category])
|
|
|
-
|
|
|
return (
|
|
|
<>
|
|
|
{(goods.length > 0 ?
|
|
|
- <Box sx={{height:'100%', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
|
|
|
- <Box display='flex' alignItems='center' justifyContent='space-between' padding='0 20px'>
|
|
|
+ <Box
|
|
|
+ sx={{height:'100%',
|
|
|
+ display: 'flex',
|
|
|
+ flexDirection: 'column',
|
|
|
+ justifyContent: 'space-between'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Box
|
|
|
+ display='flex'
|
|
|
+ alignItems='center'
|
|
|
+ justifyContent='space-between'
|
|
|
+ padding='0 20px'
|
|
|
+ >
|
|
|
<Typography
|
|
|
variant='body1'
|
|
|
color='#616161'
|
|
|
letterSpacing='1px'
|
|
|
>
|
|
|
- SHOWING {goods[0].length > itemsPerPage ? `${((page-1) * itemsPerPage)+1}-${page * itemsPerPage > goods[0].length ? goods[0].length : page * itemsPerPage}` : goods[0].length} OF {goods[0].length} RESULTS
|
|
|
+ SHOWING {goods[0].length > itemsPerPage ? `${((page-1) * itemsPerPage)+1}-
|
|
|
+ ${page * itemsPerPage > goods[0].length ? goods[0].length : page * itemsPerPage}` :
|
|
|
+ goods[0].length} OF {goods[0].length} RESULTS
|
|
|
</Typography>
|
|
|
- <FormControl variant="standard">
|
|
|
+ <FormControl
|
|
|
+ variant="standard"
|
|
|
+ >
|
|
|
<Select
|
|
|
labelId="demo-simple-select-label"
|
|
|
id="demo-simple-select"
|
|
@@ -253,15 +258,25 @@ const Goods = ({_id, category={}}) => {
|
|
|
</Select>
|
|
|
</FormControl>
|
|
|
</Box>
|
|
|
- <Box flexGrow='1'>
|
|
|
- <Grid container justifyContent='space-between'>
|
|
|
+ <Box
|
|
|
+ flexGrow='1'
|
|
|
+ >
|
|
|
+ <Grid
|
|
|
+ container
|
|
|
+ justifyContent='space-between'
|
|
|
+ >
|
|
|
{[...goods[0]].slice((page - 1) * itemsPerPage, page * itemsPerPage)
|
|
|
- .map(good => <CGoodCard key={good['_id']} good={good}/>)}
|
|
|
+ .map(good => <CGoodCard key={good['_id']} good={good}/>)
|
|
|
+ }
|
|
|
</Grid>
|
|
|
</Box>
|
|
|
<Box width='100%' flexGrow='0'>
|
|
|
<Divider sx={{margin: '20px'}}/>
|
|
|
- <Box display='flex' justifyContent='center' width='100%'>
|
|
|
+ <Box
|
|
|
+ display='flex'
|
|
|
+ justifyContent='center'
|
|
|
+ width='100%'
|
|
|
+ >
|
|
|
<Pagination
|
|
|
count={count}
|
|
|
page={page}
|
|
@@ -275,7 +290,7 @@ const Goods = ({_id, category={}}) => {
|
|
|
</Box>
|
|
|
</Box>
|
|
|
</Box>
|
|
|
- : <NotFoundBlock/>)
|
|
|
+ : <NotFoundBlock marginTop={'-50px'}/>)
|
|
|
}
|
|
|
</>
|
|
|
)
|
|
@@ -292,37 +307,13 @@ const BlockGood = ({match:{params:{_id}}, getData}) => {
|
|
|
}
|
|
|
const CBlockGood= connect(null, {getData: actionFullCatById})(BlockGood)
|
|
|
|
|
|
-const Products = () => {
|
|
|
+export const Products = () => {
|
|
|
return (
|
|
|
<Grid xs={12} lg={9} item>
|
|
|
<Switch>
|
|
|
- <Route path="/catalog/category/:_id" component={CBlockGood} />
|
|
|
- <Route path="*" component={NotFoundBlock} />
|
|
|
+ <CRRoute path="/catalog/category/:_id" component={CBlockGood} />
|
|
|
+ <CRRoute path="*" component={NotFoundBlock} />
|
|
|
</Switch>
|
|
|
</Grid>
|
|
|
)
|
|
|
}
|
|
|
-
|
|
|
-const CatalogPage = ({category={}, actionRootCat}) => {
|
|
|
- const matches = useMediaQuery('(max-width:899px)')
|
|
|
- if(Object.entries(category).length === 0) actionRootCat()
|
|
|
-
|
|
|
- return (
|
|
|
- <>
|
|
|
- <Breadcrumb links={['catalog']}/>
|
|
|
- <main style={{backgroundColor: "#f3f3f3", padding: matches ? "20px 0" : "50px 0"}}>
|
|
|
- <Container maxWidth="lg">
|
|
|
- <Grid container justifyContent='space-between'>
|
|
|
- <CategoryAside category={category}/>
|
|
|
- <Products/>
|
|
|
- </Grid>
|
|
|
- </Container>
|
|
|
- </main>
|
|
|
- </>
|
|
|
- )
|
|
|
-}
|
|
|
-const CCatalogPage = connect(state => ({category: state.category}), {actionRootCat: actionFullRootCats})(CatalogPage)
|
|
|
-
|
|
|
-export default CCatalogPage
|
|
|
-
|
|
|
-//TODO MOBILE VERSION
|