Skip to content

Commit ff97615

Browse files
authored
Merge pull request #1338 from bc-zoharmuzafi/update_qty
Update qty
2 parents ddf41b5 + 786e7da commit ff97615

File tree

4 files changed

+193
-2
lines changed

4 files changed

+193
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- Require Webpack config only when used (reduce time to be ready for receiving messages from stencil-cli). [#1334](https://github.com/bigcommerce/cornerstone/pull/1334)
77
- Fixed amp page error related to store logo [#1323](https://github.com/bigcommerce/cornerstone/pull/1323)
88
- Add link to order status in account menu when viewing order [#1343](https://github.com/bigcommerce/cornerstone/pull/1343)
9+
- Update cart when quantity changed manually (without using the increase and decrease arrows). [#1338](https://github.com/bigcommerce/cornerstone/pull/1338)
910

1011
## 2.3.2 (2018-08-17)
1112
- Fix zoom behavior for small images in gallery (turn off zoom if image is too small). [#1325](https://github.com/bigcommerce/cornerstone/pull/1325)
+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import $ from 'jquery'
2+
import utils from '@bigcommerce/stencil-utils';
3+
import Cart from '../../theme/cart.js';
4+
import * as SweetAlert from 'sweetalert2';
5+
6+
var dataSpy;
7+
var swalSpy;
8+
var UpdateSpy;
9+
var c = new Cart();
10+
beforeEach(function() {
11+
UpdateSpy = spyOn(utils.api.cart, 'itemUpdate');
12+
13+
dataSpy = function(requestedAction = null) {
14+
spyOn(jQuery.fn, 'data').and.callFake(function() {
15+
var param = arguments[0];
16+
switch (param) {
17+
case 'action':
18+
return requestedAction;
19+
case 'cartItemid':
20+
return '11111';
21+
case 'quantityMax':
22+
return 5;
23+
case 'quantityMin':
24+
return 1;
25+
case 'quantityMinError':
26+
return 'min error';
27+
case 'quantityMaxError':
28+
return ' max error';
29+
default:
30+
return null;
31+
}
32+
})
33+
};
34+
});
35+
36+
var $dom = $('<table class="cart" data-cart-quantity="2">\
37+
<thead class="cart-header">\
38+
<tr>\
39+
<th class="cart-header-item" colspan="2">Item</th>\
40+
<th class="cart-header-item">Price</th>\
41+
<th class="cart-header-item cart-header-quantity">Quantity</th>\
42+
<th class="cart-header-item">Total</th>\
43+
</tr>\
44+
</thead>\
45+
<tbody class="cart-list">\
46+
<tr class="cart-item" data-item-row="">\
47+
<td class="cart-item-block cart-item-figure">\
48+
<img class="cart-item-image lazyautosizes lazyloaded" data-sizes="auto" src="www.example.com" data-src="www.example.com" alt="[Sample] product" title="[Sample] product">\
49+
</td>\
50+
<td class="cart-item-block cart-item-title">\
51+
<h4 class="cart-item-name"><a href="/fog-linen-chambray-towel-beige-stripe/">[Sample] Fog Linen Chambray Towel - Beige Stripe</a></h4>\
52+
<dl class="definitionList">\
53+
<dt class="definitionList-key">Size:</dt>\
54+
<dd class="definitionList-value">\
55+
XS\
56+
</dd>\
57+
<dt class="definitionList-key">Color:</dt>\
58+
<dd class="definitionList-value">\
59+
Silver\
60+
</dd>\
61+
</dl>\
62+
<a href="#" data-item-edit="item-id">Change</a>\
63+
</td>\
64+
<td class="cart-item-block cart-item-info">\
65+
<span class="cart-item-label">Price</span>\
66+
<span class="cart-item-value ">$49.00</span>\
67+
</td>\
68+
<td class="cart-item-block cart-item-info cart-item-quantity">\
69+
<label class="form-label cart-item-label" for="qty-item-id">Quantity:</label>\
70+
<div class="form-increment">\
71+
<button class="button button--icon" data-cart-update="" data-cart-itemid="item-id" data-action="dec">\
72+
<span class="is-srOnly">Decrease Quantity:</span>\
73+
<i class="icon" aria-hidden="true"><svg><use xmlns:xlink="www.ccc.com"></use></svg></i>\
74+
</button>\
75+
<input class="form-input form-input--incrementTotal cart-item-qty-input" id="item-id" name="qty-item-id" type="tel" value="2" data-quantity-min="0" data-quantity-max="" data-quantity-min-error="The minimum purchasable quantity is 0" data-quantity-max-error="The maximum purchasable quantity is null" min="1" pattern="[0-9]*" data-cart-itemid="item-id" data-action="manualQtyChange" aria-live="polite">\
76+
<button class="button button--icon" data-cart-update="" data-cart-itemid="item-id" data-action="inc">\
77+
<span class="is-srOnly">Increase Quantity:</span>\
78+
<i class="icon" aria-hidden="true"><svg><use xmlns:xlink="www.ddd.com"></use></svg></i>\
79+
</button>\
80+
</div>\
81+
</td>\
82+
<td class="cart-item-block cart-item-info">\
83+
<span class="cart-item-label">Total</span>\
84+
<strong class="cart-item-value ">$98.00</strong>\
85+
<a class="cart-remove icon" data-cart-itemid="item-id" href="#" data-confirm-delete="Are you sure you want to delete this item?">\
86+
<svg><use xmlns:xlink="www.eee.com" xlink:href="#icon-close"></use></svg>\
87+
</a>\
88+
</td>\
89+
</tr>\
90+
</tbody>\
91+
</table>')
92+
93+
c.onReady();
94+
95+
describe('cartUpdate', () => {
96+
it('should INCRIMENT qty', () => {
97+
dataSpy
98+
dataSpy('inc');
99+
spyOn(jQuery.fn, 'val').and.returnValue(2);
100+
c.cartUpdate($dom);
101+
102+
expect(UpdateSpy).toHaveBeenCalledWith('11111', 3, jasmine.any(Function));
103+
});
104+
105+
it('should DECREMENT qty', () => {
106+
dataSpy
107+
dataSpy('dec');
108+
spyOn(jQuery.fn, 'val').and.returnValue(2);
109+
c.cartUpdate($dom);
110+
111+
expect(UpdateSpy).toHaveBeenCalledWith('11111', 1, jasmine.any(Function));
112+
});
113+
});
114+
115+
describe('cartUpdateQtyTextChange', () => {
116+
it('should CHANGE qty completly based on the cart-item-qty-input', () => {
117+
dataSpy
118+
dataSpy('manualQtyChange');
119+
spyOn(jQuery.fn, 'attr').and.returnValue(5);
120+
spyOn(jQuery.fn, 'val').and.returnValue(2);
121+
c.cartUpdateQtyTextChange($dom);
122+
123+
expect(UpdateSpy).toHaveBeenCalledWith('11111', 5, jasmine.any(Function));
124+
});
125+
});

assets/js/theme/cart.js

+64-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export default class Cart extends PageManager {
2727
const minError = $el.data('quantityMinError');
2828
const maxError = $el.data('quantityMaxError');
2929
const newQty = $target.data('action') === 'inc' ? oldQty + 1 : oldQty - 1;
30-
3130
// Does not quality for min/max quantity
3231
if (newQty < minQty) {
3332
return swal({
@@ -61,6 +60,57 @@ export default class Cart extends PageManager {
6160
});
6261
}
6362

63+
cartUpdateQtyTextChange($target, preVal = null) {
64+
const itemId = $target.data('cartItemid');
65+
const $el = $(`#qty-${itemId}`);
66+
const maxQty = parseInt($el.data('quantityMax'), 10);
67+
const minQty = parseInt($el.data('quantityMin'), 10);
68+
const oldQty = preVal !== null ? preVal : minQty;
69+
const minError = $el.data('quantityMinError');
70+
const maxError = $el.data('quantityMaxError');
71+
const newQty = parseInt(Number($el.attr('value')), 10);
72+
let invalidEntry;
73+
// Does not quality for min/max quantity
74+
if (!newQty) {
75+
invalidEntry = $el.attr('value');
76+
$el.val(oldQty);
77+
return swal({
78+
text: `${invalidEntry} is not a valid entry`,
79+
type: 'error',
80+
});
81+
} else if (newQty < minQty) {
82+
$el.val(oldQty);
83+
return swal({
84+
text: minError,
85+
type: 'error',
86+
});
87+
} else if (maxQty > 0 && newQty > maxQty) {
88+
$el.val(oldQty);
89+
return swal({
90+
text: maxError,
91+
type: 'error',
92+
});
93+
}
94+
95+
this.$overlay.show();
96+
utils.api.cart.itemUpdate(itemId, newQty, (err, response) => {
97+
this.$overlay.hide();
98+
99+
if (response.data.status === 'succeed') {
100+
// if the quantity is changed "1" from "0", we have to remove the row.
101+
const remove = (newQty === 0);
102+
103+
this.refreshContent(remove);
104+
} else {
105+
$el.val(oldQty);
106+
swal({
107+
text: response.data.errors.join('\n'),
108+
type: 'error',
109+
});
110+
}
111+
});
112+
}
113+
64114
cartRemoveItem(itemId) {
65115
this.$overlay.show();
66116
utils.api.cart.itemRemove(itemId, (err, response) => {
@@ -162,7 +212,9 @@ export default class Cart extends PageManager {
162212
bindCartEvents() {
163213
const debounceTimeout = 400;
164214
const cartUpdate = _.bind(_.debounce(this.cartUpdate, debounceTimeout), this);
215+
const cartUpdateQtyTextChange = _.bind(_.debounce(this.cartUpdateQtyTextChange, debounceTimeout), this);
165216
const cartRemoveItem = _.bind(_.debounce(this.cartRemoveItem, debounceTimeout), this);
217+
let preVal;
166218

167219
// cart update
168220
$('[data-cart-update]', this.$cartContent).on('click', event => {
@@ -174,6 +226,17 @@ export default class Cart extends PageManager {
174226
cartUpdate($target);
175227
});
176228

229+
// cart qty manually updates
230+
$('.cart-item-qty-input', this.$cartContent).on('focus', function () {
231+
preVal = this.value;
232+
}).change(event => {
233+
const $target = $(event.currentTarget);
234+
event.preventDefault();
235+
236+
// update cart quantity
237+
cartUpdateQtyTextChange($target, preVal);
238+
});
239+
177240
$('.cart-remove', this.$cartContent).on('click', event => {
178241
const itemId = $(event.currentTarget).data('cartItemid');
179242
const string = $(event.currentTarget).data('confirmDelete');

templates/components/cart/content.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ <h4 class="cart-item-name"><a href="{{url}}">{{name}}</a></h4>
9999
<i class="icon" aria-hidden="true"><svg><use xlink:href="#icon-keyboard-arrow-down" /></svg></i>
100100
</button>
101101
{{/if}}
102-
<input class="form-input form-input--incrementTotal"
102+
<input class="form-input form-input--incrementTotal cart-item-qty-input"
103103
id="qty-{{id}}"
104104
name="qty-{{id}}"
105105
type="tel"
@@ -110,6 +110,8 @@ <h4 class="cart-item-name"><a href="{{url}}">{{name}}</a></h4>
110110
data-quantity-max-error="{{lang 'products.quantity_max' quantity=max_purchase_quantity}}"
111111
min="1"
112112
pattern="[0-9]*"
113+
data-cart-itemid="{{id}}"
114+
data-action="manualQtyChange"
113115
aria-live="polite"{{#unless can_modify}} disabled{{/unless}}>
114116
{{# if can_modify}}
115117
<button class="button button--icon" data-cart-update data-cart-itemid="{{id}}" data-action="inc">

0 commit comments

Comments
 (0)