MyOrdersPage.jsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. {console.log(item.good.images[0].url)}
  55. return <Box minWidth='60px' maxWidth='60px' height='60px' borderRadius='10px' overflow='hidden' marginRight='20px'>
  56. <img style={{width: '100%', height: '100%', objectFit: 'cover'}}
  57. src={item.good.images && item.good.images[0].url ? backURL + '/' + item.good.images[0].url : imgNotFound}
  58. alt={'image'}/>
  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 minWidth='60px' maxWidth='60px' height='60px' borderRadius='10px' overflow='hidden' marginRight='20px'>
  121. <img style={{width: '100%', height: '100%', objectFit: 'cover'}}
  122. src={item.good.images && item.good.images[0].url ? backURL + '/' + item.good.images[0].url : imgNotFound}
  123. alt={'image'}/>
  124. </Box>
  125. <Typography
  126. variant='body1'
  127. >
  128. {item.good?.name || 'product name'}
  129. </Typography>
  130. </Link>
  131. </Grid>
  132. <Grid item md={2}>
  133. <Typography
  134. color='#616161'
  135. variant='body1'
  136. letterSpacing='1px'
  137. textAlign='center'
  138. >
  139. {item?.price ? '$' + parseFloat(item.price).toFixed(2) : 'NaN'}
  140. </Typography>
  141. </Grid>
  142. <Grid item md={1}>
  143. <Typography
  144. color='#616161'
  145. variant='body1'
  146. letterSpacing='1px'
  147. textAlign='center'
  148. >
  149. {item?.count || '1'}
  150. </Typography>
  151. </Grid>
  152. <Grid item md={2}>
  153. <Typography
  154. color='#616161'
  155. variant='body1'
  156. letterSpacing='1px'
  157. textAlign='right'
  158. >
  159. {item?.price && item?.count ? '$'+parseFloat(item.price * item.count).toFixed(2) : 'NaN'}
  160. </Typography>
  161. </Grid>
  162. </Grid>
  163. })}
  164. <Divider sx={{margin: '-10px 0 10px 0'}}/>
  165. <Box display='flex' justifyContent='space-between'>
  166. <Typography
  167. variant='body1'
  168. color='#616161'
  169. >
  170. Total
  171. </Typography>
  172. <Typography
  173. variant='body1'
  174. color='#616161'
  175. >
  176. {data?.total ? '$'+parseFloat(data.total).toFixed(2) : 'NaN'}
  177. </Typography>
  178. </Box>
  179. </> :
  180. <Typography>Error</Typography>
  181. }
  182. </AccordionDetails>
  183. </Accordion>
  184. )
  185. }
  186. const MainOrders = ({itemsPerPage=10, orders, onFindOrders, onOrdersClear}) => {
  187. const [page, setPage] = useState(1)
  188. const [count, setCount] = useState(1)
  189. const handleChange = (event, value) => {
  190. setPage(value);
  191. }
  192. useEffect(() => {
  193. onOrdersClear()
  194. }, [onOrdersClear])
  195. useEffect(() => {
  196. if(orders?.orderResult && Object.entries(orders.orderResult).length > 0) {
  197. setCount(Math.ceil(Object.entries(orders.orderResult).length / itemsPerPage))
  198. }
  199. }, [orders])
  200. if(Object.entries(orders).length === 0) onFindOrders()
  201. return (
  202. <>
  203. {Object.entries(orders).length === 0 ?
  204. <Box sx={{height: '100%', width: '100%', display: 'flex', justifyContent:'center', alignItems:'center'}}><CircularProgress color="inherit"/></Box> :
  205. Object.entries(orders?.orderResult).length > 0 ?
  206. <Box>
  207. {Object.values(orders.orderResult).slice((page - 1) * itemsPerPage, page * itemsPerPage).map(item => <AccordionItem data={item}/>)}
  208. <Divider sx={{margin: '20px'}}/>
  209. <Box display='flex' justifyContent='center' width='100%'>
  210. <Pagination
  211. count={count}
  212. page={page}
  213. onChange={handleChange}
  214. defaultPage={1}
  215. color="primary"
  216. size="large"
  217. showFirstButton
  218. showLastButton
  219. />
  220. </Box>
  221. </Box>
  222. :
  223. <NotFoundBlock headerText={'OOPS! ORDERS CAN’T BE FOUND'} text={'No order has been made yet.'}/>
  224. }
  225. </>
  226. )
  227. }
  228. export const CMainOrders = connect(state=>({orders: state.myorders}), {onFindOrders: actionFullOrderFind, onOrdersClear: actionMyOrderClear})(MainOrders)
  229. const MyOrdersPage = () => {
  230. const matches = useMediaQuery('(max-width:768px)')
  231. return (
  232. <>
  233. <Breadcrumb links={['My orders']} />
  234. <main style={{backgroundColor: "#f3f3f3", padding: matches ? "20px 0" : "50px 0", minHeight:'300px'}}>
  235. <Container maxWidth="lg" sx={{position:'relative'}}>
  236. <CMainOrders />
  237. </Container>
  238. </main>
  239. </>
  240. )
  241. }
  242. export default MyOrdersPage