ProductPage.jsx 8.3 KB

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