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
});
});