diff --git a/blocks/pdp/add-to-cart.js b/blocks/pdp/add-to-cart.js index d70ea036..76dab6cd 100644 --- a/blocks/pdp/add-to-cart.js +++ b/blocks/pdp/add-to-cart.js @@ -222,5 +222,11 @@ export default function renderAddToCart(block, parent) { // add quantity container to main add to cart container addToCartContainer.appendChild(quantityContainer); + // preload formkey on hover of atc container + addToCartContainer.addEventListener('mouseover', async () => { + const { cartApi } = await import('../../scripts/minicart/api.js'); + await cartApi.getFormKey(); + }, { once: true }); + return addToCartContainer; } diff --git a/scripts/minicart/api.js b/scripts/minicart/api.js index a4fe07aa..3cf6f03a 100644 --- a/scripts/minicart/api.js +++ b/scripts/minicart/api.js @@ -60,8 +60,10 @@ class Store { return Store.DEFAULT_CART; } - async updateCart() { - await updateMagentoCacheSections(['cart']); + async updateCart(updateCache = true) { + if (updateCache) { + await updateMagentoCacheSections(['cart']); + } this.notifySubscribers(); } @@ -88,6 +90,10 @@ class Store { export const store = new Store(); export const cartApi = { + getFormKey: async () => { + const { getFormKey } = await import('./cart.js'); + return getFormKey(); + }, addToCart: async (sku, options, quantity) => { const { addToCart } = await import('./cart.js'); // const { showCart } = await import('./Minicart.js'); diff --git a/scripts/minicart/cart.js b/scripts/minicart/cart.js index 94ea3aef..d52a21d8 100644 --- a/scripts/minicart/cart.js +++ b/scripts/minicart/cart.js @@ -164,34 +164,6 @@ export async function performMonolithGraphQLQuery(query, variables, GET = true, return response.json(); } -const handleCartErrors = (errors) => { - if (!errors) { - return; - } - - // Cart cannot be found - if (errors.some(({ extensions }) => extensions?.category === 'graphql-no-such-entity')) { - console.error('Cart does not exist, resetting cart'); - store.resetCart(); - return; - } - - // No access to cart - if (errors.some(({ extensions }) => extensions?.category === 'graphql-authorization')) { - console.error('No access to cart, resetting cart'); - store.resetCart(); - return; - } - - if (errors.some(({ extensions }) => extensions?.category === 'graphql-input')) { - console.error('Some items in the cart might not be available anymore'); - return; - } - - // Throw for everything else - throw new Error(errors); -}; - /** * Function called when waiting for the cart to return. * TODO: Should be customized with selectors specific to your implementation. @@ -224,7 +196,7 @@ export async function resolveSessionCartDrift(options) { return; } - let done = () => {}; + let done = () => { }; if (options.waitForCart) { done = waitForCart(); } @@ -248,7 +220,7 @@ export async function resolveSessionCartDrift(options) { } export function updateCartFromLocalStorage(options) { - let done = () => {}; + let done = () => { }; if (options.waitForCart) { done = waitForCart(); } @@ -281,25 +253,18 @@ export function updateCartFromLocalStorage(options) { done(); } -function hasExtendedWarranty() { - return window.selectedWarranty?.price && window.selectedWarranty.price !== '0.00'; -} - -function hasCouponParam() { - return window.location.search?.toLowerCase().includes('coupon'); -} - -function shouldUseLegacyAddToCart() { - return hasExtendedWarranty() || hasCouponParam(); -} - +/** @type {Promise} */ let pformKey; -async function getFormKey() { +export async function getFormKey() { if (!pformKey) { - const resp = await fetch('/us/en_us/checkout/cart/'); - const txt = await resp.text(); - const input = txt.match(/ resp.text()) + .then((txt) => { + const input = txt.match(/ { pformKey = null; @@ -400,47 +365,8 @@ async function addToCartLegacy(sku, options, quantity) { export async function addToCart(sku, options, quantity) { const done = waitForCart(); try { - if (shouldUseLegacyAddToCart()) { - await addToCartLegacy(sku, options, quantity); - } else { - const variables = { - cartId: store.getCartId(), - cartItems: [{ - sku, - quantity, - selected_options: options, - }], - }; - - const { data, errors } = await performMonolithGraphQLQuery( - addProductsToCartMutation, - variables, - false, - false, - ); - handleCartErrors(errors); - - const { cart, user_errors: userErrors } = data.addProductsToCart; - if (userErrors && userErrors.length > 0) { - console.error('User errors while adding item to cart', userErrors); - } - - cart.items = cart.items.filter((item) => item); - - // Adding a new line item to the cart incorrectly returns the total - // quantity so we check that and update if necessary - if (cart.items.length > 0) { - const lineItemTotalQuantity = cart.items.flatMap( - (item) => item.quantity, - ).reduce((partialSum, a) => partialSum + a, 0); - if (lineItemTotalQuantity !== cart.total_quantity) { - console.debug('Incorrect total quantity from AC, updating.'); - cart.total_quantity = lineItemTotalQuantity; - } - } - console.debug('Added items to cart', variables, cart); - } - await store.updateCart(); + await addToCartLegacy(sku, options, quantity); + await store.updateCart(false); } catch (err) { console.error('Could not add item to cart', err); } finally { diff --git a/scripts/storage/util.js b/scripts/storage/util.js index bdab6e9b..2991665e 100644 --- a/scripts/storage/util.js +++ b/scripts/storage/util.js @@ -162,7 +162,7 @@ export function isCommerceStatePristine() { * Updates only the Magento cart and customer cache sections. * * @param {string[]} the sections that should be updated - * @return {void} + * @return {Promise} */ export async function updateMagentoCacheSections(sections) { let result = {};