MyOrdersPage.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import Breadcrumb from "../components/Breadcrumbs";
  2. import {
  3. Accordion,
  4. AccordionDetails,
  5. AccordionSummary, Box,
  6. CircularProgress,
  7. Container, Divider, Grid, Pagination,
  8. Typography,
  9. useMediaQuery
  10. } from "@mui/material";
  11. import {connect} from "react-redux";
  12. import {actionFullOrderFind} from "../actions/ActionOrderFind";
  13. import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
  14. import {timeCalc} from "./ProductPage";
  15. import {backURL} from "../actions/PathDB";
  16. import {actionMyOrderClear} from "../reducers/MyOrdersReducer";
  17. import {useEffect, useState} from "react";
  18. import imgNotFound from "../img/catalog/imgNotFound.png";
  19. import Link from "react-router-dom/es/Link";
  20. import {NotFoundBlock} from "../components/NotFoundBlock";
  21. const AccordionHeaderText = ({columnText, content}) => {
  22. return (
  23. <Box display='flex' flexDirection='column' justifyContent='space-between'>
  24. <Typography
  25. variant='body2'
  26. color='#616161'
  27. marginBottom='20px'
  28. >
  29. {columnText}
  30. </Typography>
  31. <Typography
  32. variant='body1'
  33. >
  34. {content}
  35. </Typography>
  36. </Box>
  37. )
  38. }
  39. const AccordionItem = ({data}) => {
  40. const time = timeCalc(+data['createdAt'])
  41. const [status, setStatus] = useState(false);
  42. return (
  43. <Accordion onChange={() => setStatus(!status)}>
  44. <AccordionSummary
  45. expandIcon={<ExpandMoreIcon />}
  46. >
  47. <Divider orientation="vertical" flexItem sx={{backgroundColor: data['total'] ? '#7cd545': '#ad2222', width:'5px', borderRadius: '3px', boxShadow: 'none'}}/>
  48. <Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', padding: '10px 20px'}}>
  49. <AccordionHeaderText columnText={`№ ${data['_id']} from ${time}`} content={data['total'] ? 'Completed' : 'Canceled'}/>
  50. {!status && <AccordionHeaderText columnText={'Order price'} content={data['total'] ? `$${data['total']}` : 'null'}/>}
  51. {!status && <Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '200px'}}>
  52. {data['orderGoods'] && data['orderGoods'].map((item, index, array) => {
  53. if (index < 2) {
  54. return <Box sx={{width:'60px', height:'60px'}}>
  55. <img src={item?.good?.images && Array.isArray(item.good.images) ? `${backURL}/${item.good.images[0].url}` : imgNotFound}
  56. alt={'image'}
  57. style={{width: '100%', height: '100%', objectFit:'cover'}}
  58. />
  59. </Box>
  60. }
  61. else if (index === 2) {
  62. return <Box sx={{width:'60px', height:'60px', border:'1px solid #616161', display: 'flex', justifyContent: 'center', alignItems: 'center', color: '#616161', borderRadius: '10px'}}>
  63. +{array.length - 2}
  64. </Box>}
  65. })
  66. }
  67. </Box>}
  68. </Box>
  69. </AccordionSummary>
  70. <AccordionDetails sx={{padding: '20px'}}>
  71. {data['orderGoods'] && data['orderGoods'].length > 0 ?
  72. <>
  73. <Grid container>
  74. <Grid item md={7}>
  75. <Typography
  76. color='#616161'
  77. variant='body1'
  78. letterSpacing='1px'
  79. textAlign='left'
  80. >
  81. Product
  82. </Typography>
  83. </Grid>
  84. <Grid item md={2}>
  85. <Typography
  86. color='#616161'
  87. variant='body1'
  88. letterSpacing='1px'
  89. textAlign='center'
  90. >
  91. Price
  92. </Typography>
  93. </Grid>
  94. <Grid item md={1}>
  95. <Typography
  96. color='#616161'
  97. variant='body1'
  98. letterSpacing='1px'
  99. textAlign='center'
  100. >
  101. Count
  102. </Typography>
  103. </Grid>
  104. <Grid item md={2}>
  105. <Typography
  106. color='#616161'
  107. variant='body1'
  108. letterSpacing='1px'
  109. textAlign='right'
  110. >
  111. Sum
  112. </Typography>
  113. </Grid>
  114. </Grid>
  115. <Divider sx={{margin: '10px 0'}}/>
  116. {data['orderGoods'].map(item => {
  117. return <Grid container alignItems='center' marginBottom='20px'>
  118. <Grid item md={7}>
  119. <Link style={{textDecoration: 'none', display: 'flex', alignItems: 'center', color: '#616161'}} to={`/good/${item?.good?._id}`}>
  120. <Box sx={{width:'60px', height:'60px'}} marginRight='10px'>
  121. <img src={item?.good?.images && Array.isArray(item.good.images) ? `${backURL}/${item.good.images[0].url}` : imgNotFound}
  122. alt={'image'}
  123. style={{width: '100%', height: '100%', objectFit:'cover'}}
  124. />
  125. </Box>
  126. <Typography
  127. variant='body1'
  128. >
  129. {item.good?.name || 'product name'}
  130. </Typography>
  131. </Link>
  132. </Grid>
  133. <Grid item md={2}>
  134. <Typography
  135. color='#616161'
  136. variant='body1'
  137. letterSpacing='1px'
  138. textAlign='center'
  139. >
  140. {item?.price ? '$' + parseFloat(item.price).toFixed(2) : 'NaN'}
  141. </Typography>
  142. </Grid>
  143. <Grid item md={1}>
  144. <Typography
  145. color='#616161'
  146. variant='body1'
  147. letterSpacing='1px'
  148. textAlign='center'
  149. >
  150. {item?.count || '1'}
  151. </Typography>
  152. </Grid>
  153. <Grid item md={2}>
  154. <Typography
  155. color='#616161'
  156. variant='body1'
  157. letterSpacing='1px'
  158. textAlign='right'
  159. >
  160. {item?.price && item?.count ? '$'+parseFloat(item.price * item.count).toFixed(2) : 'NaN'}
  161. </Typography>
  162. </Grid>
  163. </Grid>
  164. })}
  165. <Divider sx={{margin: '-10px 0 10px 0'}}/>
  166. <Box display='flex' justifyContent='space-between'>
  167. <Typography
  168. variant='body1'
  169. color='#616161'
  170. >
  171. Total
  172. </Typography>
  173. <Typography
  174. variant='body1'
  175. color='#616161'
  176. >
  177. {data?.total ? '$'+parseFloat(data.total).toFixed(2) : 'NaN'}
  178. </Typography>
  179. </Box>
  180. </> :
  181. <Typography>Error</Typography>
  182. }
  183. </AccordionDetails>
  184. </Accordion>
  185. )
  186. }
  187. const MyOrdersPage = ({orders, onFindOrders, onOrdersClear}) => {
  188. const itemsPerPage = 10
  189. const [page, setPage] = useState(1)
  190. const [count, setCount] = useState(1)
  191. const handleChange = (event, value) => {
  192. setPage(value);
  193. }
  194. useEffect(() => {
  195. onOrdersClear()
  196. }, [onOrdersClear])
  197. useEffect(() => {
  198. if(orders?.orderResult && Object.entries(orders.orderResult).length > 0) {
  199. setCount(Math.ceil(Object.entries(orders.orderResult).length / itemsPerPage))
  200. }
  201. }, [orders])
  202. if(Object.entries(orders).length === 0) onFindOrders()
  203. const matches = useMediaQuery('(max-width:768px)')
  204. return (
  205. <>
  206. <Breadcrumb links={['My orders']} />
  207. <main style={{backgroundColor: "#f3f3f3", padding: matches ? "20px 0" : "50px 0", minHeight:'300px'}}>
  208. <Container maxWidth="lg" sx={{position:'relative'}}>
  209. {Object.entries(orders).length === 0 ?
  210. <Box sx={{height: '100%', width: '100%', display: 'flex', justifyContent:'center', alignItems:'center'}}><CircularProgress color="inherit"/></Box> :
  211. Object.entries(orders?.orderResult).length > 0 ?
  212. <Box>
  213. {Object.values(orders.orderResult).slice((page - 1) * itemsPerPage, page * itemsPerPage).map(item => <AccordionItem data={item}/>)}
  214. <Divider sx={{margin: '20px'}}/>
  215. <Box display='flex' justifyContent='center' width='100%'>
  216. <Pagination
  217. count={count}
  218. page={page}
  219. onChange={handleChange}
  220. defaultPage={1}
  221. color="primary"
  222. size="large"
  223. showFirstButton
  224. showLastButton
  225. />
  226. </Box>
  227. </Box>
  228. :
  229. <NotFoundBlock headerText={'OOPS! ORDERS CAN’T BE FOUND'} text={'No order has been made yet.'}/>
  230. }
  231. </Container>
  232. </main>
  233. </>
  234. )
  235. }
  236. const CMyOrdersPage = connect(state=>({orders: state.myorders}), {onFindOrders: actionFullOrderFind, onOrdersClear: actionMyOrderClear})(MyOrdersPage)
  237. export default CMyOrdersPage