Bladeren bron

create my orders pages

Alex 2 jaren geleden
bovenliggende
commit
c03122e25a

+ 10 - 1
src/actions/ActionOrderFind.js

@@ -1,7 +1,8 @@
 import {actionPromise} from "../reducers/PromiseReducer";
 import {gql} from "./PathDB";
+import {actionMyOrder} from "../reducers/MyOrdersReducer";
 
-export const actionOrderFind = () => {
+const actionOrderFind = () => {
     return actionPromise('orderFind', gql(`query orderFind {
         OrderFind(query:"[{}]") {
             _id total createdAt orderGoods{
@@ -15,3 +16,11 @@ export const actionOrderFind = () => {
     }`)
     )
 }
+
+export const actionFullOrderFind = () =>
+    async dispatch => {
+        let value = await dispatch(actionOrderFind())
+        if (value){
+            dispatch(actionMyOrder(value))
+        }
+    }

+ 236 - 6
src/pages/MyOrdersPage.jsx

@@ -1,15 +1,245 @@
 import Breadcrumb from "../components/Breadcrumbs";
-import {useMediaQuery} from "@mui/material";
+import {
+    Accordion,
+    AccordionDetails,
+    AccordionSummary, Box,
+    CircularProgress,
+    Container, Divider, Grid, Pagination,
+    Typography,
+    useMediaQuery
+} from "@mui/material";
+import {connect} from "react-redux";
+import {actionFullOrderFind} from "../actions/ActionOrderFind";
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import {timeCalc} from "./ProductPage";
+import {backURL} from "../actions/PathDB";
+import {actionMyOrderClear} from "../reducers/MyOrdersReducer";
+import {useEffect, useState} from "react";
+import imgNotFound from "../img/catalog/imgNotFound.png";
+import Link from "react-router-dom/es/Link";
+import {NotFoundBlock} from "../components/NotFoundBlock";
 
-const MyOrdersPage = () => {
-    const matches = useMediaQuery('(max-width:768px)');
+const AccordionHeaderText = ({columnText, content}) => {
+    return (
+        <Box display='flex' flexDirection='column' justifyContent='space-between'>
+            <Typography
+                variant='body2'
+                color='#616161'
+                marginBottom='20px'
+            >
+                {columnText}
+            </Typography>
+            <Typography
+                variant='body1'
+            >
+                {content}
+            </Typography>
+        </Box>
+    )
+}
+const AccordionItem = ({data}) => {
+    const time = timeCalc(+data['createdAt'])
+    const [status, setStatus] = useState(false);
+
+    return (
+        <Accordion onChange={() => setStatus(!status)}>
+            <AccordionSummary
+                expandIcon={<ExpandMoreIcon />}
+            >
+                <Divider orientation="vertical" flexItem sx={{backgroundColor: data['total'] ? '#7cd545': '#ad2222', width:'5px', borderRadius: '3px', boxShadow: 'none'}}/>
+                <Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', padding: '10px 20px'}}>
+                    <AccordionHeaderText columnText={`№ ${data['_id']} from ${time}`} content={data['total'] ? 'Completed' : 'Canceled'}/>
+                    {!status && <AccordionHeaderText columnText={'Order price'} content={data['total'] ? `$${data['total']}` : 'null'}/>}
+                    {!status && <Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '200px'}}>
+                        {data['orderGoods'] && data['orderGoods'].map((item, index, array) => {
+                            if (index < 2) {
+                                return <Box sx={{width:'60px', height:'60px'}}>
+                                            <img src={item?.good?.images && Array.isArray(item.good.images) ? `${backURL}/${item.good.images[0].url}` : imgNotFound}
+                                                 alt={'image'}
+                                                 style={{width: '100%', height: '100%', objectFit:'cover'}}
+                                            />
+                                        </Box>
+                            }
+                            else if (index === 2) {
+                                return <Box sx={{width:'60px', height:'60px', border:'1px solid #616161', display: 'flex', justifyContent: 'center', alignItems: 'center', color: '#616161', borderRadius: '10px'}}>
+                                            +{array.length - 2}
+                                       </Box>}
+                            })
+                        }
+                    </Box>}
+                </Box>
+            </AccordionSummary>
+            <AccordionDetails sx={{padding: '20px'}}>
+                {data['orderGoods'] && data['orderGoods'].length > 0 ?
+                    <>
+                        <Grid container>
+                            <Grid item md={7}>
+                                <Typography
+                                    color='#616161'
+                                    variant='body1'
+                                    letterSpacing='1px'
+                                    textAlign='left'
+                                >
+                                    Product
+                                </Typography>
+                            </Grid>
+                            <Grid item md={2}>
+                                <Typography
+                                    color='#616161'
+                                    variant='body1'
+                                    letterSpacing='1px'
+                                    textAlign='center'
+                                >
+                                    Price
+                                </Typography>
+                            </Grid>
+                            <Grid item md={1}>
+                                <Typography
+                                    color='#616161'
+                                    variant='body1'
+                                    letterSpacing='1px'
+                                    textAlign='center'
+                                >
+                                    Count
+                                </Typography>
+                            </Grid>
+                            <Grid item md={2}>
+                                <Typography
+                                    color='#616161'
+                                    variant='body1'
+                                    letterSpacing='1px'
+                                    textAlign='right'
+                                >
+                                    Sum
+                                </Typography>
+                            </Grid>
+                        </Grid>
+                        <Divider sx={{margin: '10px 0'}}/>
+                        {data['orderGoods'].map(item => {
+                            return <Grid container alignItems='center' marginBottom='20px'>
+                                <Grid item md={7}>
+                                    <Link style={{textDecoration: 'none', display: 'flex', alignItems: 'center', color: '#616161'}} to={`/good/${item?.good?._id}`}>
+                                        <Box sx={{width:'60px', height:'60px'}} marginRight='10px'>
+                                            <img src={item?.good?.images && Array.isArray(item.good.images) ? `${backURL}/${item.good.images[0].url}` : imgNotFound}
+                                                 alt={'image'}
+                                                 style={{width: '100%', height: '100%', objectFit:'cover'}}
+                                            />
+                                        </Box>
+                                        <Typography
+                                            variant='body1'
+                                        >
+                                            {item.good?.name || 'product name'}
+                                        </Typography>
+                                    </Link>
+                                </Grid>
+                                <Grid item md={2}>
+                                    <Typography
+                                        color='#616161'
+                                        variant='body1'
+                                        letterSpacing='1px'
+                                        textAlign='center'
+                                    >
+                                        {item?.price ? '$' + parseFloat(item.price).toFixed(2) : 'NaN'}
+                                    </Typography>
+                                </Grid>
+                                <Grid item md={1}>
+                                    <Typography
+                                        color='#616161'
+                                        variant='body1'
+                                        letterSpacing='1px'
+                                        textAlign='center'
+                                    >
+                                        {item?.count || '1'}
+                                    </Typography>
+                                </Grid>
+                                <Grid item md={2}>
+                                    <Typography
+                                        color='#616161'
+                                        variant='body1'
+                                        letterSpacing='1px'
+                                        textAlign='right'
+                                    >
+                                        {item?.price && item?.count ? '$'+parseFloat(item.price * item.count).toFixed(2) : 'NaN'}
+                                    </Typography>
+                                </Grid>
+                            </Grid>
+                        })}
+                        <Divider sx={{margin: '-10px 0 10px 0'}}/>
+                        <Box display='flex' justifyContent='space-between'>
+                            <Typography
+                                variant='body1'
+                                color='#616161'
+                            >
+                                Total
+                            </Typography>
+                            <Typography
+                                variant='body1'
+                                color='#616161'
+                            >
+                                {data?.total ? '$'+parseFloat(data.total).toFixed(2) : 'NaN'}
+                            </Typography>
+                        </Box>
+                    </> :
+                    <Typography>Error</Typography>
+                }
+            </AccordionDetails>
+        </Accordion>
+    )
+}
+
+const MyOrdersPage = ({orders, onFindOrders, onOrdersClear}) => {
+    const itemsPerPage = 10
+    const [page, setPage] = useState(1)
+    const [count, setCount] = useState(1)
+    const handleChange = (event, value) => {
+        setPage(value);
+    }
+
+    useEffect(() => {
+        onOrdersClear()
+    }, [onOrdersClear])
+
+    useEffect(() => {
+        if(orders?.orderResult && Object.entries(orders.orderResult).length > 0) {
+            setCount(Math.ceil(Object.entries(orders.orderResult).length / itemsPerPage))
+        }
+    }, [orders])
+
+    if(Object.entries(orders).length === 0) onFindOrders()
+
+    const matches = useMediaQuery('(max-width:768px)')
     return (
         <>
             <Breadcrumb links={['My orders']} />
-            <main style={{backgroundColor: "#f3f3f3", padding: matches ? "20px 0" : "50px 0"}}>
-
+            <main style={{backgroundColor: "#f3f3f3", padding: matches ? "20px 0" : "50px 0", minHeight:'300px'}}>
+                <Container maxWidth="lg" sx={{position:'relative'}}>
+                    {Object.entries(orders).length === 0 ?
+                        <Box sx={{height: '100%', width: '100%', display: 'flex', justifyContent:'center', alignItems:'center'}}><CircularProgress color="inherit"/></Box> :
+                        Object.entries(orders?.orderResult).length > 0 ?
+                            <Box>
+                                {Object.values(orders.orderResult).slice((page - 1) * itemsPerPage, page * itemsPerPage).map(item => <AccordionItem data={item}/>)}
+                                <Divider sx={{margin: '20px'}}/>
+                                <Box display='flex' justifyContent='center' width='100%'>
+                                    <Pagination
+                                        count={count}
+                                        page={page}
+                                        onChange={handleChange}
+                                        defaultPage={1}
+                                        color="primary"
+                                        size="large"
+                                        showFirstButton
+                                        showLastButton
+                                    />
+                                </Box>
+                            </Box>
+                        :
+                        <NotFoundBlock headerText={'OOPS! ORDERS CAN’T BE FOUND'} text={'No order has been made yet.'}/>
+                    }
+                </Container>
             </main>
         </>
     )
 }
-export default MyOrdersPage
+const CMyOrdersPage = connect(state=>({orders: state.myorders}), {onFindOrders: actionFullOrderFind, onOrdersClear: actionMyOrderClear})(MyOrdersPage)
+
+export default CMyOrdersPage

+ 2 - 2
src/pages/ProductPage.jsx

@@ -37,11 +37,11 @@ let defProduct = {
     ]
 }
 
-const timeCalc = (createdAt) => {
+export const timeCalc = (createdAt) => {
     let formattedTime = 0;
     let date = new Date(+createdAt);
     let year = date.getFullYear();
-    let month = "0" + date.getMonth();
+    let month = "0" + (date.getMonth()+1);
     let day = "0" + date.getDate();
     let hours = "0" + date.getHours();
     let minutes = "0" + date.getMinutes();

+ 3 - 1
src/reducers/CombineReducers.js

@@ -7,6 +7,7 @@ import {CategoryReducer} from "./CategoryReducer";
 import {WishListReducer} from "./WishListReducer";
 import {localStoredReducer} from "./LocalStoredReducer";
 import {SearchReducer} from "./SearchReducer";
+import {MyOrdersReducer} from "./MyOrdersReducer";
 
 export const rootReducer = combineReducers({
     auth: AuthReducer,
@@ -15,5 +16,6 @@ export const rootReducer = combineReducers({
     user: UserReducer,
     category: localStoredReducer(CategoryReducer,'category'),
     wishlist: localStoredReducer(WishListReducer, 'wishlist'),
-    search: SearchReducer
+    search: SearchReducer,
+    myorders: MyOrdersReducer
 })

+ 16 - 0
src/reducers/MyOrdersReducer.js

@@ -0,0 +1,16 @@
+export const MyOrdersReducer = (state={}, { type, value }) => {
+    if (type === 'ORDER_RESULT'){
+        return {
+            orderResult : {
+                ...value
+            }
+        }
+    }
+    if (type === 'ORDER_CLEAR'){
+        return {}
+    }
+    return state
+}
+
+export const actionMyOrder = value => ({type: 'ORDER_RESULT', value})
+export const actionMyOrderClear = () => ({type: 'ORDER_CLEAR'})