Skip to content

Commit

Permalink
TH-109: Meraki > Product page > Prevent the customer from placing an …
Browse files Browse the repository at this point in the history
…order if a variant is out of stock (#69)
  • Loading branch information
bj-anas authored Oct 21, 2024
1 parent 5f12d57 commit 9b9ac7d
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 116 deletions.
27 changes: 19 additions & 8 deletions themes/meraki/assets/add-to-cart.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
async function addToCart(snippetId) {
const parentSection = document.querySelector(`#s-${snippetId}`);
const variantId = parentSection.querySelector(`#variantId`)?.value || undefined;
const quantity = parentSection.querySelector(`#quantity`)?.value || 1;
const inventory = parentSection.querySelector(`#_inventory`)?.value || null;
const quantity = parseInt(parentSection.querySelector(`#quantity`)?.value) || 1;
const inventory = parseInt(parentSection.querySelector(`#_inventory`)?.value) || null;
const uploadedImageLink = parentSection.querySelector(`#yc-upload-link`)?.value || undefined;
const variantQuantityInCart = parseInt(document.querySelector('#cartQuantity')?.value) || null;

if (!variantId) {
return notify(ADD_TO_CART_EXPECTED_ERRORS.select_variant, 'error');
Expand All @@ -13,10 +14,14 @@ async function addToCart(snippetId) {
return notify(ADD_TO_CART_EXPECTED_ERRORS.quantity_smaller_than_zero, 'error');
}

if (inventory == 0) {
if (inventory === 0) {
return notify(ADD_TO_CART_EXPECTED_ERRORS.empty_inventory, 'error');
}

if (Number.isFinite(inventory) && ((variantQuantityInCart ?? 0) + quantity) > inventory) {
return notify(ADD_TO_CART_EXPECTED_ERRORS.max_quantity + inventory, 'warning');
}

try {
requestAnimationFrame(() => {
load('#loading__cart');
Expand All @@ -28,6 +33,8 @@ async function addToCart(snippetId) {
quantity,
});

await trackVariantQuantityOnCart(variantId);

if (response.error) throw new Error(response.error);

updateCartCount(response.count);
Expand Down Expand Up @@ -57,9 +64,11 @@ function attachRemoveItemListeners() {
const cartItemId = event.target.getAttribute('data-cart-item-id');
const productVariantId = event.target.getAttribute('data-product-variant-id');

await removeCartItem(cartItemId, productVariantId);
await updateCartDrawer();
updateCartCount(-1, true);
if(cartItemId && productVariantId) {
await removeCartItem(cartItemId, productVariantId);
await updateCartDrawer();
updateCartCount(-1, true);
}
})
);
}
Expand All @@ -74,6 +83,8 @@ async function removeCartItem(cartItemId, productVariantId) {
cartItemId,
productVariantId,
});

await trackVariantQuantityOnCart(productVariantId);
} catch (error) {
notify(error.message, 'error');
} finally {
Expand Down Expand Up @@ -106,7 +117,7 @@ function cartTemplate(item) {
</div>
<div class="product-price">
${
item.productVariant.compare_at_price ?
item.productVariant.compare_at_price ?
`<span class="compare-price">${item.productVariant.compare_at_price}</span>` : ''
}
<div class="currency-wrapper">
Expand Down Expand Up @@ -157,7 +168,7 @@ async function updateCartDrawer() {

if (item.productVariant.compare_at_price) {
item.productVariant.compare_at_price = formatCurrency(
item.productVariant.compare_at_price,
item.productVariant.compare_at_price,
currencyCode,
customerLocale,
);
Expand Down
10 changes: 8 additions & 2 deletions themes/meraki/assets/dropdown-menu.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
let isDropDownOpened = false;
/**
* @param {HTMLElement} element
*/
function showDropDownMenu(element) {
element.classList.toggle('show');
isDropDownOpened = true;
}

/**
Expand All @@ -12,6 +14,7 @@ function showDropDownMenu(element) {
function hideDropDownMenu(element, event) {
if (!event.target.matches('.dropbtn, .dropbtn *')) {
element?.classList.remove('show');
isDropDownOpened = false;
}
}

Expand Down Expand Up @@ -43,7 +46,11 @@ function dropdownMenu() {
const dropdownContent = dropDownInput.querySelector('.dropdown-content');

selectInput.addEventListener('click', () => showDropDownMenu(dropdownContent));
window.addEventListener('click', (event) => hideDropDownMenu(dropdownContent, event));
document.addEventListener('click', (event) => {
if(isDropDownOpened) {
hideDropDownMenu(dropdownContent, event);
}
});

const selectOptions = dropdownContent.querySelectorAll('li');

Expand All @@ -62,5 +69,4 @@ function dropdownMenu() {
});
});
}

dropdownMenu();
18 changes: 0 additions & 18 deletions themes/meraki/assets/express-checkout.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
border-width:1px;
border-style:solid;
background:#fff;
box-shadow:1px 13px 53px 0px rgba(0, 0, 0, 0.1);
padding:20px;
grid-gap:18px;
}
Expand All @@ -13,23 +12,16 @@
}

.express-checkout-fields{
border-width:1px;
border-style:solid;
background:#fff;
box-shadow:1px 13px 53px 0px rgba(0, 0, 0, 0.1);
display:grid;
grid-template-columns:1fr;
grid-gap:14px;
padding:16px;
}
@media (min-width: 768px){
.express-checkout-fields{
border:medium none currentcolor;
border:initial;
background:transparent none repeat 0 0 / auto auto padding-box border-box scroll;
background:initial;
box-shadow:none;
box-shadow:initial;
padding:0;
padding:initial;
}
Expand Down Expand Up @@ -190,13 +182,3 @@
flex:1 1 50%;
}
}

.sticky-checkout-placeholder .express-checkout-button:disabled{
opacity:0.5;
cursor:not-allowed;
}

.sticky-btn-placehodler{
opacity:0.5;
cursor:not-allowed;
}
1 change: 0 additions & 1 deletion themes/meraki/assets/express-checkout.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ async function placeOrder() {
const formField = form.querySelector(`[name="${fieldName}"]`);
const errorEl = form.querySelector(`.validation-error[data-error="${fieldName}"]`);
if (formField) {
console.log(formField);
formField.classList.add('error');
}

Expand Down
5 changes: 5 additions & 0 deletions themes/meraki/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ button:focus{
.yc-btn > *{
color:white !important;
}
.yc-btn:disabled, .yc-btn[data-type=loading]:disabled{
background:#bdc3c7 !important;
color:#ffffff !important;
cursor:not-allowed;
}

.yc-btn-secondary{
border:1px solid var(--yc-primary-color);
Expand Down
93 changes: 85 additions & 8 deletions themes/meraki/assets/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,45 @@ window.addEventListener('scroll', toggleNavbar);
/* ----- spinner-loader ----- */
/* -------------------------- */
function load(el) {
const loader = document.querySelector(el);
if (loader) {
loader.classList.remove('hidden');
const element = document.querySelector(el);

if (!element) {
return;
}

if (element) {
element.classList.remove('hidden');
}

if (element.parentElement.hasAttribute('data-type')) {
element.parentElement.setAttribute('data-type', 'loading');
element.parentElement.disabled = true;
}

const nextEl = loader ? loader.nextElementSibling : null;
const nextEl = element ? element.nextElementSibling : null;

if (nextEl) {
nextEl.classList.add('hidden');
}
}

function stopLoad(el) {
const loader = document.querySelector(el);
if (loader) {
loader.classList.add('hidden');
const element = document.querySelector(el);

if (!element) {
return;
}

if (element) {
element.classList.add('hidden');
}

if (element.parentElement.hasAttribute('data-type')) {
element.parentElement.setAttribute('data-type', '');
element.parentElement.disabled = false;
}

const nextEl = loader ? loader.nextElementSibling : null;
const nextEl = element ? element.nextElementSibling : null;
if (nextEl) {
nextEl.classList.remove('hidden');
}
Expand Down Expand Up @@ -375,3 +395,60 @@ function shouldUsePrecision(amount) {

return isMulticurrencyActive && usePrecision;
}

/**
* Restrict the input value based on the inventory number
*
* @param {HTMLInputElement} inputElement - The input element.
* @param {number} maxInventoryValue - The maximum allowable inventory value.
*/
function restrictInputValue(inputElement, maxInventoryValue) {

if (maxInventoryValue === null) {
return;
}

let currentValue = parseInt(inputElement.value);

if (currentValue < 1) {
inputElement.value = 1;
}

if (currentValue > maxInventoryValue) {
inputElement.value = maxInventoryValue;
}
}

/**
* Tracks the quantity of a specific variant in the cart and set it in the hidden quantity input.
*
* @param {string} selectedVariantId - The ID of the selected product variant.
*/
async function trackVariantQuantityOnCart(selectedVariantId) {
try {
load('#loading__cart');
const cartQuantityInput = document.querySelector('#cartQuantity');
cartQuantityInput.value = 0;
const cart = await youcanjs.cart.fetch();

if (!cart) {
return;
}

if (cart.items.length === 0 || cart.items.data?.length === 0) {
return;
}

const cartItem = cart.items.find((item) => item.productVariant.id === selectedVariantId);

if (!cartItem || cartItem.productVariant.product.track_inventory === false) {
return;
}

cartQuantityInput.value = cartItem.quantity;
} catch(e) {
notify(e.message, 'error');
} finally {
stopLoad('#loading__cart');
}
}
15 changes: 15 additions & 0 deletions themes/meraki/assets/product-quantity-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ function manipulateQuantity() {
const decrementButton = $('.decrement-button');
const incrementButton = $('.increment-button');
const quantityInput = $('.quantity-input');
const inventoryInput = $('#_inventory');

/**
* Decreases quantity value by 1 when decrement button is clicked
Expand All @@ -21,8 +22,22 @@ function manipulateQuantity() {
*/
incrementButton?.addEventListener('click', () => {
const currentValue = parseInt(quantityInput.value);
const inventory = parseInt(inventoryInput.value);

if(Number.isFinite(inventory) && currentValue >= inventory) {
return notify(ADD_TO_CART_EXPECTED_ERRORS.max_quantity + inventory, 'warning');
}

quantityInput.value = currentValue + 1;
});

/**
* Check if the current value exceeds the max inventory
*/
quantityInput?.addEventListener('input', () => {
const maxInventoryValue = parseInt(inventoryInput.value);
restrictInputValue(quantityInput, maxInventoryValue);
});
}

manipulateQuantity();
10 changes: 0 additions & 10 deletions themes/meraki/assets/product.css
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,6 @@
padding-bottom:20px;
}

.add-to-cart-btn button:disabled{
cursor:not-allowed;
opacity:0.5;
}

.add-to-cart-btn:disabled{
background-color:#E7E7E7;
color:#8D8D8D;
}

.single-product-placeholder .product-images svg{
width:100%;
height:333px;
Expand Down
Loading

0 comments on commit 9b9ac7d

Please sign in to comment.