티스토리 뷰

📌 2020 07 22

  • Cart와 Order에서 수량 조절 기능을 구현
    • 이제까지는 수량조절하려면 수동으로 해당 Product를 다시 add to cart 혹은 order해야 했는데 이를 개선함
  • Cart에서 check한 Product만 Order로 넘어가도록 수정함
    • 이제까지는 Cart에 있는 모든 Product를 Order로 넘길 수 밖에 없었는데 이를 개선함

Cart / Order 수량조절

  1. 수량 조절 버튼에 onClick 이벤트가 발생하면 해당 product의 수량을 변경하는 라우팅으로 fetch시키는 자바스크립트 함수가 실행되도록 한다.
  2. 여기서 get 방식으로 전송하므로 product Id와 변경될 수량 (qty) 는 각각 파라미터와 쿼리에 담아서 전달해준다.
  3. 전달받은 데이터를 통해 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에 추가하기

  1. 먼저 cart에 담긴 모든 Product의 check 값을 true로 해준다.
  2. user모델의 해당 cart item 영역의 unorderd를 추가해주어 해당 product가 주문 리스트에 올랐는지 확인해주도록 한다.
  3. 해당 checkbox의 onclick 이벤트에 자바스크립트 함수를 등록한다. 자바스크립트 함수는 checked == true라면 unorderd를 undefined로 변경 or 유지 해주고, checked == false 라면 true로 변경해주는 라우팅으로 fetch 해준다.
  4. Order를 생성 할 때, cart에 있는 product중 unorderd 가 undefined 인 product만 order로 옮겨준다.
  5. 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();
}
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함