NODE.JS

OnlineShop 만들기 - 10) Cart Page 만들기 1 (cart정보 가져오기)

dodop 2021. 5. 16. 16:31

장바구니 페이지를 만들 것이다. 

 

순서
생성된 컬렉션

여기서 user컬렉션에는 cart quantity 정보가 있지만 product collection에는 quantity정보가 없다. 

그래서 둘의 컬렉션을 종합해서 fetch하고 사용해서 정보를 나타내야 한다. 

 

 

 

제일먼저 카트 페이지를 만들어준다. 

views>CartPage>CartPage.js

import React from 'react'

function CartPage() {
    return (
        <div>
            
        </div>
    )
}

export default CartPage

 

App.js에 가서 route 추가해준다.

로그인 한사람만 자신의 장바구니 볼 수 있게 true로 바꿔준다.

import CartPage from './views/CartPage/CartPage';

          <Route exact path="/user/cart" component={Auth(CartPage, true)} />

 

header부분에 장바구니모양을 추가해준다. 

views>NavBar>Sections>RightMenu에 다음과 같은 내용 추가해준다. 

import { Menu, Icon, Badge } from 'antd';

        <Menu.Item key="cart">
          <Badge count = {user.userData&&user.userData.cart.length} >
          <a href="/user/cart" style = {{marginRight:-22, color:'#667777'}}>
            <Icon type="shopping-cart" style={{fontSize: 30,marginBottom:4 }}/>
          </a>
          </Badge>
        </Menu.Item>

현재모양

 

이제 데이터 베이스에 있는 정보를 가지고 와서 카트 페이지에 보이도록 해주자. 

import React, { useEffect } from 'react'
import {useDispatch} from 'react-redux'
import {getCartItems} from '../../../_actions/user_actions'//redux를 이용하니 actions에서 가져와서 실행한다. 

function CartPage() {

    const dispatch = useDispatch();

    useEffect(() => {

        //redux에 있는 cart 정보가 필요하다
        let cartItems = [];
        if(props.user.userData && props.user.userData.cart){
            //1개 이상 카트에 존재할 때만 작동한다. 
            if(props.user.userData.cart.length>0){
                //각각의 아이템에 대해서 실행한다.
                props.user.userData.cart.forEach(item=>{
                    cartItems.push(item.id)
                });
            //Axios를 이용하는 대신 리덕스를 이용할 것이다. (아이템아이디배열이랑 카트의 모든 정보를 넣는다.)
                dispatch(getCartItems(cartItems, props.user.userData.cart ))
            }


        }
    }, [props.user.userData])//변경될 때마다 자동 업데이트 되도록 설정

리덕스를 이용해서 정보 가져오는데, 

actions에 기능을 넣어야 하므로 user_actions에 가서 getCartItems를 만들어준다. 

export function getCartItems(cartItems, userCart){ //카트 아이디 배열이랑 카트에 대한 모든 정보를  파라미터로 넘겨준다.
    const request = axios.get(`/api/product/products_by_id?id=${cartItems}&type=array`)//product route에 가서 cart아이디들을 주고 실행한다.(여러가지 카트아이디니까 배열로 타입)
    .then(response => {
    //cart는 오직 id, quantity, data정보만 있는데 cartdetail로 더 많은 정보를 가지고 오자. 여기서 우리는 product collection뿐만 아니라 user의 quantity 정보도 필요하다
    //cart detail을 redux store 안에 만들어 준다. (product+user(quantity))
    //products_by_id는 product 정보를 돌려준다. 
        userCart.forEach(cartItem=>{
            response.aata.forEach((productDetail, i)=>{
                if(cartItem.Id===productDetail._id){
                    response.data[i].quantity = cartItem.quantity;
                }
            })
        })
        return response.data;

    });



    return {
        type: GET_CART_ITEMS_USER,
        payload: request
    }
}

 

 

product api 가서 만들어 준다. router

router.get("/products_by_id", (req, res) => {
    let type = req.query.type //이번에는 쿼리로 가져왔기 때문에 body가 아닌 쿼리를 사용한다.
    let productIds = req.query.id
    if(type =="array"){//타입이 배열이라서 여러개를 가져온다면 다음과 같이 처리한다(여기서 우리는 single로 가져와서 상관 없다.)
        //카트 아이디들을 가지고 들어왔을 때 배열이라서 실행된다.

        //카트 아이디를 담은 배열을 만들고 싶은데, 하나이상의 카트 아이디를 ,로 나눠서(id = 111,223,44,...) 가지고 있기 때문에 각각 분리해서 저장해줘야 한다. 
        let ids = req.query.id.split(',');
        productIds = [];
        productIds = ids.map(item =>{
            return item
        })

    }

    //we need to find product information that belong to product Id
    Product.find({'_id':{$in:productIds}}) //아이디에 해당하는 모든 정보 받을 수 있다 ($in)
        .populate('writer')
        .exec((err, product)=>{
            if(err) return res.status(400).send(err);
            return res.status(200).send(product)
        })
});

types로 가서 타입만들고 

reducer로 가서 타입넣어준다. 

export const GET_CART_ITEMS_USER = 'get_cart_items_user';
import {
    LOGIN_USER,
    REGISTER_USER,
    AUTH_USER,
    LOGOUT_USER,
    ADD_TO_CART_USER,
    GET_CART_ITEMS_USER
} from '../_actions/types';
 
         case GET_CART_ITEMS_USER:
            return {
                ...state, cartDetail: action.payload} //getCartitems action의 결과
        

 

페이지를 옮길 때마다 항상 실행하는 user route에 auth부분에 cart 정보를 추가해줘야 한다. 

추가로 history 부분도 넣어주자.

user model에 cart를 넣었더라도 auth redux에 넣어줘야만 확인이 가능하기 때문이다. 

router.get("/auth", auth, (req, res) => {
    res.status(200).json({
        _id: req.user._id,
        isAdmin: req.user.role === 0 ? false : true,
        isAuth: true,
        email: req.user.email,
        name: req.user.name,
        lastname: req.user.lastname,
        role: req.user.role,
        image: req.user.image,
        cart: req.user.cart,
        history: req.user.history
    });
});

리덕스에 추가된 것을 확인할 수 있다.