Goods.jsx 13 KB

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