Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Draft
- Updated accessibility features [2656](https://github.com/bigcommerce/cornerstone/pull/2656)
- Respect `available_to_sell` on PDP so the Sold Out alert is hidden and the Add to Cart button stays enabled for backorderable products, and is disabled when quantity exceeds `available_to_sell` [#2659](https://github.com/bigcommerce/cornerstone/pull/2659)
- Updated accessibility features [2656](https://github.com/bigcommerce/cornerstone/pull/2656)
- Update 'Ship to' copy for multi address orders [#2655](https://github.com/bigcommerce/cornerstone/pull/2655)
- Fixed typo in category page reset-filters live region handler [#2643](https://github.com/bigcommerce/cornerstone/pull/2643)
- Swap content/data keys in onProductOptionsChanged event detail [#2640](https://github.com/bigcommerce/cornerstone/pull/2640)
Expand Down
56 changes: 54 additions & 2 deletions assets/js/theme/common/product-details-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export default class ProductDetailsBase {

this._makeProductVariantAccessible(value, type);
});

if ((parseInt(this.context.availableToSell, 10) || 0) > 0) {
this.toggleSoldOutAlert(true);
}
}

_makeProductVariantAccessible(variantDomNode, variantType) {
Expand Down Expand Up @@ -298,6 +302,31 @@ export default class ProductDetailsBase {
}
}

updateAddToCartForQty(qty, passedViewModel) {
const viewModel = passedViewModel || this.getViewModel(this.$scope);
const availableToSell = parseInt(this.context.availableToSell, 10) || 0;

if (availableToSell <= 0) return;

const $variantMessage = $('#add-to-cart-wrapper .productAttributes-message', this.$scope);

if (qty > availableToSell) {
viewModel.$addToCart.prop('disabled', true);

const template = this.context.quantityMaxMessage || 'The maximum purchasable quantity is __QTY__';
const message = template.replace('__QTY__', availableToSell);
$('.alertBox-message', $variantMessage).text(message);
$variantMessage.attr('data-qty-limit', 'true').show();
} else if (!viewModel.$increments.prop('disabled')) {
viewModel.$addToCart.prop('disabled', false);

if ($variantMessage.attr('data-qty-limit') === 'true') {
$variantMessage.removeAttr('data-qty-limit').hide();
$('.alertBox-message', $variantMessage).text('');
}
}
}

updateBackorderContext(data) {
if (typeof data.available_on_hand === 'number') {
this.context.availableOnHand = data.available_on_hand;
Expand Down Expand Up @@ -397,6 +426,7 @@ export default class ProductDetailsBase {
this.updateBackorderMessage(viewModel);

this.updateDefaultAttributesForOOS(data);
this.updateAddToCartForQty(currentQty, viewModel);
this.updateWalletButtonsView(data);

// If Bulk Pricing rendered HTML is available
Expand Down Expand Up @@ -488,20 +518,42 @@ export default class ProductDetailsBase {

updateDefaultAttributesForOOS(data) {
const viewModel = this.getViewModel(this.$scope);
if (!data.purchasable || !data.instock) {
const dataAvailableToSell = typeof data.available_to_sell === 'number'
? data.available_to_sell
: parseInt(this.context.availableToSell, 10) || 0;
const canSell = data.instock || dataAvailableToSell > 0;
if (!data.purchasable || !canSell) {
viewModel.$addToCart.prop('disabled', true);
viewModel.$increments.prop('disabled', true);
} else {
viewModel.$addToCart.prop('disabled', false);
viewModel.$increments.prop('disabled', false);
}

this.toggleSoldOutAlert(canSell);
}

toggleSoldOutAlert(canSell) {
const $soldOut = $('#add-to-cart-wrapper .alertBox--error', this.$scope).not('.productAttributes-message');
const $variantMessage = $('#add-to-cart-wrapper .productAttributes-message', this.$scope);

if (canSell) {
$soldOut.hide();
$variantMessage.hide();
} else if ($soldOut.length) {
$soldOut.show();
}
}

updateWalletButtonsView(data) {
const viewModel = this.getViewModel(this.$scope);
const isValidForm = viewModel.$addToCartForm?.[0]?.checkValidity() ?? true;
const dataAvailableToSell = typeof data.available_to_sell === 'number'
? data.available_to_sell
: parseInt(this.context.availableToSell, 10) || 0;
const canSell = data.instock || dataAvailableToSell > 0;

this.toggleWalletButtonsVisibility(isValidForm && data.purchasable && data.instock);
this.toggleWalletButtonsVisibility(isValidForm && data.purchasable && canSell);
}

toggleWalletButtonsVisibility(shouldShow) {
Expand Down
24 changes: 13 additions & 11 deletions assets/js/theme/common/product-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,17 @@ export default class ProductDetails extends ProductDetailsBase {
this.setProductVariant();
});

if (!$productOptionsElement.length) {
const simpleProductId = $('[name="product_id"]', $form).val();
utils.api.productAttributes.optionChange(simpleProductId, $form.serialize(), (err, response) => {
if (err || !response || !response.data) return;
this.updateBackorderContext(response.data);
const vm = this.getViewModel(this.$scope);
const qty = parseInt(vm.quantity.$input.val(), 10) || 0;
this.updateQtyBackorderedMessage(qty, vm);
this.updateBackorderMessage(vm);
});
}
const productId = $('[name="product_id"]', $form).val();
utils.api.productAttributes.optionChange(productId, $form.serialize(), (err, response) => {
if (err || !response || !response.data) return;
this.updateBackorderContext(response.data);
const vm = this.getViewModel(this.$scope);
const qty = parseInt(vm.quantity.$input.val(), 10) || 0;
this.updateQtyBackorderedMessage(qty, vm);
this.updateBackorderMessage(vm);
this.updateDefaultAttributesForOOS(response.data);
this.updateAddToCartForQty(qty, vm);
});

$form.on('submit', event => {
this.addToCartValidator.performCheck();
Expand Down Expand Up @@ -393,6 +393,7 @@ export default class ProductDetails extends ProductDetailsBase {
this.updateProductDetailsData();
this.updateQtyBackorderedMessage(qty, viewModel);
this.updateBackorderMessage(viewModel);
this.updateAddToCartForQty(qty, viewModel);
});

// Prevent triggering quantity change when pressing enter
Expand All @@ -411,6 +412,7 @@ export default class ProductDetails extends ProductDetailsBase {
this.updateProductDetailsData();
this.updateQtyBackorderedMessage(qty, viewModel);
this.updateBackorderMessage(viewModel);
this.updateAddToCartForQty(qty, viewModel);
});
}

Expand Down
12 changes: 7 additions & 5 deletions templates/components/products/add-to-cart.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@
{{/if}}

{{#if product.out_of_stock}}
{{#if product.out_of_stock_message}}
{{> components/common/alert/alert-error product.out_of_stock_message}}
{{else}}
{{> components/common/alert/alert-error (lang 'products.sold_out')}}
{{/if}}
{{#unless product.available_to_sell}}
{{#if product.out_of_stock_message}}
{{> components/common/alert/alert-error product.out_of_stock_message}}
{{else}}
{{> components/common/alert/alert-error (lang 'products.sold_out')}}
{{/if}}
{{/unless}}
{{/if}}

<div class="alertBox alertBox--error productAttributes-message" style="display:none">
Expand Down
1 change: 1 addition & 0 deletions templates/components/products/product-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{{inject 'showBackorderAvailabilityPrompt' product.show_backorder_availability_prompt}}
{{inject 'backorderAvailabilityPrompt' product.backorder_availability_prompt}}
{{inject 'quantityBackorderedMessage' (lang 'products.quantity_backordered' quantity='__QTY__')}}
{{inject 'quantityMaxMessage' (lang 'products.quantity_max' quantity='__QTY__')}}
{{inject 'backorderMessages' backorder_messages}}
{{inject 'showBackorderMessage' product.show_backorder_message}}

Expand Down
Loading