|
@@ -1,30 +1,31 @@
|
|
|
-import Header from "../components/Header";
|
|
|
-import Footer from "../components/Footer";
|
|
|
import Breadcrumb from "../components/Breadcrumbs";
|
|
|
import {
|
|
|
Accordion,
|
|
|
AccordionDetails,
|
|
|
AccordionSummary, Box, Button,
|
|
|
Card, CardActionArea, CardActions, CardContent, CardMedia,
|
|
|
- Container, Divider,
|
|
|
- Grid,
|
|
|
+ Container, Divider, FormControl,
|
|
|
+ Grid, MenuItem, Select,
|
|
|
Typography,
|
|
|
useMediaQuery
|
|
|
} from "@mui/material";
|
|
|
import {connect} from "react-redux";
|
|
|
import {actionFullCatById, actionFullRootCats} from "../actions/ActionCategory";
|
|
|
import Link from "react-router-dom/es/Link";
|
|
|
-import Page404 from "./404Page";
|
|
|
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 {actionCartAdd} from "../reducers/CartReducer";
|
|
|
+import {actionCardRemove, actionCartAdd} from "../reducers/CartReducer";
|
|
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
|
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 imgUrl from "../img/not-found/1.png";
|
|
|
+import imgNotFound from "../img/catalog/imgNotFound.png";
|
|
|
|
|
|
const CategoryItem = ({object: {_id, name, subCategories}={}}) => {
|
|
|
const [expanded, setExpanded] = useState(false);
|
|
@@ -69,7 +70,7 @@ const CategoryItem = ({object: {_id, name, subCategories}={}}) => {
|
|
|
<AccordionDetails>
|
|
|
<ul style={{listStyle: 'none', padding: '0 0 0 10px', marginBottom: '10px'}}>
|
|
|
{subCategories && Object.values(subCategories).map(item =>
|
|
|
- <CategoryItem object={item}/>
|
|
|
+ <CategoryItem key={item['_id']} object={item}/>
|
|
|
)}
|
|
|
</ul>
|
|
|
</AccordionDetails>
|
|
@@ -81,7 +82,7 @@ const CategoryItem = ({object: {_id, name, subCategories}={}}) => {
|
|
|
}
|
|
|
const CategoryAside = ({category}) => {
|
|
|
return (
|
|
|
- <Grid sx={{backgroundColor: '#fff', padding: '30px'}} xs={12} lg={3}>
|
|
|
+ <Grid sx={{backgroundColor: '#fff', padding: '30px'}} xs={12} lg={3} item>
|
|
|
<Typography
|
|
|
variant='h6'
|
|
|
letterSpacing='3px'
|
|
@@ -92,14 +93,14 @@ const CategoryAside = ({category}) => {
|
|
|
</Typography>
|
|
|
<ul style={{listStyle: 'none', padding: '0'}}>
|
|
|
{category && Object.values(category).map(item =>
|
|
|
- <CategoryItem object={item}/>
|
|
|
+ <CategoryItem key={item['_id']} object={item}/>
|
|
|
)}
|
|
|
</ul>
|
|
|
</Grid>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-const GoodCard = ({good:{_id, name, description, price, images}={}, onCartAdd}) => {
|
|
|
+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'}}>
|
|
@@ -108,10 +109,10 @@ const GoodCard = ({good:{_id, name, description, price, images}={}, onCartAdd})
|
|
|
<CardMedia sx={{marginBottom: '20px', marginTop: '20px'}}
|
|
|
component="img"
|
|
|
height="230"
|
|
|
- image={`${backURL}/${images[0].url}`}
|
|
|
+ image={images[0].url ? `${backURL}/${images[0].url}` : imgNotFound}
|
|
|
alt="Good title image"
|
|
|
/>
|
|
|
- <CardContent sx={{display: 'flex', flexDirection: 'column', height: '180px', justifyContent: 'space-between'}}>
|
|
|
+ <CardContent sx={{display: 'flex', flexDirection: 'column', height: '200px', justifyContent: 'space-between'}}>
|
|
|
<Typography
|
|
|
textAlign='center'
|
|
|
fontFamily='sarif'
|
|
@@ -121,7 +122,7 @@ const GoodCard = ({good:{_id, name, description, price, images}={}, onCartAdd})
|
|
|
sx={{textTransform: 'uppercase', flexGrow: '1'}}
|
|
|
color='#000'
|
|
|
>
|
|
|
- {name}
|
|
|
+ {name.length > 30 ? name.split(' ').splice(0, 6).join(' ') : name}
|
|
|
</Typography>
|
|
|
<Typography textAlign='center' variant="body2" color='#616161' marginBottom='20px' sx={{ flexGrow: '0'}}>
|
|
|
{description.length > 60 ?
|
|
@@ -136,72 +137,185 @@ const GoodCard = ({good:{_id, name, description, price, images}={}, onCartAdd})
|
|
|
</Link>
|
|
|
</CardActionArea>
|
|
|
<CardActions sx={{flexGrow: '0', justifyContent: 'space-between'}}>
|
|
|
- <Button onClick={() => onCartAdd({_id, name, price, images})} size="small" color="primary">
|
|
|
- <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={() => console.log('nice')} size="small" color="primary">
|
|
|
- <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>
|
|
|
</Grid>
|
|
|
)
|
|
|
}
|
|
|
-const CGoodCard = connect(null, {onCartAdd: actionCartAdd})(GoodCard)
|
|
|
+const CGoodCard = connect(state => ({wishlist: state.wishlist, cart: state.cart}),
|
|
|
+ {onCartAdd: actionCartAdd, onWishListAdd: actionWishListAdd, onCartRemove: actionCardRemove, onWishListRemove: actionWishListRemove})(GoodCard)
|
|
|
+
|
|
|
+const GoodNotFound = () => {
|
|
|
+ const matches2 = useMediaQuery('(max-width:450px)');
|
|
|
+ return (
|
|
|
+ <Container maxWidth="lg">
|
|
|
+ <Box sx={{
|
|
|
+ backgroundColor: "#fff",
|
|
|
+ height: matches2 ? "250px" : "350px",
|
|
|
+ display: "flex",
|
|
|
+ flexDirection: "column",
|
|
|
+ justifyContent: "center",
|
|
|
+ alignItems: "center"
|
|
|
+ }}>
|
|
|
+ <img style={{
|
|
|
+ maxWidth: matches2 ? "100px" : "150px"
|
|
|
+ }} src={imgUrl} alt="PAGE NOT FOUND"/>
|
|
|
+ <Typography
|
|
|
+ variant={matches2 ? "h6" : "h5"}
|
|
|
+ fontFamily="sarif"
|
|
|
+ fontWeight="300"
|
|
|
+ marginBottom="20px"
|
|
|
+ marginTop="20px"
|
|
|
+ textAlign="center"
|
|
|
+ >
|
|
|
+ OOPS! THAT PAGE CAN’T BE FOUND
|
|
|
+ </Typography>
|
|
|
+ <Typography
|
|
|
+ variant={matches2 ? "body1" : "h7"}
|
|
|
+ textAlign="center"
|
|
|
+ fontWeight="300"
|
|
|
+ >
|
|
|
+ The page you are trying to reach is not available.
|
|
|
+ </Typography>
|
|
|
+ </Box>
|
|
|
+ </Container>
|
|
|
+ )
|
|
|
+}
|
|
|
|
|
|
const Goods = ({_id='5dc49f4d5df9d670df48cc64', category={}}) => {
|
|
|
- // const itemsPerPage = 6
|
|
|
- // const [page, setPage] = useState(1)
|
|
|
- // const [count, setCount] = useState(1)
|
|
|
- // const handleChange = (event, value) => {
|
|
|
- // setPage(value);
|
|
|
- // }
|
|
|
- return (
|
|
|
- <>
|
|
|
- {(Object.values(category) || []).map(item => {
|
|
|
- if (item['_id'] === _id) {
|
|
|
- if(!item.goods || item['goods'] === null) {
|
|
|
- return <div>not info</div>
|
|
|
- }
|
|
|
- if (item.goods) {
|
|
|
- // setCount(item['goods'].length / itemsPerPage)
|
|
|
- return (item['goods'] || []).map((good, index) => <CGoodCard key={index} good={good}/>)
|
|
|
- }
|
|
|
- }
|
|
|
- else if(item['subCategories'] !== null) {
|
|
|
- return (item['subCategories'] || []).map(subItem => {
|
|
|
- if (subItem['_id'] === _id) {
|
|
|
- if(subItem['goods'] === null) return <div>not info</div>
|
|
|
- // setCount(subItem['goods'].length / itemsPerPage)
|
|
|
- return (subItem['goods'] || []).map(good => <CGoodCard good={good}/>)
|
|
|
- }
|
|
|
- else if(subItem['subCategories'] !== null) {
|
|
|
- return (subItem['subCategories'] || []).map(subSubItem => {
|
|
|
- if (subSubItem['_id'] === _id) {
|
|
|
- if(subSubItem['goods'] === null) return <div>not info</div>
|
|
|
- // setCount(subSubItem['goods'].length / itemsPerPage)
|
|
|
- return (subSubItem['goods'] || []).map(good => <CGoodCard good={good}/>)
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- })}
|
|
|
- {/*<Divider />*/}
|
|
|
- {/*<Box display='flex' justifyContent='center' width='100%'>*/}
|
|
|
- {/* <Pagination*/}
|
|
|
- {/* count={count}*/}
|
|
|
- {/* page={page}*/}
|
|
|
- {/* onChange={handleChange}*/}
|
|
|
- {/* defaultPage={1}*/}
|
|
|
- {/* color="primary"*/}
|
|
|
- {/* size="large"*/}
|
|
|
- {/* showFirstButton*/}
|
|
|
- {/* showLastButton*/}
|
|
|
- {/* />*/}
|
|
|
- {/*</Box>*/}
|
|
|
- </>
|
|
|
- )
|
|
|
+ const itemsPerPage = 6
|
|
|
+ const [page, setPage] = useState(1)
|
|
|
+ const [count, setCount] = useState(1)
|
|
|
+ const [goods, setGoods] = useState([])
|
|
|
+ const [sort, setSort] = useState(0)
|
|
|
+
|
|
|
+ const sortDefault = () => {
|
|
|
+ setGoods([goods[0].sort((a, b) => a['name'] > b['name'] ? 1 : -1)])
|
|
|
+ }
|
|
|
+ const sortLatest = () => {
|
|
|
+ setGoods([goods[0].sort((a, b) => b['createdAt'] > a['createdAt'] ? 1 : -1)])
|
|
|
+ }
|
|
|
+ const sortLowToHigh = () => {
|
|
|
+ setGoods([goods[0].sort((a, b) => a['price'] > b['price'] ? 1 : -1)])
|
|
|
+ }
|
|
|
+ const sortHighToLow = () => {
|
|
|
+ setGoods([goods[0].sort((a, b) => b['price'] > a['price'] ? 1 : -1)])
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleChange = (event, value) => {
|
|
|
+ setPage(value);
|
|
|
+ }
|
|
|
+ const handleChangeSelect = (event) => {
|
|
|
+ setSort(event.target.value);
|
|
|
+ if (event.target.value === 0) sortDefault()
|
|
|
+ else if (event.target.value === 1) sortLatest()
|
|
|
+ else if (event.target.value === 2) sortLowToHigh()
|
|
|
+ else if (event.target.value === 3) sortHighToLow()
|
|
|
+ }
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ let arr = (Object.values(category) || []).map(item => {
|
|
|
+ if (item['_id'] === _id) {
|
|
|
+ if (Array.isArray(item?.goods) && item?.goods.length > 0) {
|
|
|
+ setCount(Math.ceil(item.goods.length / itemsPerPage))
|
|
|
+ return item.goods
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(Array.isArray(item['subCategories'])) {
|
|
|
+ let arr = item['subCategories'].map(subItem => {
|
|
|
+ if (subItem['_id'] === _id) {
|
|
|
+ if (Array.isArray(subItem?.goods) && subItem?.goods.length > 0) {
|
|
|
+ setCount(Math.ceil(subItem.goods.length / itemsPerPage))
|
|
|
+ return subItem.goods
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(Array.isArray(subItem['subCategories'])) {
|
|
|
+ let arr = subItem['subCategories'].map(subSubItem => {
|
|
|
+ if (subSubItem['_id'] === _id) {
|
|
|
+ if (Array.isArray(subSubItem?.goods && subSubItem?.goods.length > 0)) {
|
|
|
+ setCount(Math.ceil(subSubItem.goods.length / itemsPerPage))
|
|
|
+ return subSubItem.goods
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ }).filter(item => item)
|
|
|
+ return arr.length > 0 ? [...arr[0]] : 0
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ }).filter(item => item)
|
|
|
+ return arr.length > 0 ? [...arr[0]] : 0
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ }).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'>
|
|
|
+ <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
|
|
|
+ </Typography>
|
|
|
+ <FormControl variant="standard">
|
|
|
+ <Select
|
|
|
+ labelId="demo-simple-select-label"
|
|
|
+ id="demo-simple-select"
|
|
|
+ value={sort}
|
|
|
+ label="Sort"
|
|
|
+ onChange={handleChangeSelect}
|
|
|
+ sx={{textTransform: 'uppercase', color: '#616161'}}
|
|
|
+ >
|
|
|
+ <MenuItem value={0}>Default sorting</MenuItem>
|
|
|
+ <MenuItem value={1}>Sort by latest</MenuItem>
|
|
|
+ <MenuItem value={2}>Sort by price: low to high</MenuItem>
|
|
|
+ <MenuItem value={3}>Sort by price: high to low</MenuItem>
|
|
|
+ </Select>
|
|
|
+ </FormControl>
|
|
|
+ </Box>
|
|
|
+ <Box flexGrow='1'>
|
|
|
+ <Grid container justifyContent='space-between'>
|
|
|
+ {[...goods[0]].slice((page - 1) * itemsPerPage, page * itemsPerPage)
|
|
|
+ .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%'>
|
|
|
+ <Pagination
|
|
|
+ count={count}
|
|
|
+ page={page}
|
|
|
+ onChange={handleChange}
|
|
|
+ defaultPage={1}
|
|
|
+ color="primary"
|
|
|
+ size="large"
|
|
|
+ showFirstButton
|
|
|
+ showLastButton
|
|
|
+ />
|
|
|
+ </Box>
|
|
|
+ </Box>
|
|
|
+ </Box>
|
|
|
+ : <GoodNotFound/>)
|
|
|
+ }
|
|
|
+ </>
|
|
|
+ )
|
|
|
}
|
|
|
const CGoods = connect(state => ({category: state.category}))(Goods)
|
|
|
|
|
@@ -210,19 +324,17 @@ const BlockGood = ({match:{params:{_id}}, getData}) => {
|
|
|
getData(_id)
|
|
|
},[_id, getData])
|
|
|
return(
|
|
|
- <Grid container justifyContent='space-between'>
|
|
|
- <CGoods _id={_id} />
|
|
|
- </Grid>
|
|
|
+ <CGoods key={_id} _id={_id} />
|
|
|
)
|
|
|
}
|
|
|
-export const CBlockGood= connect(null, {getData: actionFullCatById})(BlockGood)
|
|
|
+const CBlockGood= connect(null, {getData: actionFullCatById})(BlockGood)
|
|
|
|
|
|
const Products = () => {
|
|
|
return (
|
|
|
- <Grid xs={12} lg={9}>
|
|
|
+ <Grid xs={12} lg={9} item>
|
|
|
<Switch>
|
|
|
<Route path="/catalog/category/:_id" component={CBlockGood} />
|
|
|
- <Route path="*" component={Page404} />
|
|
|
+ <Route path="*" component={GoodNotFound} />
|
|
|
</Switch>
|
|
|
</Grid>
|
|
|
)
|