Fixing cart storage and management
parent
ba33ad2f96
commit
03573129b3
|
@ -111,15 +111,24 @@ const clearSessionValue = (session, sessionVar) => {
|
|||
return temp;
|
||||
};
|
||||
|
||||
const updateTotalCartAmount = (req, res) => {
|
||||
const updateTotalCart = (req, res) => {
|
||||
const config = getConfig();
|
||||
|
||||
req.session.totalCartAmount = 0;
|
||||
req.session.cartTotalItems = 0;
|
||||
|
||||
_(req.session.cart).forEach((item) => {
|
||||
req.session.totalCartAmount = req.session.totalCartAmount + item.totalItemPrice;
|
||||
// If cart is empty return zero values
|
||||
if(!req.session.cart){
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(req.session.cart).forEach((item) => {
|
||||
req.session.totalCartAmount = req.session.totalCartAmount + req.session.cart[item].totalItemPrice;
|
||||
});
|
||||
|
||||
// Update the total items in cart for the badge
|
||||
req.session.cartTotalItems = Object.keys(req.session.cart).length;
|
||||
|
||||
// under the free shipping threshold
|
||||
if(req.session.totalCartAmount < config.freeShippingAmount){
|
||||
req.session.totalCartAmount = req.session.totalCartAmount + parseInt(config.flatShipping);
|
||||
|
@ -136,7 +145,7 @@ const updateSubscriptionCheck = (req, res) => {
|
|||
return;
|
||||
}
|
||||
|
||||
req.session.cart.forEach((item) => {
|
||||
Object.keys(req.session.cart).forEach((item) => {
|
||||
if(item.productSubscription){
|
||||
req.session.cartSubscription = item.productSubscription;
|
||||
}else{
|
||||
|
@ -279,7 +288,7 @@ const updateConfig = (fields) => {
|
|||
}
|
||||
});
|
||||
|
||||
// delete settings
|
||||
// delete any settings
|
||||
delete settingsFile.customCss_input;
|
||||
delete settingsFile.footerHtml_input;
|
||||
delete settingsFile.googleAnalytics_input;
|
||||
|
@ -583,7 +592,7 @@ module.exports = {
|
|||
convertBool,
|
||||
addSitemapProducts,
|
||||
clearSessionValue,
|
||||
updateTotalCartAmount,
|
||||
updateTotalCart,
|
||||
updateSubscriptionCheck,
|
||||
checkDirectorySync,
|
||||
getThemes,
|
||||
|
|
|
@ -19,6 +19,13 @@ $(document).ready(function (){
|
|||
$('#offcanvasClose').hide();
|
||||
}
|
||||
|
||||
// If cart was open before reload, open it again
|
||||
var isCartOpen = (localStorage.getItem('cartOpen') === 'true');
|
||||
if(isCartOpen === true){
|
||||
localStorage.setItem('cartOpen', false);
|
||||
$('body').addClass('pushy-open-right');
|
||||
}
|
||||
|
||||
$('#userSetupForm').validator().on('submit', function(e){
|
||||
if(!e.isDefaultPrevented()){
|
||||
e.preventDefault();
|
||||
|
@ -40,24 +47,6 @@ $(document).ready(function (){
|
|||
}
|
||||
});
|
||||
|
||||
// $('.shipping-form input').each(function(e){
|
||||
// $(this).wrap('<fieldset></fieldset>');
|
||||
// var tag = $(this).attr('placeholder');
|
||||
// $(this).after('<label for="name" class="hidden">' + tag + '</label>');
|
||||
// });
|
||||
|
||||
// $('.shipping-form input').on('focus', function(){
|
||||
// $(this).next().addClass('floatLabel');
|
||||
// $(this).next().removeClass('hidden');
|
||||
// });
|
||||
|
||||
// $('.shipping-form input').on('blur', function(){
|
||||
// if($(this).val() === ''){
|
||||
// $(this).next().addClass('hidden');
|
||||
// $(this).next().removeClass('floatLabel');
|
||||
// }
|
||||
// });
|
||||
|
||||
$(document).on('click', '.menu-btn', function(e){
|
||||
e.preventDefault();
|
||||
$('body').addClass('pushy-open-right');
|
||||
|
@ -68,7 +57,9 @@ $(document).ready(function (){
|
|||
$(this).addClass('table table-hover');
|
||||
});
|
||||
|
||||
$('#productTags').tokenfield();
|
||||
if($('#productTags').length){
|
||||
$('#productTags').tokenfield();
|
||||
}
|
||||
|
||||
$(document).on('click', '.dashboard_list', function(e){
|
||||
window.document.location = $(this).attr('href');
|
||||
|
@ -79,7 +70,6 @@ $(document).ready(function (){
|
|||
$(document).on('click', '.btn-qty-minus', function(e){
|
||||
e.preventDefault();
|
||||
var qtyElement = $(e.target).parent().parent().find('.cart-product-quantity');
|
||||
// console.log('qtyElement', qtyElement);
|
||||
$(qtyElement).val(parseInt(qtyElement.val()) - 1);
|
||||
cartUpdate(qtyElement);
|
||||
});
|
||||
|
@ -91,11 +81,6 @@ $(document).ready(function (){
|
|||
cartUpdate(qtyElement);
|
||||
});
|
||||
|
||||
// $(document).on('change', '.cart-product-quantity', function (e){
|
||||
// console.log('test');
|
||||
// cartUpdate(e.target);
|
||||
// });
|
||||
|
||||
$(document).on('click', '.btn-delete-from-cart', function(e){
|
||||
deleteFromCart($(e.target));
|
||||
});
|
||||
|
@ -172,6 +157,7 @@ $(document).ready(function (){
|
|||
});
|
||||
|
||||
$('#checkoutInformation').validator().on('click', function(e){
|
||||
console.log('here?');
|
||||
e.preventDefault();
|
||||
if($('#shipping-form').validator('validate').has('.has-error').length === 0){
|
||||
// Change route if customer to be saved for later
|
||||
|
@ -320,16 +306,15 @@ $(document).ready(function (){
|
|||
})
|
||||
.done(function(msg){
|
||||
$('#cart-count').text(msg.totalCartItems);
|
||||
updateCartDiv();
|
||||
showNotification(msg.message, 'success');
|
||||
showNotification(msg.message, 'success', true);
|
||||
})
|
||||
.fail(function(msg){
|
||||
showNotification(msg.responseJSON.message, 'danger');
|
||||
});
|
||||
});
|
||||
|
||||
$('.cart-product-quantity').on('input', function(){
|
||||
cartUpdate();
|
||||
$('.cart-product-quantity').on('focusout', function(e){
|
||||
cartUpdate($(e.target));
|
||||
});
|
||||
|
||||
$(document).on('click', '.pushy-link', function(e){
|
||||
|
@ -352,8 +337,7 @@ $(document).ready(function (){
|
|||
})
|
||||
.done(function(msg){
|
||||
$('#cart-count').text(msg.totalCartItems);
|
||||
updateCartDiv();
|
||||
showNotification(msg.message, 'success');
|
||||
showNotification(msg.message, 'success', true);
|
||||
})
|
||||
.fail(function(msg){
|
||||
showNotification(msg.responseJSON.message, 'danger');
|
||||
|
@ -368,7 +352,6 @@ $(document).ready(function (){
|
|||
})
|
||||
.done(function(msg){
|
||||
$('#cart-count').text(msg.totalCartItems);
|
||||
updateCartDiv();
|
||||
showNotification(msg.message, 'success', true);
|
||||
});
|
||||
});
|
||||
|
@ -420,25 +403,11 @@ function deleteFromCart(element){
|
|||
$.ajax({
|
||||
method: 'POST',
|
||||
url: '/product/removefromcart',
|
||||
data: { cartId: element.attr('data-id') }
|
||||
data: { productId: element.attr('data-id') }
|
||||
})
|
||||
.done(function(msg){
|
||||
$('#cart-count').text(msg.totalCartItems);
|
||||
if(msg.totalCartItems === 0){
|
||||
$(element).closest('.cart-row').hide('slow', function(){
|
||||
$(element).closest('.cart-row').remove();
|
||||
});
|
||||
$('.cart-contents-shipping').hide('slow', function(){
|
||||
$('.cart-contents-shipping').remove();
|
||||
});
|
||||
showNotification(msg.message, 'success');
|
||||
setTimeout(function(){
|
||||
window.location = '/';
|
||||
}, 3700);
|
||||
}else{
|
||||
$(element).closest('.cart-row').hide('slow', function(){ $(element).closest('.cart-row').remove(); });
|
||||
showNotification(msg.message, 'success');
|
||||
}
|
||||
setCartOpen();
|
||||
showNotification(msg.message, 'success', true);
|
||||
})
|
||||
.fail(function(msg){
|
||||
showNotification(msg.responseJSON.message, 'danger');
|
||||
|
@ -446,61 +415,42 @@ function deleteFromCart(element){
|
|||
}
|
||||
|
||||
function cartUpdate(element){
|
||||
console.log('element', element.val());
|
||||
if($(element).val() > 0){
|
||||
if($(element).val() !== ''){
|
||||
updateCart();
|
||||
updateCart(element);
|
||||
}
|
||||
}else{
|
||||
$(element).val(1);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCart(){
|
||||
// gather items of cart
|
||||
var cartItems = [];
|
||||
$('.cart-product-quantity').each(function(){
|
||||
cartItems.push({
|
||||
productId: $(this).attr('data-id'),
|
||||
quantity: $(this).val()
|
||||
});
|
||||
});
|
||||
|
||||
console.log('cartItems', cartItems)
|
||||
function setCartOpen(){
|
||||
if($('body').hasClass('pushy-open-right') === true){
|
||||
localStorage.setItem('cartOpen', true);
|
||||
}else{
|
||||
localStorage.setItem('cartOpen', false);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCart(element){
|
||||
// update cart on server
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: '/product/updatecart',
|
||||
data: { items: JSON.stringify(cartItems) }
|
||||
data: {
|
||||
productId: element.attr('data-id'),
|
||||
quantity: element.val()
|
||||
}
|
||||
})
|
||||
.done(function(msg){
|
||||
// update cart items
|
||||
updateCartDiv();
|
||||
$('#cart-count').text(msg.totalCartItems);
|
||||
setCartOpen();
|
||||
showNotification(msg.message, 'success', true);
|
||||
})
|
||||
.fail(function(msg){
|
||||
showNotification(msg.responseJSON.message, 'danger', true);
|
||||
});
|
||||
}
|
||||
|
||||
function updateCartDiv(){
|
||||
// get new cart render
|
||||
var path = window.location.pathname.split('/').length > 0 ? window.location.pathname.split('/')[1] : '';
|
||||
$.ajax({
|
||||
method: 'GET',
|
||||
url: '/cartPartial',
|
||||
data: { path: path }
|
||||
})
|
||||
.done(function(msg){
|
||||
// update cart div
|
||||
$('#cart').html(msg);
|
||||
})
|
||||
.fail(function(msg){
|
||||
showNotification(msg.responseJSON.message, 'danger');
|
||||
});
|
||||
}
|
||||
|
||||
function getSelectedOptions(){
|
||||
var options = {};
|
||||
$('.product-opt').each(function(){
|
||||
|
|
File diff suppressed because one or more lines are too long
172
routes/index.js
172
routes/index.js
|
@ -1,7 +1,6 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const colors = require('colors');
|
||||
const async = require('async');
|
||||
const _ = require('lodash');
|
||||
const {
|
||||
getId,
|
||||
|
@ -11,7 +10,7 @@ const {
|
|||
getMenu,
|
||||
getPaymentConfig,
|
||||
getImages,
|
||||
updateTotalCartAmount,
|
||||
updateTotalCart,
|
||||
updateSubscriptionCheck,
|
||||
getData,
|
||||
addSitemapProducts,
|
||||
|
@ -155,6 +154,10 @@ router.get('/checkout/cart', (req, res) => {
|
|||
});
|
||||
});
|
||||
|
||||
router.get('/checkout/cartdata', (req, res) => {
|
||||
res.status(200).json(req.session.cart);
|
||||
});
|
||||
|
||||
router.get('/checkout/payment', (req, res) => {
|
||||
const config = req.app.config;
|
||||
|
||||
|
@ -244,14 +247,10 @@ router.get('/cart/retrieve', async (req, res, next) => {
|
|||
});
|
||||
|
||||
// Updates a single product quantity
|
||||
router.post('/product/updatecart', (req, res, next) => {
|
||||
router.post('/product/updatecart', async (req, res, next) => {
|
||||
const db = req.app.db;
|
||||
const config = req.app.config;
|
||||
const cartItems = JSON.parse(req.body.items);
|
||||
let hasError = false;
|
||||
let stockError = false;
|
||||
|
||||
console.log('cartItems', cartItems);
|
||||
const cartItem = req.body;
|
||||
|
||||
// Check cart exists
|
||||
if(!req.session.cart){
|
||||
|
@ -259,100 +258,84 @@ router.post('/product/updatecart', (req, res, next) => {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log('req.session.cart', req.session.cart);
|
||||
// Calculate the quantity to update
|
||||
let productQuantity = cartItem.quantity ? cartItem.quantity : 1;
|
||||
if(typeof productQuantity === 'string'){
|
||||
productQuantity = parseInt(productQuantity);
|
||||
}
|
||||
|
||||
async.eachSeries(cartItems, async (cartItem, callback) => {
|
||||
// Find index in cart
|
||||
const cartIndex = _.findIndex(req.session.cart, { productId: cartItem.productId });
|
||||
if(productQuantity === 0){
|
||||
// quantity equals zero so we remove the item
|
||||
delete req.session.cart[cartItem.productId];
|
||||
res.status(400).json({ message: 'There was an error updating the cart', totalCartItems: Object.keys(req.session.cart).length });
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the quantity to update
|
||||
let productQuantity = cartItem.quantity ? cartItem.quantity : 1;
|
||||
if(typeof productQuantity === 'string'){
|
||||
productQuantity = parseInt(productQuantity);
|
||||
}
|
||||
const product = await db.products.findOne({ _id: getId(cartItem.productId) });
|
||||
if(!product){
|
||||
res.status(400).json({ message: 'There was an error updating the cart', totalCartItems: Object.keys(req.session.cart).length });
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('productQuantity', productQuantity);
|
||||
if(productQuantity === 0){
|
||||
// quantity equals zero so we remove the item
|
||||
req.session.cart.splice(cartIndex, 1);
|
||||
callback(null);
|
||||
// If stock management on check there is sufficient stock for this product
|
||||
if(config.trackStock){
|
||||
if(productQuantity > product.productStock){
|
||||
res.status(400).json({ message: 'There is insufficient stock of this product.', totalCartItems: Object.keys(req.session.cart).length });
|
||||
return;
|
||||
}
|
||||
const product = await db.products.findOne({ _id: getId(cartItem.productId) });
|
||||
if(product){
|
||||
// If stock management on check there is sufficient stock for this product
|
||||
if(config.trackStock){
|
||||
if(productQuantity > product.productStock){
|
||||
hasError = true;
|
||||
stockError = true;
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const productPrice = parseFloat(product.productPrice).toFixed(2);
|
||||
if(req.session.cart[cartIndex]){
|
||||
req.session.cart[cartIndex].quantity = productQuantity;
|
||||
req.session.cart[cartIndex].totalItemPrice = productPrice * productQuantity;
|
||||
callback(null);
|
||||
}
|
||||
}else{
|
||||
hasError = true;
|
||||
callback(null);
|
||||
}
|
||||
}, async () => {
|
||||
// update total cart amount
|
||||
updateTotalCartAmount(req, res);
|
||||
const productPrice = parseFloat(product.productPrice).toFixed(2);
|
||||
if(!req.session.cart[cartItem.productId]){
|
||||
res.status(400).json({ message: 'There was an error updating the cart', totalCartItems: Object.keys(req.session.cart).length });
|
||||
return;
|
||||
}
|
||||
|
||||
// Update checking cart for subscription
|
||||
updateSubscriptionCheck(req, res);
|
||||
// Update the cart
|
||||
req.session.cart[cartItem.productId].quantity = productQuantity;
|
||||
req.session.cart[cartItem.productId].totalItemPrice = productPrice * productQuantity;
|
||||
|
||||
// Update cart to the DB
|
||||
await db.cart.updateOne({ sessionId: req.session.id }, {
|
||||
$set: { cart: req.session.cart }
|
||||
});
|
||||
// update total cart amount
|
||||
updateTotalCart(req, res);
|
||||
|
||||
// show response
|
||||
if(hasError === false){
|
||||
res.status(200).json({ message: 'Cart successfully updated', totalCartItems: Object.keys(req.session.cart).length });
|
||||
}else{
|
||||
if(stockError){
|
||||
res.status(400).json({ message: 'There is insufficient stock of this product.', totalCartItems: Object.keys(req.session.cart).length });
|
||||
}else{
|
||||
res.status(400).json({ message: 'There was an error updating the cart', totalCartItems: Object.keys(req.session.cart).length });
|
||||
}
|
||||
}
|
||||
// Update checking cart for subscription
|
||||
updateSubscriptionCheck(req, res);
|
||||
|
||||
// Update cart to the DB
|
||||
await db.cart.updateOne({ sessionId: req.session.id }, {
|
||||
$set: { cart: req.session.cart }
|
||||
});
|
||||
|
||||
res.status(200).json({ message: 'Cart successfully updated', totalCartItems: Object.keys(req.session.cart).length });
|
||||
});
|
||||
|
||||
// Remove single product from cart
|
||||
router.post('/product/removefromcart', async (req, res, next) => {
|
||||
const db = req.app.db;
|
||||
let itemRemoved = false;
|
||||
|
||||
// Check for item in cart
|
||||
if(!req.session.cart[req.body.productId]){
|
||||
return res.status(400).json({ message: 'Product not found in cart' });
|
||||
}
|
||||
|
||||
// remove item from cart
|
||||
req.session.cart.forEach((item) => {
|
||||
if(item){
|
||||
if(item.productId === req.body.cartId){
|
||||
itemRemoved = true;
|
||||
req.session.cart = _.pull(req.session.cart, item);
|
||||
}
|
||||
}
|
||||
});
|
||||
delete req.session.cart[req.body.productId];
|
||||
|
||||
// If not items in cart, empty it
|
||||
if(Object.keys(req.session.cart).length === 0){
|
||||
return emptyCart(req, res, 'json');
|
||||
}
|
||||
|
||||
// Update cart in DB
|
||||
await db.cart.updateOne({ sessionId: req.session.id }, {
|
||||
$set: { cart: req.session.cart }
|
||||
});
|
||||
// update total cart amount
|
||||
updateTotalCartAmount(req, res);
|
||||
// update total cart
|
||||
updateTotalCart(req, res);
|
||||
|
||||
// Update checking cart for subscription
|
||||
updateSubscriptionCheck(req, res);
|
||||
|
||||
if(itemRemoved === false){
|
||||
return res.status(400).json({ message: 'Product not found in cart' });
|
||||
}
|
||||
return res.status(200).json({ message: 'Product successfully removed', totalCartItems: Object.keys(req.session.cart).length });
|
||||
});
|
||||
|
||||
|
@ -372,8 +355,8 @@ const emptyCart = async (req, res, type, customMessage) => {
|
|||
// Remove cart from DB
|
||||
await db.cart.deleteOne({ sessionId: req.session.id });
|
||||
|
||||
// update total cart amount
|
||||
updateTotalCartAmount(req, res);
|
||||
// update total cart
|
||||
updateTotalCart(req, res);
|
||||
|
||||
// Update checking cart for subscription
|
||||
updateSubscriptionCheck(req, res);
|
||||
|
@ -409,7 +392,7 @@ router.post('/product/addtocart', async (req, res, next) => {
|
|||
|
||||
// setup cart object if it doesn't exist
|
||||
if(!req.session.cart){
|
||||
req.session.cart = [];
|
||||
req.session.cart = {};
|
||||
}
|
||||
|
||||
// Get the product from the DB
|
||||
|
@ -425,14 +408,19 @@ router.post('/product/addtocart', async (req, res, next) => {
|
|||
}
|
||||
|
||||
// If existing cart isn't empty check if product is a subscription
|
||||
if(req.session.cart.length !== 0){
|
||||
if(Object.keys(req.session.cart).length !== 0){
|
||||
if(product.productSubscription){
|
||||
return res.status(400).json({ message: 'You cannot combine scubscription products with existing in your cart. Empty your cart and try again.' });
|
||||
return res.status(400).json({ message: 'You cannot combine subscription products with existing in your cart. Empty your cart and try again.' });
|
||||
}
|
||||
}
|
||||
|
||||
// If stock management on check there is sufficient stock for this product
|
||||
if(config.trackStock && product.productStock){
|
||||
// If there is more stock than total (ignoring held)
|
||||
if(productQuantity > product.productStock){
|
||||
return res.status(400).json({ message: 'There is insufficient stock of this product.' });
|
||||
}
|
||||
|
||||
const stockHeld = await db.cart.aggregate(
|
||||
{
|
||||
$match: {
|
||||
|
@ -478,22 +466,14 @@ router.post('/product/addtocart', async (req, res, next) => {
|
|||
}
|
||||
}catch(ex){}
|
||||
}
|
||||
const findDoc = {
|
||||
productId: req.body.productId,
|
||||
options: options
|
||||
};
|
||||
|
||||
// if exists we add to the existing value
|
||||
const cartIndex = _.findIndex(req.session.cart, findDoc);
|
||||
let cartQuantity = 0;
|
||||
if(cartIndex > -1){
|
||||
cartQuantity = parseInt(req.session.cart[cartIndex].quantity) + productQuantity;
|
||||
req.session.cart[cartIndex].quantity = cartQuantity;
|
||||
req.session.cart[cartIndex].totalItemPrice = productPrice * parseInt(req.session.cart[cartIndex].quantity);
|
||||
if(req.session.cart[product._id]){
|
||||
cartQuantity = parseInt(req.session.cart[product._id].quantity) + productQuantity;
|
||||
req.session.cart[product._id].quantity = cartQuantity;
|
||||
req.session.cart[product._id].totalItemPrice = productPrice * parseInt(req.session.cart[product._id].quantity);
|
||||
}else{
|
||||
// Doesnt exist so we add to the cart session
|
||||
req.session.cartTotalItems = req.session.cartTotalItems + productQuantity;
|
||||
|
||||
// Set the card quantity
|
||||
cartQuantity = productQuantity;
|
||||
|
||||
|
@ -514,7 +494,7 @@ router.post('/product/addtocart', async (req, res, next) => {
|
|||
}
|
||||
|
||||
// merge into the current cart
|
||||
req.session.cart.push(productObj);
|
||||
req.session.cart[product._id] = productObj;
|
||||
}
|
||||
|
||||
// Update cart to the DB
|
||||
|
@ -523,7 +503,7 @@ router.post('/product/addtocart', async (req, res, next) => {
|
|||
}, { upsert: true });
|
||||
|
||||
// update total cart amount
|
||||
updateTotalCartAmount(req, res);
|
||||
updateTotalCart(req, res);
|
||||
|
||||
// Update checking cart for subscription
|
||||
updateSubscriptionCheck(req, res);
|
||||
|
@ -532,8 +512,6 @@ router.post('/product/addtocart', async (req, res, next) => {
|
|||
req.session.cartSubscription = product.productSubscription;
|
||||
}
|
||||
|
||||
// update how many products in the shopping cart
|
||||
req.session.cartTotalItems = req.session.cart.reduce((a, b) => +a + +b.quantity, 0);
|
||||
return res.status(200).json({ message: 'Cart successfully updated', totalCartItems: req.session.cartTotalItems });
|
||||
});
|
||||
|
||||
|
|
|
@ -75,13 +75,13 @@ test('[Success] Update cart', async t => {
|
|||
.get('/cart/retrieve')
|
||||
.expect(200);
|
||||
|
||||
// Adjust the quantity of an item
|
||||
cart.body.cart[0].quantity = 10;
|
||||
const productId = g.products[0]._id;
|
||||
|
||||
const res = await g.request
|
||||
.post('/product/updatecart')
|
||||
.send({
|
||||
items: JSON.stringify(cart.body.cart)
|
||||
productId: productId,
|
||||
quantity: 10
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -92,8 +92,8 @@ test('[Success] Update cart', async t => {
|
|||
.expect(200);
|
||||
|
||||
// Check new quantity and total price has been updated
|
||||
t.deepEqual(checkCart.body.cart[0].quantity, 10);
|
||||
t.deepEqual(checkCart.body.cart[0].totalItemPrice, cart.body.cart[0].totalItemPrice * 10);
|
||||
t.deepEqual(checkCart.body.cart[productId].quantity, 10);
|
||||
t.deepEqual(checkCart.body.cart[productId].totalItemPrice, cart.body.cart[productId].totalItemPrice * 10);
|
||||
});
|
||||
|
||||
test('[Fail] Cannot add subscripton when other product in cart', async t => {
|
||||
|
@ -105,7 +105,7 @@ test('[Fail] Cannot add subscripton when other product in cart', async t => {
|
|||
productOptions: {}
|
||||
})
|
||||
.expect(400);
|
||||
t.deepEqual(res.body.message, 'You cannot combine scubscription products with existing in your cart. Empty your cart and try again.');
|
||||
t.deepEqual(res.body.message, 'You cannot combine subscription products with existing in your cart. Empty your cart and try again.');
|
||||
});
|
||||
|
||||
test('[Fail] Add product to cart with not enough stock', async t => {
|
||||
|
@ -132,10 +132,20 @@ test('[Fail] Add incorrect product to cart', async t => {
|
|||
});
|
||||
|
||||
test('[Success] Remove item previously added to cart', async t => {
|
||||
// Add a second product to cart
|
||||
await g.request
|
||||
.post('/product/addtocart')
|
||||
.send({
|
||||
productId: g.products[1]._id,
|
||||
productQuantity: 1,
|
||||
productOptions: JSON.stringify(g.products[1].productOptions)
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const res = await g.request
|
||||
.post('/product/removefromcart')
|
||||
.send({
|
||||
cartId: g.products[0]._id
|
||||
productId: g.products[0]._id
|
||||
})
|
||||
.expect(200);
|
||||
t.deepEqual(res.body.message, 'Product successfully removed');
|
||||
|
|
|
@ -2,51 +2,53 @@
|
|||
<div class="card top-marg-15 bottom-marg-15">
|
||||
<div class="card-body cart-body">
|
||||
<h5 class="card-title">{{ @root.__ "Cart contents" }}</h5>
|
||||
{{#each @root.session.cart}}
|
||||
<div class="d-flex flex-row bottom-pad-15">
|
||||
<div class="col-xs-4 col-md-3">
|
||||
{{#if productImage}}
|
||||
<img class="img-fluid" src="{{this.productImage}}" alt="{{this.title}} product image"> {{else}}
|
||||
<img class="img-fluid" src="/uploads/placeholder.png" alt="{{this.title}} product image"> {{/if}}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-7">
|
||||
<div class="row h-200">
|
||||
<div class="col-sm-12 text-left no-pad-left">
|
||||
<h6><a href="/product/{{this.link}}">{{this.title}}</a></h6>
|
||||
</div>
|
||||
<div class="col-sm-12 text-left no-pad-left">
|
||||
{{#each this.options}}
|
||||
{{#if @last}}
|
||||
{{@key}}: {{this}}
|
||||
{{else}}
|
||||
{{@key}}: {{this}} /
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#ifCond cartReadOnly '!=' true}}
|
||||
<div class="col-md-8 no-pad-left">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button class="btn btn-outline-primary btn-qty-minus" type="button">-</button>
|
||||
</div>
|
||||
<input type="number" class="form-control cart-product-quantity text-center" data-id="{{../this.productId}}" data-index="{{@key}}"
|
||||
maxlength="2" value="{{../this.quantity}}">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-primary btn-qty-add" type="button">+</button>
|
||||
<div id="cartBodyWrapper">
|
||||
{{#each @root.session.cart}}
|
||||
<div class="d-flex flex-row bottom-pad-15">
|
||||
<div class="col-xs-4 col-md-3">
|
||||
{{#if productImage}}
|
||||
<img class="img-fluid" src="{{this.productImage}}" alt="{{this.title}} product image"> {{else}}
|
||||
<img class="img-fluid" src="/uploads/placeholder.png" alt="{{this.title}} product image"> {{/if}}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-7">
|
||||
<div class="row h-200">
|
||||
<div class="col-sm-12 text-left no-pad-left">
|
||||
<h6><a href="/product/{{this.link}}">{{this.title}}</a></h6>
|
||||
</div>
|
||||
<div class="col-sm-12 text-left no-pad-left">
|
||||
{{#each this.options}}
|
||||
{{#if @last}}
|
||||
{{@key}}: {{this}}
|
||||
{{else}}
|
||||
{{@key}}: {{this}} /
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#ifCond cartReadOnly '!=' true}}
|
||||
<div class="col-md-8 no-pad-left">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button class="btn btn-outline-primary btn-qty-minus" type="button">-</button>
|
||||
</div>
|
||||
<input type="number" class="form-control cart-product-quantity text-center" data-id="{{../this.productId}}" data-index="{{@key}}"
|
||||
maxlength="2" value="{{../this.quantity}}">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-primary btn-qty-add" type="button">+</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 text-right">
|
||||
<button class="btn btn-outline-danger btn-delete-from-cart" data-id="{{../this.productId}}" type="button"><i class="fa fa-trash" data-id="{{../this.productId}}" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
{{/ifCond}}
|
||||
</div>
|
||||
<div class="col-md-4 text-right">
|
||||
<button class="btn btn-outline-danger btn-delete-from-cart" data-id="{{../this.productId}}" type="button"><i class="fa fa-trash" data-id="{{../this.productId}}" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
{{/ifCond}}
|
||||
</div>
|
||||
<div class="align-self-center col-sm-12 col-md-2 text-right no-pad-right">
|
||||
<strong class="my-auto">{{currencySymbol @root.config.currencySymbol}}{{formatAmount this.totalItemPrice}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="align-self-center col-sm-12 col-md-2 text-right no-pad-right">
|
||||
<strong class="my-auto">{{currencySymbol @root.config.currencySymbol}}{{formatAmount this.totalItemPrice}}</strong>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
<div class="container-fluid">
|
||||
{{#if @root.session.cart}}
|
||||
<div class="row">
|
||||
|
|
Loading…
Reference in New Issue