ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아마존 E-commerce 클론 -32) 차트 스크린 만들기
    NODE.JS 2021. 5. 30. 20:32

     

     

    orderRouter로 가보자. 

    get/다음에 작성해주자.

    mongoDB의 aggregate기능을 사용할 것이다. 

    각각의 주문들에 대해서 sum, 판매량 구하고, 

    각각의 사용자에 대해서 사용자 수를 구해서 사용한다. 

    
    orderRouter.get(
        '/summary',
        isAuth,
        isAdmin,
        expressAsyncHandler(async (req, res) => {
          const orders = await Order.aggregate([
            {
              $group: {
                _id: null,
                numOrders: { $sum: 1 },
                totalSales: { $sum: '$totalPrice' },
              },
            },
          ]);
          const users = await User.aggregate([
            {
              $group: {
                _id: null,
                numUsers: { $sum: 1 },
              },
            },
          ]);
          const dailyOrders = await Order.aggregate([
            {
              $group: {
                _id: { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } },
                orders: { $sum: 1 },
                sales: { $sum: '$totalPrice' },
              },
            },
                    { $sort: { _id: 1 } },//차트를 날짜순으로 배열한다. 
    
          ]);
          const productCategories = await Product.aggregate([
            {
              $group: {
                _id: '$category',
                count: { $sum: 1 },
              },
            },
          ]);
          res.send({ users, orders, dailyOrders, productCategories });
        })
      );
    

     

     

    새로 스크린을 만들어보자. 

    import React from 'react'
    import LoadingBox from '../components/LoadingBox'
    import MessageBox from '../components/MessageBox'
    
    function DashboardScreen() {
        return (
            <div>
                <div className="row">
                    <h1>Dashboard</h1>
                </div>
                {loading? 
                    <LoadingBox></LoadingBox>
                : error?(
                    <MessageBox variant='danger'>{error}</MessageBox>
                ):(
                    <>
                        <ul className="row summary">
                            <li>
                                <div className="summary-title color1">
                                    <span><i className="fa fa-users"></i>Users</span>
                                </div>
                                <div className="summary-body">{summary.users[0].numUsers}</div>
                            </li>
                            <li>
                                <div className="summary-title color2">
                                    <span><i className="fa fa-shopping-cart"></i>Orders</span>
                                </div>
                                <div className="summary-body">{summary.orders[0]? summary.orders[0].numOrders:0}</div>
                            </li>
                            <li>
                                <div className="summary-title color3">
                                    <span><i className="fa fa-money"></i>Orders</span>
                                </div>
                                <div className="summary-body">${summary.orders[0]? summary.orders[0].totalSales.toFixed(2):0}</div>
                            </li>
                        </ul>
                    </>
                )
                }
            </div>
        )
    }
    
    export default DashboardScreen
    

     

    이제 데이터를 patch하자. 

     

    orderConstants.js

    export const ORDER_SUMMARY_REQUEST = 'ORDER_SUMMARY_REQUEST';
    export const ORDER_SUMMARY_SUCCESS = 'ORDER_SUMMARY_SUCCESS';
    export const ORDER_SUMMARY_FAIL = 'ORDER_SUMMARY_FAIL';

    orderActions

    export const summaryOrder = () => async (dispatch, getState) => {
        dispatch({ type: ORDER_SUMMARY_REQUEST });
        const {
          userSignin: { userInfo },
        } = getState();
        try {
          const { data } = await axios.get('/api/orders/summary', {
            headers: { Authorization: `Bearer ${userInfo.token}` },
          });
          dispatch({ type: ORDER_SUMMARY_SUCCESS, payload: data });
        } catch (error) {
          dispatch({
            type: ORDER_CREATE_FAIL,
            payload:
              error.response && error.response.data.message
                ? error.response.data.message
                : error.message,
          });
        }
      };

     

     

    orderReducers.js

    export const orderSummaryReducer = (
        state = { loading: true, summary: {} },
        action
      ) => {
        switch (action.type) {
          case ORDER_SUMMARY_REQUEST:
            return { loading: true };
          case ORDER_SUMMARY_SUCCESS:
            return { loading: false, summary: action.payload };
          case ORDER_SUMMARY_FAIL:
            return { loading: false, error: action.payload };
          default:
            return state;
        }
      };
    

     

     

    store.js

        orderSummary:orderSummaryReducer
    

     

     

    app.js에 페이지 추가

     

     

    import DashboardScreen from './screens/DashboardScreen';
                  <AdminRoute path="/dashboard" component={DashboardScreen} exact></AdminRoute>          
    

     

     

    DashboardScreen.js

    import { summaryOrder } from '../actions/orderActions'
    
    
        const orderSummary = useSelector(state => state.orderSummary)
        const {loading, summary, error} = orderSummary;
    
        const dispatch = useDispatch()
        useEffect(() => {
            dispatch(summaryOrder())
        }, [dispatch])
    

     

    스타일링하자. 

    /* Dashboard */
    
    .summary > li {
      border: 0.1rem #c0c0c0 solid;
      margin: 2rem;
      border-radius: 0.5rem;
      flex: 1 1 20rem;
    }
    .summary-title {
      font-size: 2rem;
      padding: 1rem;
    }
    .summary-body {
      font-size: 4rem;
      padding: 1rem;
      text-align: center;
    }
    
    .summary-title.color1 {
      background-color: #f0e0e0;
    }
    .summary-title.color2 {
      background-color: #e0f0e0;
    }
    .summary-title.color3 {
      background-color: #e0e0f0;
      }

     

     

    이제 차트를 넣자. 

    frontent> npm install react-google-charts

    dash sceen

    import Chart from 'react-google-charts';
    
    
              <div>
                <div>
                  <h2>Sales</h2>
                  {summary.dailyOrders.length === 0 ? (
                    <MessageBox>No Sale</MessageBox>
                  ) : (
                    <Chart
                      width="100%"
                      height="400px"
                      chartType="AreaChart"
                      loader={<div>Loading Chart</div>}
                      data={[
                        ['Date', 'Sales'],
                        ...summary.dailyOrders.map((x) => [x._id, x.sales]),
                      ]}
                    ></Chart>
                  )}
                </div>
              </div>
              <div>
                <h2>Categories</h2>
                {summary.productCategories.length === 0 ? (
                  <MessageBox>No Category</MessageBox>
                ) : (
                  <Chart
                    width="100%"
                    height="400px"
                    chartType="PieChart"
                    loader={<div>Loading Chart</div>}
                    data={[
                      ['Category', 'Products'],
                      ...summary.productCategories.map((x) => [x._id, x.count]),
                    ]}
                  />
                )}
              </div>

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

Designed by Tistory.