ProductPage.jsx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import {useEffect, useState} from "react";
  2. import {connect} from "react-redux";
  3. import {Box, Button, CircularProgress, Container, Divider, Grid, Paper, Typography, useMediaQuery} from "@mui/material";
  4. import {actionGoodFindOne} from "../actions/ActionGoodFind";
  5. import Switch from "react-router-dom/es/Switch";
  6. import Route from "react-router-dom/es/Route";
  7. import Page404 from "./404Page";
  8. import Breadcrumb from "../components/Breadcrumbs";
  9. import {SetCount} from "../components/SetCount";
  10. import FavoriteBorderIcon from "@mui/icons-material/FavoriteBorder";
  11. import Link from "react-router-dom/es/Link";
  12. import {actionCardChange} from "../reducers/CartReducer";
  13. import {actionWishListAdd, actionWishListRemove} from "../reducers/WishListReducer";
  14. import FavoriteIcon from "@mui/icons-material/Favorite";
  15. import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
  16. import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
  17. import Carousel from 'react-material-ui-carousel'
  18. import {backURL} from "../actions/PathDB";
  19. import imgNotFound from "../img/catalog/imgNotFound.png";
  20. export const timeCalc = (createdAt) => {
  21. let formattedTime;
  22. let date = new Date(+createdAt);
  23. let year = date.getFullYear();
  24. let month = "0" + (date.getMonth()+1);
  25. let day = "0" + date.getDate();
  26. let hours = "0" + date.getHours();
  27. let minutes = "0" + date.getMinutes();
  28. let seconds = "0" + date.getSeconds();
  29. formattedTime = day.substr(-2) + '.' + month.substr(-2) + '.' + year +
  30. ' ' + hours.substr(-2) + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
  31. return formattedTime;
  32. }
  33. const ImageItem = ({images}) => {
  34. return (
  35. <img src={images && images.url ? backURL + '/' + images.url : imgNotFound} alt={images?.originalFileName ? images.originalFileName.split('.')[0] : 'image'}/>
  36. )
  37. }
  38. const CarouselItem = ({images}) => {
  39. return (
  40. <Carousel
  41. navButtonsProps={{
  42. style: {
  43. backgroundColor: 'transparent',
  44. color: '#000',
  45. borderRadius: 0
  46. }
  47. }}
  48. NextIcon={<ArrowForwardIosIcon/>}
  49. PrevIcon={<ArrowBackIosNewIcon/>}
  50. fullHeightHover={true}
  51. >
  52. {
  53. images.map((item, index) => <Box key={index} sx={{width: '100%', display: 'flex', justifyContent: 'center', height: '340px'}}><ImageItem key={item._id} images={item} /></Box>)
  54. }
  55. </Carousel>
  56. )
  57. }
  58. const ProductTitle = ({title}) => {
  59. return (
  60. <Typography
  61. variant='h4'
  62. fontFamily='sarif'
  63. letterSpacing='4px'
  64. >
  65. {title || 'PRODUCT TITLE'}
  66. </Typography>
  67. )
  68. }
  69. const ProductPrice = ({price}) => {
  70. return (
  71. <Typography
  72. variant='h5'
  73. margin='30px 0'
  74. >
  75. ${price ? parseFloat(price).toFixed(2) : 0 }
  76. </Typography>
  77. )
  78. }
  79. const ProductDescription = ({description}) => {
  80. return (
  81. <Typography
  82. fontSize='17px'
  83. letterSpacing='1px'
  84. lineHeight='1.7em'
  85. color='#616161'
  86. fontWeight='300'
  87. >
  88. {description || 'PRODUCT DESCRIPTION'}
  89. </Typography>
  90. )
  91. }
  92. const ProductTags = ({title, subtitle}) => {
  93. return (
  94. <Typography
  95. variant='body2'
  96. color='#616161'
  97. fontWeight='300'
  98. marginBottom='10px'
  99. >
  100. {title}: {Array.isArray(subtitle) ? subtitle.map((item, index) => <span key={index}>{item}{subtitle.length-1 !== index && ", " } </span>) : subtitle}
  101. </Typography>
  102. )
  103. }
  104. const AddToCart = ({cart, good, addToCart}) => {
  105. let [count, setCount] = useState(cart[good?._id]?.count || 1)
  106. useEffect(() => {
  107. setCount(cart[good?._id]?.count || 1)
  108. },[cart])
  109. console.log(count)
  110. return (
  111. <Box width='100%' backgroundColor='#fff' padding='30px'>
  112. <Grid container justifyContent='space-between'>
  113. <Grid xs={5} item>
  114. <SetCount defaultValue={count} onCount={value => setCount(value)}/>
  115. </Grid>
  116. <Grid xs={5} item>
  117. <Button
  118. sx={{height: '55px', width: '100%', borderRadius: '0', color: '#000', borderColor: '#000', fontSize: '20px', fontWeight: '300'}}
  119. variant="outlined"
  120. color={"inherit"}
  121. onClick={() => addToCart(good, count)}
  122. >
  123. {good._id in cart ? 'CHANGE CART' : 'ADD TO CART'}
  124. </Button>
  125. </Grid>
  126. </Grid>
  127. </Box>
  128. )
  129. }
  130. const CAddToCart = connect(state=>({cart: state.cart}), {addToCart: actionCardChange})(AddToCart)
  131. const AddToWishList = ({good={}, wishlist ,onAddToWishList, onWishListRemove}) => {
  132. const flag = good?._id in wishlist
  133. return (
  134. <Button size="small"
  135. color="inherit"
  136. sx={{paddingLeft: '0', margin: '30px 0'}}
  137. onClick={() => {flag ? onWishListRemove(good) : onAddToWishList(good)}}
  138. >
  139. <Typography
  140. color='#000'
  141. display='flex'
  142. alignItems='center'
  143. fontSize='13px'
  144. fontWeight='600'
  145. letterSpacing='2px'
  146. >
  147. {flag ?
  148. <><FavoriteIcon sx={{marginRight: '10px'}}/> REMOVE FROM WISHLIST</>:
  149. <><FavoriteBorderIcon sx={{marginRight: '10px'}}/> ADD TO WISHLIST</>
  150. }
  151. </Typography>
  152. </Button>
  153. )
  154. }
  155. const CAddToWishList = connect(state => ({wishlist: state.wishlist}), {onAddToWishList: actionWishListAdd, onWishListRemove: actionWishListRemove})(AddToWishList)
  156. const Goods = ({good}) => {
  157. const matches = useMediaQuery('(max-width:768px)');
  158. return (
  159. good && Object.values(good).length > 0 ?
  160. <Grid container justifyContent='space-around' padding={matches ? "20px 0" : "50px 0"}>
  161. <Grid xs={12} md={6} item padding='5px 70px 5px 10px'>
  162. {Array.isArray(good?.images) && good?.images.length > 1 ? <CarouselItem images={good?.images}/> :
  163. <Box sx={{width: '100%', display: 'flex', justifyContent: 'center', height: '340px'}}>
  164. <ImageItem images={Array.isArray(good?.images) && good?.images[0]}/>
  165. </Box>}
  166. <Divider sx={{margin: '20px 0'}}/>
  167. <ProductDescription description={good?.description}/>
  168. </Grid>
  169. <Grid xs={12} md={6} item padding='5px 110px 5px 10px'>
  170. <ProductTitle title={good?.name}/>
  171. <ProductPrice price={good?.price}/>
  172. <CAddToCart good={good}/>
  173. <CAddToWishList good={good}/>
  174. <Box>
  175. {good?._id && <ProductTags key={'SKU'} title={'SKU'} subtitle={good?._id}/>}
  176. {Array.isArray(good?.categories) &&
  177. <ProductTags key={'CATEGORY'} title={'CATEGORY'} subtitle={good?.categories.map(item => {
  178. return <Link key={item?._id} style={{color: "#000", textDecoration: 'none'}}
  179. to={`/catalog/category/${item?._id}`}>{item?.name}</Link>
  180. })}/>
  181. }
  182. {good?.createdAt && <ProductTags key={'TIMEOFCREATION'} title={'TIME OF CREATION'}
  183. subtitle={timeCalc(good?.createdAt)}/>}
  184. </Box>
  185. </Grid>
  186. </Grid>:
  187. <Box sx={{height: '100%', width: '100%', display: 'flex', justifyContent:'center', alignItems:'center'}}><CircularProgress color="inherit"/></Box>
  188. )
  189. }
  190. const CGoods = connect(state => ({good: state.promise['goodFindOne']?.payload}))(Goods)
  191. const BlockProduct = ({match:{params:{_id}}, getData}) => {
  192. useEffect(() => {
  193. getData(_id)
  194. },[_id, getData])
  195. return(
  196. <>
  197. <main style={{backgroundColor: "#f3f3f3", minHeight:'300px'}}>
  198. <Breadcrumb links={['good']}/>
  199. <Container maxWidth="lg">
  200. <CGoods key={_id} />
  201. </Container>
  202. </main>
  203. </>
  204. )
  205. }
  206. const CBlockProduct = connect(null, {getData: actionGoodFindOne})(BlockProduct)
  207. const ProductPage = () => {
  208. return (
  209. <Switch>
  210. <Route path="/good/:_id" component={CBlockProduct} />
  211. <Route path="*" component={Page404} />
  212. </Switch>
  213. )
  214. }
  215. export default ProductPage
  216. //TODO MOBILE VERSION