Goods.jsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. import React from 'react';
  2. import {
  3. Box,
  4. Button,
  5. Card,
  6. CardActionArea,
  7. CardActions,
  8. CardContent,
  9. CardMedia, Divider,
  10. FormControl,
  11. Grid, MenuItem, Pagination, Select,
  12. Typography
  13. } from "@mui/material";
  14. import Link from "react-router-dom/es/Link";
  15. import {backURL} from "../../actions/PathDB";
  16. import imgNotFound from "../../img/catalog/imgNotFound.png";
  17. import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
  18. import AddShoppingCartIcon from "@mui/icons-material/AddShoppingCart";
  19. import FavoriteIcon from "@mui/icons-material/Favorite";
  20. import FavoriteBorderIcon from "@mui/icons-material/FavoriteBorder";
  21. import {connect} from "react-redux";
  22. import {actionCardRemove, actionCartAdd} from "../../reducers/CartReducer";
  23. import {actionWishListAdd, actionWishListRemove} from "../../reducers/WishListReducer";
  24. import {useEffect, useState} from "react";
  25. import {NotFoundBlock} from "../../components/NotFoundBlock";
  26. import {actionFullCatById} from "../../actions/ActionCategory";
  27. import Switch from "react-router-dom/es/Switch";
  28. import Route from "react-router-dom/es/Route";
  29. const GoodCard = ({good:{_id, name, description, price, images}={},
  30. wishlist={},
  31. cart={},
  32. onCartAdd,
  33. onWishListAdd,
  34. onCartRemove,
  35. onWishListRemove}) => {
  36. return (
  37. <Grid xs={12} lg={4} item margin='20px 0'>
  38. <Card
  39. sx={{
  40. maxWidth: 345,
  41. height: '100%',
  42. display: 'flex',
  43. flexDirection: 'column',
  44. margin: 'auto 20px'
  45. }}
  46. >
  47. <CardActionArea
  48. sx={{
  49. padding: '0',
  50. flexGrow: '1',
  51. position: 'relative'
  52. }}
  53. >
  54. <Link
  55. to={`/good/${_id}`}
  56. style={{position: 'relative', textDecoration: 'none'}}
  57. >
  58. <CardMedia
  59. sx={{marginBottom: '20px', marginTop: '20px'}}
  60. component="img"
  61. height="230"
  62. image={images && images[0]?.url ? `${backURL}/${images[0]?.url}` : imgNotFound}
  63. alt="Good title image"
  64. />
  65. <CardContent
  66. sx={{
  67. display: 'flex',
  68. flexDirection: 'column',
  69. height: '200px',
  70. justifyContent: 'space-between'
  71. }}
  72. >
  73. <Typography
  74. textAlign='center'
  75. fontFamily='sarif'
  76. letterSpacing='2px'
  77. marginBottom='20px'
  78. fontSize='19px'
  79. sx={{textTransform: 'uppercase', flexGrow: '1'}}
  80. color='#000'
  81. >
  82. {name.length > 30 ? name.split(' ').splice(0, 6).join(' ') : name}
  83. </Typography>
  84. <Typography
  85. textAlign='center'
  86. variant="body2"
  87. color='#616161'
  88. marginBottom='20px'
  89. sx={{ flexGrow: '0'}}
  90. >
  91. {description && description.length > 60 ?
  92. 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' :
  93. description
  94. }
  95. </Typography>
  96. <Typography
  97. textAlign='center'
  98. variant="h5"
  99. color="#000"
  100. sx={{ flexGrow: '0'}}>
  101. $ {parseFloat(price || 0).toFixed(2)}
  102. </Typography>
  103. </CardContent>
  104. </Link>
  105. </CardActionArea>
  106. <CardActions sx={{flexGrow: '0', justifyContent: 'space-between'}}>
  107. <Button
  108. onClick={() => {
  109. _id in cart ?
  110. onCartRemove({_id, name, price, images})
  111. : onCartAdd({_id, name, price, images})}
  112. }
  113. size="small"
  114. color="primary"
  115. >
  116. {_id in cart ?
  117. <ShoppingCartIcon/>
  118. : <AddShoppingCartIcon />
  119. }
  120. </Button>
  121. <Button
  122. onClick={() => {
  123. _id in wishlist ?
  124. onWishListRemove({_id, name, price, images})
  125. : onWishListAdd({_id, name, price, images})}
  126. }
  127. size="small"
  128. color="primary"
  129. >
  130. {_id in wishlist ?
  131. <FavoriteIcon/>
  132. : <FavoriteBorderIcon />
  133. }
  134. </Button>
  135. </CardActions>
  136. </Card>
  137. </Grid>
  138. )
  139. }
  140. const CGoodCard = connect(state => ({
  141. wishlist: state.wishlist,
  142. cart: state.cart}),
  143. {
  144. onCartAdd: actionCartAdd,
  145. onWishListAdd: actionWishListAdd,
  146. onCartRemove: actionCardRemove,
  147. onWishListRemove: actionWishListRemove})
  148. (GoodCard)
  149. const Goods = ({_id, category={}}) => {
  150. const itemsPerPage = 9
  151. const [page, setPage] = useState(1)
  152. const [count, setCount] = useState(1)
  153. const [goods, setGoods] = useState([])
  154. const [sort, setSort] = useState(0)
  155. const sortDefault = () => {
  156. setGoods([goods[0].sort((a, b) => a['name'] > b['name'] ? 1 : -1)])
  157. }
  158. const sortLatest = () => {
  159. setGoods([goods[0].sort((a, b) => b['createdAt'] > a['createdAt'] ? 1 : -1)])
  160. }
  161. const sortLowToHigh = () => {
  162. setGoods([goods[0].sort((a, b) => a['price'] > b['price'] ? 1 : -1)])
  163. }
  164. const sortHighToLow = () => {
  165. setGoods([goods[0].sort((a, b) => b['price'] > a['price'] ? 1 : -1)])
  166. }
  167. const handleChange = (event, value) => {
  168. setPage(value);
  169. }
  170. const handleChangeSelect = (event) => {
  171. setSort(event.target.value);
  172. if (event.target.value === 0) sortDefault()
  173. else if (event.target.value === 1) sortLatest()
  174. else if (event.target.value === 2) sortLowToHigh()
  175. else if (event.target.value === 3) sortHighToLow()
  176. }
  177. useEffect(() => {
  178. let arr = (Object.values(category) || []).map(item => {
  179. if (item['_id'] === _id) {
  180. if (Array.isArray(item?.goods) && item?.goods.length > 0) {
  181. setCount(Math.ceil(item.goods.length / itemsPerPage))
  182. return item.goods
  183. }
  184. }
  185. else if(Array.isArray(item['subCategories'])) {
  186. let arr = item['subCategories'].map(subItem => {
  187. if (subItem['_id'] === _id) {
  188. if (Array.isArray(subItem?.goods) && subItem?.goods.length > 0) {
  189. setCount(Math.ceil(subItem.goods.length / itemsPerPage))
  190. return subItem.goods
  191. }
  192. }
  193. else if(Array.isArray(subItem['subCategories'])) {
  194. let arr = subItem['subCategories'].map(subSubItem => {
  195. if (subSubItem['_id'] === _id) {
  196. if (Array.isArray(subSubItem?.goods) && subSubItem?.goods.length > 0) {
  197. setCount(Math.ceil(subSubItem.goods.length / itemsPerPage))
  198. console.log(subSubItem.goods)
  199. return subSubItem.goods
  200. }
  201. }
  202. else {
  203. return 0
  204. }
  205. }).filter(item => item)
  206. return arr.length > 0 ? [...arr[0]] : 0
  207. }
  208. else {
  209. return 0
  210. }
  211. }).filter(item => item)
  212. return arr.length > 0 ? [...arr[0]] : 0
  213. }
  214. else {
  215. return 0
  216. }
  217. }).filter(item => item)
  218. setGoods(arr)
  219. }, [_id, category])
  220. return (
  221. <>
  222. {(goods.length > 0 && goods[0] !== undefined ?
  223. <Box
  224. sx={{height:'100%',
  225. display: 'flex',
  226. flexDirection: 'column',
  227. justifyContent: 'space-between'
  228. }}
  229. >
  230. <Box
  231. display='flex'
  232. alignItems='center'
  233. justifyContent='space-between'
  234. padding='0 20px'
  235. >
  236. <Typography
  237. variant='body1'
  238. color='#616161'
  239. letterSpacing='1px'
  240. >
  241. SHOWING {goods[0].length > itemsPerPage ? `${((page-1) * itemsPerPage)+1} -
  242. ${page * itemsPerPage > goods[0].length ? goods[0].length : page * itemsPerPage}` :
  243. goods[0].length} OF {goods[0].length} RESULTS
  244. </Typography>
  245. <FormControl
  246. variant="standard"
  247. >
  248. <Select
  249. labelId="demo-simple-select-label"
  250. id="demo-simple-select"
  251. value={sort}
  252. label="Sort"
  253. onChange={handleChangeSelect}
  254. sx={{textTransform: 'uppercase', color: '#616161'}}
  255. >
  256. <MenuItem value={0}>Default sorting</MenuItem>
  257. <MenuItem value={1}>Sort by latest</MenuItem>
  258. <MenuItem value={2}>Sort by price: low to high</MenuItem>
  259. <MenuItem value={3}>Sort by price: high to low</MenuItem>
  260. </Select>
  261. </FormControl>
  262. </Box>
  263. <Box
  264. flexGrow='1'
  265. >
  266. <Grid
  267. container
  268. justifyContent='space-between'
  269. >
  270. {[...goods[0]].slice((page - 1) * itemsPerPage, page * itemsPerPage)
  271. .map(good => <CGoodCard key={good['_id']} good={good}/>)
  272. }
  273. </Grid>
  274. </Box>
  275. <Box width='100%' flexGrow='0'>
  276. <Divider sx={{margin: '20px'}}/>
  277. <Box
  278. display='flex'
  279. justifyContent='center'
  280. width='100%'
  281. >
  282. <Pagination
  283. count={count}
  284. page={page}
  285. onChange={handleChange}
  286. defaultPage={1}
  287. color="primary"
  288. size="large"
  289. showFirstButton
  290. showLastButton
  291. />
  292. </Box>
  293. </Box>
  294. </Box>
  295. : <NotFoundBlock marginTop={'-50px'}/>)
  296. }
  297. </>
  298. )
  299. }
  300. const CGoods = connect(state => ({category: state.category}))(Goods)
  301. const BlockGood = ({match:{params:{_id}}, getData}) => {
  302. useEffect(() => {
  303. getData(_id)
  304. },[_id, getData])
  305. return(
  306. <CGoods key={_id} _id={_id} />
  307. )
  308. }
  309. const CBlockGood= connect(null, {getData: actionFullCatById})(BlockGood)
  310. export const Products = () => {
  311. return (
  312. <Grid xs={12} lg={9} item>
  313. <Switch>
  314. <Route path="/catalog/category/:_id" component={CBlockGood} />
  315. <Route path="*" component={NotFoundBlock} />
  316. </Switch>
  317. </Grid>
  318. )
  319. }