티스토리 뷰
[ node js - express 쇼핑몰 웹] 6. Cart 와 Order 수량 변경 기능 구현 / Cart 내에서 체크한 항목만 Order하는 기능 구현
무니웜테일패드풋프롱스 2020. 7. 22. 23:13📌 2020 07 22
- Cart와 Order에서 수량 조절 기능을 구현
- 이제까지는 수량조절하려면 수동으로 해당 Product를 다시 add to cart 혹은 order해야 했는데 이를 개선함
- Cart에서 check한 Product만 Order로 넘어가도록 수정함
- 이제까지는 Cart에 있는 모든 Product를 Order로 넘길 수 밖에 없었는데 이를 개선함
Cart / Order 수량조절
- 수량 조절 버튼에 onClick 이벤트가 발생하면 해당 product의 수량을 변경하는 라우팅으로 fetch시키는 자바스크립트 함수가 실행되도록 한다.
- 여기서 get 방식으로 전송하므로 product Id와 변경될 수량 (qty) 는 각각 파라미터와 쿼리에 담아서 전달해준다.
- 전달받은 데이터를 통해 user 모델의 cart에서 해당 상품의 수량을 변경시켜준다.
cart view 코드
<li class="cart__item">
<input type="hidden" value="<%= p.productId._id %>" name="productId">
<input type="hidden" name="_csrf" value="<%= csrfToken%>">
<label for="qty">quantity: </label>
<input type="number" name="qty" value="<%= p.quantity%>" onclick="cartChangeQty(this)">
<input type="checkbox" class="orderCheck" name="order" checked="true" onclick="orderChecked(this)">
<button class="btn danger" type="button" onclick="deleteFromCart(this)">Delete</button>
</li>
해당 라우팅으로 fetch 시키는 코드 : this를 매개변수로 받아옴으로써 hidden 값으로 넘겨받은 인자들에 접근 가능하다.
const cartChangeQty=(btn)=>{ // 데이터베이스에 수량 바꾸기 등록
const prodId = btn.parentNode.querySelector('[name=productId]').value;
const qty=btn.parentNode.querySelector('[name=qty]').value;
fetch('/cart-qty/'+prodId+'/?qty='+qty, { // 파라미터로 prod Id넘겨주고 쿼리로 qty넘겨주기
method:'GET'
})
.then(result=>{
return result.json(); //전달받은 json 데이터
})
.then(data=>{
console.log(data); // json데이터 콘솔에 띄우기, 성공이면 success 실패면 fail
}).catch(err=>next(err));
;
}
/cart-qty/:productId get요청을 처리하는 라우터
exports.cartChangeQty =(req,res,next)=>{ // 카트 qty 변경
const productId = req.params.productId; // 파라미터로 받아온 productId
const qty = req.query.qty; // 쿼리로 받아온 qty
req.user.changeQty(productId,qty) // 현재 로그인된 유저의 cart 변경
.then(result=>{
res.status(200).json({message:'success'});
})
.catch(err=>{
res.status(500).json({message:'fail'});
})
}
User 모델의 cart 내 해당 아이템 수량 변경 메서드 : 받아온 product Id에 해당하는 인덱스를 뽑은 후, 해당 인덱스의 qty를 변경해준다.
userSchema.methods.changeQty=function(productId,qty){
const cartProductIndex= this.cart.items.findIndex(cp=>{
return cp.productId.toString()==productId.toString();
});
this.cart.items[cartProductIndex].quantity=qty;
return this.save();
}
Cart에서 check 한 product만 Order에 추가하기
- 먼저 cart에 담긴 모든 Product의 check 값을 true로 해준다.
- user모델의 해당 cart item 영역의 unorderd를 추가해주어 해당 product가 주문 리스트에 올랐는지 확인해주도록 한다.
- 해당 checkbox의 onclick 이벤트에 자바스크립트 함수를 등록한다. 자바스크립트 함수는 checked == true라면 unorderd를 undefined로 변경 or 유지 해주고, checked == false 라면 true로 변경해주는 라우팅으로 fetch 해준다.
- Order를 생성 할 때, cart에 있는 product중 unorderd 가 undefined 인 product만 order로 옮겨준다.
- Cart를 비울 때, cart에 있는 product중 unorderd가 true 인 product만 남겨준다.
Cart view 코드
<li class="cart__item">
<input type="hidden" value="<%= p.productId._id %>" name="productId">
<input type="hidden" name="_csrf" value="<%= csrfToken%>">
<label for="qty">quantity: </label>
<input type="number" name="qty" value="<%= p.quantity%>" onclick="cartChangeQty(this)">
<input type="checkbox" class="orderCheck" name="order" checked="true" onclick="orderChecked(this)">
<button class="btn danger" type="button" onclick="deleteFromCart(this)">Delete</button>
</li>
해당 라우팅으로 fetch 시키는 코드 : productId와 unorderd 결과를 각각 파라미터와 쿼리에 담아서 전달해준다.
const orderChecked=(btn)=>{
const prodId=btn.parentNode.querySelector('[name=productId]').value;
const orderd=btn.parentNode.querySelector('[name=order]').checked; // 체크되었으면 true, 안되었으면 false
fetch('/cart-orderd/'+prodId+'/?orderd='+orderd, {
method:'GET',
}).then(result=>{
console.log(result);
return result.json();
}).then(data=>{
console.log(data);
}).catch(err=>console.log(err));
}
/cart-orderd/:productId get요청을 처리하는 라우터
exports.cartOrderd=(req,res,next)=>{ // orderd or not check해주기 --> order 에 들어갈 cart목록 체크
const productId = req.params.productId;
const orderd = req.query.orderd;
req.user.orderCheck(productId,orderd) // 현재 로그인된 유저 모델의 카트에 결과를 반영해준다.
.then(result=>{
res.status(200).json({message:'success'});
})
.catch(err=>{
console.log(err);
res.status(500).json({message:'fail'});
})
}
User 모델에서 unorderd를 등록해주는 메서드 : 매개변수로 받은 orderd가 true이면 , 즉 주문 리스트에 포함되면 cart 내 unorderd항목을 undefined로 변경해주고, orderd가 false라면 true로 변경해준다.
userSchema.methods.orderCheck=function(productId,orderd){ // order에 들어갈 product인지 등록해준다.
const cartProductIndex=this.cart.items.findIndex(cp=>{
return cp.productId.toString()==productId.toString(); // 해당 product의 인덱스 찾기
})
if(orderd=='true'){ // orderd에 들어갈 product라면
this.cart.items[cartProductIndex].unorderd=undefined;
}
else{ // orderd에 들어가지 않을 product라면
this.cart.items[cartProductIndex].unorderd='true'
}
return this.save();
}
Order에 추가해주는 post 라우터 : 해당 메서드의 req.user의 cart.items를 매개변수로 전달해준다. 원래는 req.user._id만 전달해줘서 해당 메서드에서 다시 User.findOne()메서드를 통해서 user를 찾았는데, 어차피 로그인 된 유저의 cart정보이므로 굳이 해당 User 모델을 찾을 필요 없을 것이라 생각하여 req.user로 접근하여 cart.items를 전달해주는 방향으로 바꾸었다.
exports.postAddToOrder=(req,res,next)=>{ // Cart에서 Order로 추가
Order.findOne({'user.userId':req.user._id})
.then(order=>{
if(!order){
order=new Order({ // 해당 user의 order가 없다면 생성해주기
products: {items:[]},
user:{userId:req.user._id}
});
}
order.addOrder(req.user.cart.items) // order 추가
.then(result=>{
req.user.adjustCart(); // 카트 비우기
res.redirect('/orders');
})
}).catch(err=>{
console.log(err);
const error = new Error(err);
error.httpStatusCode = 500;
return next(error);
});
}
Order를 추가해주는 메서드 : 매개변수로 받은 cart items를 반복문으로 보며 unorderd == true인 product는 Order 에서 제외해준다.
OrderSchema.methods.addOrder=function(cart_items){ // order에 상품 추가- 이미 order에 있는 상품은 수량만 늘리기
let updatedOrderItem=[...this.products.items];
for(item of cart_items){
if(item.unorderd=='true') continue;// 주문 리스트에 포함되지 않으므로 넘어간다.
const itemIndex = this.products.items.findIndex(cp=>{
return cp.productId.toString()==item.productId.toString();
})
let newQuantity = 1;
if(itemIndex>=0){ // 이미 order에 있는 경우
newQuantity+=this.products.items[itemIndex].quantity;
updatedOrderItem[itemIndex].quantity=newQuantity;
}
else{ // 없는 경우
updatedOrderItem.push({productId:item.productId, quantity: item.quantity});
}
}
this.products.items = updatedOrderItem;
return this.save();
}
Order 후에 남은 Cart를 재정비해주는 메서드 : 주문 리스트에 올라가지 않은 product만 남겨주도록 한다.
userSchema.methods.adjustCart=function(){ // 카트에서 order로 넘겨준후 모두 지우지 않고 checked된 product만 지우기
// undefined 아닌것만 남겨주기
let updatedCartitems = this.cart.items.filter(item=>{
return item.unorderd=='true' // true로 표시된 prodcut만 남겨주기
});
this.cart.items=updatedCartitems;
return this.save();
}
'Project > 첫번째 프로젝트 쇼핑몰 웹' 카테고리의 다른 글
[ node js - express 쇼핑몰 웹] 7. 상품 검색 기능 구현 (0) | 2020.07.24 |
---|---|
[ node js - express 쇼핑몰 웹] 5. Seller 등록, 취소 구현 (0) | 2020.07.22 |
[ node js - express 쇼핑몰 웹 ] 4. input data validation 추가 (0) | 2020.07.19 |
[node js - express 쇼핑몰 웹] 3. 로그인, 로그아웃, 회원가입 구현하기 (0) | 2020.07.16 |
[node js - express 쇼핑몰 웹] 2. 삭제된 product 정보 cart와 order에 적용시키기 (0) | 2020.07.15 |