MyOrdersPage.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 minWidth='60px' maxWidth='60px' height='60px' borderRadius='10px' overflow='hidden' marginRight='20px'>
  55. <img style={{width: '100%', height: '100%', objectFit: 'cover'}}
  56. src={item?.good?.images && item.good.images[0].url ? backURL + '/' + item.good.images[0].url : imgNotFound}
  57. alt={'image'}/>
  58. </Box>
  59. }
  60. else if (index === 2) {
  61. return <Box sx={{width:'60px', height:'60px', border:'1px solid #616161', display: 'flex', justifyContent: 'center', alignItems: 'center', color: '#616161', borderRadius: '10px'}}>
  62. +{array.length - 2}
  63. </Box>}
  64. })
  65. }
  66. </Box>}
  67. </Box>
  68. </AccordionSummary>
  69. <AccordionDetails sx={{padding: '20px'}}>
  70. {data['orderGoods'] && data['orderGoods'].length > 0 ?
  71. <>
  72. <Grid container>
  73. <Grid item md={7}>
  74. <Typography
  75. color='#616161'
  76. variant='body1'
  77. letterSpacing='1px'
  78. textAlign='left'
  79. >
  80. Product
  81. </Typography>
  82. </Grid>
  83. <Grid item md={2}>
  84. <Typography
  85. color='#616161'
  86. variant='body1'
  87. letterSpacing='1px'
  88. textAlign='center'
  89. >
  90. Price
  91. </Typography>
  92. </Grid>
  93. <Grid item md={1}>
  94. <Typography
  95. color='#616161'
  96. variant='body1'
  97. letterSpacing='1px'
  98. textAlign='center'
  99. >
  100. Count
  101. </Typography>
  102. </Grid>
  103. <Grid item md={2}>
  104. <Typography
  105. color='#616161'
  106. variant='body1'
  107. letterSpacing='1px'
  108. textAlign='right'
  109. >
  110. Sum
  111. </Typography>
  112. </Grid>
  113. </Grid>
  114. <Divider sx={{margin: '10px 0'}}/>
  115. {data['orderGoods'].map(item => {
  116. return <Grid container alignItems='center' marginBottom='20px'>
  117. <Grid item md={7}>
  118. <Link style={{textDecoration: 'none', display: 'flex', alignItems: 'center', color: '#616161'}} to={`/good/${item?.good?._id}`}>
  119. <Box minWidth='60px' maxWidth='60px' height='60px' borderRadius='10px' overflow='hidden' marginRight='20px'>
  120. <img style={{width: '100%', height: '100%', objectFit: 'cover'}}
  121. src={item?.good?.images && item.good.images[0].url ? backURL + '/' + item.good.images[0].url : imgNotFound}
  122. alt={'image'}/>
  123. </Box>
  124. <Typography
  125. variant='body1'
  126. >
  127. {item.good?.name || 'product name'}
  128. </Typography>
  129. </Link>
  130. </Grid>
  131. <Grid item md={2}>
  132. <Typography
  133. color='#616161'
  134. variant='body1'
  135. letterSpacing='1px'
  136. textAlign='center'
  137. >
  138. {item?.price ? '$' + parseFloat(item.price).toFixed(2) : 'NaN'}
  139. </Typography>
  140. </Grid>
  141. <Grid item md={1}>
  142. <Typography
  143. color='#616161'
  144. variant='body1'
  145. letterSpacing='1px'
  146. textAlign='center'
  147. >
  148. {item?.count || '1'}
  149. </Typography>
  150. </Grid>
  151. <Grid item md={2}>
  152. <Typography
  153. color='#616161'
  154. variant='body1'
  155. letterSpacing='1px'
  156. textAlign='right'
  157. >
  158. {item?.price && item?.count ? '$'+parseFloat(item.price * item.count).toFixed(2) : 'NaN'}
  159. </Typography>
  160. </Grid>
  161. </Grid>
  162. })}
  163. <Divider sx={{margin: '-10px 0 10px 0'}}/>
  164. <Box display='flex' justifyContent='space-between'>
  165. <Typography
  166. variant='body1'
  167. color='#616161'
  168. >
  169. Total
  170. </Typography>
  171. <Typography
  172. variant='body1'
  173. color='#616161'
  174. >
  175. {data?.total ? '$'+parseFloat(data.total).toFixed(2) : 'NaN'}
  176. </Typography>
  177. </Box>
  178. </> :
  179. <Typography>Error</Typography>
  180. }
  181. </AccordionDetails>
  182. </Accordion>
  183. )
  184. }
  185. const MainOrders = ({itemsPerPage=10, orders, onFindOrders, onOrdersClear}) => {
  186. const [page, setPage] = useState(1)
  187. const [count, setCount] = useState(1)
  188. const handleChange = (event, value) => {
  189. setPage(value);
  190. }
  191. useEffect(() => {
  192. onOrdersClear()
  193. }, [onOrdersClear])
  194. useEffect(() => {
  195. if(orders?.orderResult && Object.entries(orders.orderResult).length > 0) {
  196. setCount(Math.ceil(Object.entries(orders.orderResult).length / itemsPerPage))
  197. }
  198. }, [orders])
  199. if(Object.entries(orders).length === 0) onFindOrders()
  200. return (
  201. <>
  202. {Object.entries(orders).length === 0 ?
  203. <Box sx={{height: '100%', width: '100%', display: 'flex', justifyContent:'center', alignItems:'center'}}><CircularProgress color="inherit"/></Box> :
  204. Object.entries(orders?.orderResult).length > 0 ?
  205. <Box>
  206. {Object.values(orders.orderResult).slice((page - 1) * itemsPerPage, page * itemsPerPage).map(item => <AccordionItem data={item}/>)}
  207. <Divider sx={{margin: '20px'}}/>
  208. <Box display='flex' justifyContent='center' width='100%'>
  209. <Pagination
  210. count={count}
  211. page={page}
  212. onChange={handleChange}
  213. defaultPage={1}
  214. color="primary"
  215. size="large"
  216. showFirstButton
  217. showLastButton
  218. />
  219. </Box>
  220. </Box>
  221. :
  222. <NotFoundBlock headerText={'OOPS! ORDERS CAN’T BE FOUND'} text={'No order has been made yet.'}/>
  223. }
  224. </>
  225. )
  226. }
  227. export const CMainOrders = connect(state=>({orders: state.myorders}), {onFindOrders: actionFullOrderFind, onOrdersClear: actionMyOrderClear})(MainOrders)
  228. const MyOrdersPage = () => {
  229. const matches = useMediaQuery('(max-width:768px)')
  230. return (
  231. <>
  232. <Breadcrumb links={['My orders']} />
  233. <main style={{backgroundColor: "#f3f3f3", padding: matches ? "20px 0" : "50px 0", minHeight:'300px'}}>
  234. <Container maxWidth="lg" sx={{position:'relative'}}>
  235. <CMainOrders />
  236. </Container>
  237. </main>
  238. </>
  239. )
  240. }
  241. export default MyOrdersPage