diff --git a/.vscode/settings.json b/.vscode/settings.json index 39e44f17346..90abaf1f399 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,8 @@ { "editor.formatOnSave": false, "[javascript]": { - "editor.formatOnSave": true + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[css]": { "editor.formatOnSave": true diff --git a/assets/bulk-add.js b/assets/bulk-add.js deleted file mode 100644 index 0821122f3b8..00000000000 --- a/assets/bulk-add.js +++ /dev/null @@ -1,41 +0,0 @@ -class BulkAdd extends HTMLElement { - constructor() { - super(); - this.queue = [] - this.requestStarted = false; - this.ids = [] - } - - startQueue(id, quantity) { - this.queue.push({id, quantity}) - const interval = setInterval(() => { - if (this.queue.length > 0) { - if (!this.requestStarted) { - this.sendRequest(this.queue) - } - } else { - clearInterval(interval) - } - }, 250) - } - - - sendRequest(queue) { - this.requestStarted = true; - const items = {} - const ids = [] - queue.forEach((queueItem) => { - items[parseInt(queueItem.id)] = queueItem.quantity; - ids.push(queueItem.id) - }); - this.queue = this.queue.filter(queueElement => !queue.includes(queueElement)); - const quickOrderList = this.closest('quick-order-list'); - quickOrderList.updateMultipleQty(items, ids) - } -} - -if (!customElements.get('bulk-add')) { - customElements.define('bulk-add', BulkAdd) -}; - - diff --git a/assets/global.js b/assets/global.js index 3ccdd967de9..29ee2cfe353 100644 --- a/assets/global.js +++ b/assets/global.js @@ -1360,3 +1360,82 @@ class AccountIcon extends HTMLElement { } customElements.define('account-icon', AccountIcon); + +class BulkAdd extends HTMLElement { + constructor() { + super(); + this.queue = []; + this.requestStarted = false; + this.ids = []; + } + + startQueue(id, quantity) { + this.queue.push({ id, quantity }); + const interval = setInterval(() => { + if (this.queue.length > 0) { + if (!this.requestStarted) { + this.sendRequest(this.queue); + } + } else { + clearInterval(interval); + } + }, 250); + } + + sendRequest(queue) { + this.requestStarted = true; + const items = {}; + queue.forEach((queueItem) => { + items[parseInt(queueItem.id)] = queueItem.quantity; + }); + this.queue = this.queue.filter((queueElement) => !queue.includes(queueElement)); + const quickBulkElement = this.closest('quick-order-list') || this.closest('quick-add-bulk'); + quickBulkElement.updateMultipleQty(items); + } + + resetQuantityInput(id) { + const input = this.querySelector(`#Quantity-${id}`); + input.value = input.getAttribute('value'); + this.isEnterPressed = false; + } + + setValidity(event, index, message) { + event.target.setCustomValidity(message); + event.target.reportValidity(); + this.resetQuantityInput(index); + event.target.select(); + } + + validateQuantity(event) { + const inputValue = parseInt(event.target.value); + const index = event.target.dataset.index; + + if (inputValue < event.target.dataset.min) { + this.setValidity(event, index, window.quickOrderListStrings.min_error.replace('[min]', event.target.dataset.min)); + } else if (inputValue > parseInt(event.target.max)) { + this.setValidity(event, index, window.quickOrderListStrings.max_error.replace('[max]', event.target.max)); + } else if (inputValue % parseInt(event.target.step) != 0) { + this.setValidity(event, index, window.quickOrderListStrings.step_error.replace('[step]', event.target.step)); + } else { + event.target.setCustomValidity(''); + event.target.reportValidity(); + this.startQueue(index, inputValue); + } + } + + getSectionsUrl() { + if (window.pageNumber) { + return `${window.location.pathname}?page=${window.pageNumber}`; + } else { + return `${window.location.pathname}`; + } + } + + getSectionInnerHTML(html, selector) { + return new DOMParser().parseFromString(html, 'text/html').querySelector(selector).innerHTML; + } +} + +if (!customElements.get('bulk-add')) { + customElements.define('bulk-add', BulkAdd); +} diff --git a/assets/quick-add-bulk.js b/assets/quick-add-bulk.js index 935d6f6a61d..1208ffe7241 100644 --- a/assets/quick-add-bulk.js +++ b/assets/quick-add-bulk.js @@ -1,16 +1,16 @@ if (!customElements.get('quick-add-bulk')) { customElements.define( 'quick-add-bulk', - class QuickAddBulk extends HTMLElement { + class QuickAddBulk extends BulkAdd { constructor() { super(); this.quantity = this.querySelector('quantity-input'); const debouncedOnChange = debounce((event) => { - if (parseInt(event.target.dataset.cartQuantity) === 0) { - this.addToCart(event); + if (parseInt(event.target.value) === 0) { + this.startQueue(event.target.dataset.index, parseInt(event.target.value)); } else { - this.updateCart(event); + this.validateQuantity(event); } }, ON_CHANGE_DEBOUNCE_TIMER); @@ -65,12 +65,6 @@ if (!customElements.get('quick-add-bulk')) { }); } - resetQuantityInput(id) { - const input = document.getElementById(id); - input.value = input.getAttribute('value'); - this.isEnterPressed = false; - } - cleanErrorMessageOnType(event) { event.target.addEventListener( 'keypress', @@ -102,81 +96,37 @@ if (!customElements.get('quick-add-bulk')) { }); } - updateCart(event) { - this.lastActiveInputId = event.target.getAttribute('data-index'); - this.quantity.classList.add('quantity__input-disabled'); + updateMultipleQty(items) { this.selectProgressBar().classList.remove('hidden'); + + const ids = Object.keys(items); const body = JSON.stringify({ - quantity: event.target.value, - id: event.target.getAttribute('data-index'), + updates: items, sections: this.getSectionsToRender().map((section) => section.section), sections_url: this.getSectionsUrl(), }); - fetch(`${routes.cart_change_url}`, { ...fetchConfig('javascript'), ...{ body } }) + fetch(`${routes.cart_update_url}`, { ...fetchConfig(), ...{ body } }) .then((response) => { return response.text(); }) .then((state) => { const parsedState = JSON.parse(state); - this.quantity.classList.remove('quantity__input-disabled'); - if (parsedState.description || parsedState.errors) { - event.target.setCustomValidity(parsedState.description); - event.target.reportValidity(); - this.resetQuantityInput(event.target.id); - this.selectProgressBar().classList.add('hidden'); - event.target.select(); - this.cleanErrorMessageOnType(event); - return; - } - - this.renderSections(parsedState); - + this.renderSections(parsedState, ids); publish(PUB_SUB_EVENTS.cartUpdate, { source: 'quick-add', cartData: parsedState }); }) - .catch((error) => { - console.log(error, 'error'); - }); - } - - addToCart(event) { - this.quantity.classList.add('quantity__input-disabled'); - this.selectProgressBar().classList.remove('hidden'); - this.lastActiveInputId = event.target.getAttribute('data-index'); - const body = JSON.stringify({ - items: [ - { - quantity: parseInt(event.target.value), - id: parseInt(this.dataset.id), - }, - ], - sections: this.getSectionsToRender().map((section) => section.section), - }); - - fetch(`${routes.cart_add_url}`, { ...fetchConfig('javascript'), ...{ body } }) - .then((response) => { - return response.text(); - }) - .then((state) => { - const parsedState = JSON.parse(state); - this.quantity.classList.remove('quantity__input-disabled'); - if (parsedState.description || parsedState.errors) { - event.target.setCustomValidity(parsedState.description); - event.target.reportValidity(); - this.resetQuantityInput(event.target.id); - this.selectProgressBar().classList.add('hidden'); - event.target.select(); - this.cleanErrorMessageOnType(event); - // Error handling - return; - } - - this.renderSections(parsedState); - - publish(PUB_SUB_EVENTS.cartUpdate, { source: 'quick-add', cartData: parsedState }); + .catch(() => { + // Commented out for now and will be fixed when BE issue is done https://github.com/Shopify/shopify/issues/440605 + // e.target.setCustomValidity(error); + // e.target.reportValidity(); + // this.resetQuantityInput(ids[index]); + // this.selectProgressBar().classList.add('hidden'); + // e.target.select(); + // this.cleanErrorMessageOnType(e); }) - .catch((error) => { - console.error(error); + .finally(() => { + this.selectProgressBar().classList.add('hidden'); + this.requestStarted = false; }); } @@ -200,19 +150,9 @@ if (!customElements.get('quick-add-bulk')) { ]; } - getSectionsUrl() { - if (window.pageNumber) { - return `${window.location.pathname}?page=${window.pageNumber}`; - } else { - return `${window.location.pathname}`; - } - } - - getSectionInnerHTML(html, selector) { - return new DOMParser().parseFromString(html, 'text/html').querySelector(selector).innerHTML; - } - - renderSections(parsedState) { + renderSections(parsedState, ids) { + const intersection = this.queue.filter((element) => ids.includes(element.id)); + if (intersection.length !== 0) return; this.getSectionsToRender().forEach((section) => { const sectionElement = document.getElementById(section.id); if ( diff --git a/assets/quick-add.css b/assets/quick-add.css index b9d889ad5a9..2fb9b2a9f49 100644 --- a/assets/quick-add.css +++ b/assets/quick-add.css @@ -355,6 +355,7 @@ quick-add-bulk .progress-bar-container { overflow: hidden; border-radius: var(--inputs-radius-outset); border: var(--inputs-border-width) solid transparent; + z-index: -1; } quick-add-bulk quantity-input { diff --git a/assets/quick-order-list.js b/assets/quick-order-list.js index 45c51cac6e2..433fb6972e8 100644 --- a/assets/quick-order-list.js +++ b/assets/quick-order-list.js @@ -137,15 +137,11 @@ if (!customElements.get('quick-order-list')) { onChange(event) { const inputValue = parseInt(event.target.value); - const cartQuantity = parseInt(event.target.dataset.cartQuantity); - const index = event.target.dataset.index; - - const quantity = inputValue - cartQuantity; this.cleanErrorMessageOnType(event); if (inputValue == 0) { - this.startQueue(index, inputValue); + this.startQueue(event.target.dataset.index, inputValue); } else { - this.validateQuantity(event, index, inputValue, cartQuantity, quantity); + this.validateQuantity(event); } } @@ -156,35 +152,6 @@ if (!customElements.get('quick-order-list')) { }); } - validateQuantity(event, index, inputValue, cartQuantity, quantity) { - if (inputValue < event.target.dataset.min) { - this.setValidity( - event, - index, - window.quickOrderListStrings.min_error.replace('[min]', event.target.dataset.min) - ); - } else if (inputValue > parseInt(event.target.max)) { - this.setValidity(event, index, window.quickOrderListStrings.max_error.replace('[max]', event.target.max)); - } else if (inputValue % parseInt(event.target.step) != 0) { - this.setValidity(event, index, window.quickOrderListStrings.step_error.replace('[step]', event.target.step)); - } else { - event.target.setCustomValidity(''); - event.target.reportValidity(); - if (cartQuantity > 0) { - this.startQueue(index, inputValue); - } else { - this.startQueue(index, quantity); - } - } - } - - setValidity(event, index, message) { - event.target.setCustomValidity(message); - event.target.reportValidity(); - this.resetQuantityInput(index); - event.target.select(); - } - validateInput(target) { if (target.max) { return ( @@ -261,47 +228,47 @@ if (!customElements.get('quick-order-list')) { } renderSections(parsedState, ids) { - if (ids) { - this.ids.push(ids) - } - const intersection = this.queue.filter(element => ids.includes(element.id)); - if (intersection.length === 0) { - this.getSectionsToRender().forEach((section) => { - const sectionElement = document.getElementById(section.id); - if ( - sectionElement && - sectionElement.parentElement && - sectionElement.parentElement.classList.contains('drawer') - ) { - parsedState.items.length > 0 - ? sectionElement.parentElement.classList.remove('is-empty') - : sectionElement.parentElement.classList.add('is-empty'); - setTimeout(() => { - document.querySelector('#CartDrawer-Overlay').addEventListener('click', this.cart.close.bind(this.cart)); - }); - } - const elementToReplace = - sectionElement && sectionElement.querySelector(section.selector) - ? sectionElement.querySelector(section.selector) - : sectionElement; - if (elementToReplace) { - if (section.selector === `#${this.quickOrderListId} .js-contents` && this.ids.length > 0) { - this.ids.flat().forEach((i) => { - elementToReplace.querySelector(`#Variant-${i}`).innerHTML = - this.getSectionInnerHTML(parsedState.sections[section.section], `#Variant-${i}`); - }); - } else { - elementToReplace.innerHTML = this.getSectionInnerHTML( - parsedState.sections[section.section], - section.selector - ); - } - } + this.ids.push(ids); + const intersection = this.queue.filter((element) => ids.includes(element.id)); + if (intersection.length !== 0) return; + + this.getSectionsToRender().forEach((section) => { + const sectionElement = document.getElementById(section.id); + if ( + sectionElement && + sectionElement.parentElement && + sectionElement.parentElement.classList.contains('drawer') + ) { + parsedState.items.length > 0 + ? sectionElement.parentElement.classList.remove('is-empty') + : sectionElement.parentElement.classList.add('is-empty'); + setTimeout(() => { + document.querySelector('#CartDrawer-Overlay').addEventListener('click', this.cart.close.bind(this.cart)); }); - this.defineInputsAndQuickOrderTable(); - this.addMultipleDebounce(); - this.ids = [] - } + } + const elementToReplace = + sectionElement && sectionElement.querySelector(section.selector) + ? sectionElement.querySelector(section.selector) + : sectionElement; + if (elementToReplace) { + if (section.selector === `#${this.quickOrderListId} .js-contents` && this.ids.length > 0) { + this.ids.flat().forEach((i) => { + elementToReplace.querySelector(`#Variant-${i}`).innerHTML = this.getSectionInnerHTML( + parsedState.sections[section.section], + `#Variant-${i}` + ); + }); + } else { + elementToReplace.innerHTML = this.getSectionInnerHTML( + parsedState.sections[section.section], + section.selector + ); + } + } + }); + this.defineInputsAndQuickOrderTable(); + this.addMultipleDebounce(); + this.ids = []; } getTableHead() { @@ -394,9 +361,11 @@ if (!customElements.get('quick-order-list')) { } } - updateMultipleQty(items, ids) { + updateMultipleQty(items) { this.querySelector('.variant-remove-total .loading__spinner')?.classList.remove('hidden'); + const ids = Object.keys(items); + const body = JSON.stringify({ updates: items, sections: this.getSectionsToRender().map((section) => section.section), @@ -413,7 +382,8 @@ if (!customElements.get('quick-order-list')) { .then((state) => { const parsedState = JSON.parse(state); this.renderSections(parsedState, ids); - }).catch(() => { + }) + .catch(() => { this.setErrorMessage(window.cartStrings.error); }) .finally(() => { @@ -422,19 +392,6 @@ if (!customElements.get('quick-order-list')) { }); } - getSectionsUrl() { - if (window.pageNumber) { - return `${window.location.pathname}?page=${window.pageNumber}`; - } else { - return `${window.location.pathname}`; - } - } - - resetQuantityInput(id, quantityElement) { - const input = quantityElement ?? document.getElementById(`Quantity-${id}`); - input.value = input.getAttribute('value'); - } - setErrorMessage(message = null) { this.errorMessageTemplate = this.errorMessageTemplate ?? @@ -513,10 +470,6 @@ if (!customElements.get('quick-order-list')) { }, 1000); } - getSectionInnerHTML(html, selector) { - return new DOMParser().parseFromString(html, 'text/html').querySelector(selector).innerHTML; - } - toggleLoading(id, enable) { const quickOrderListItems = this.querySelectorAll(`#Variant-${id} .loading__spinner`); const quickOrderListItem = this.querySelector(`#Variant-${id}`); diff --git a/layout/theme.liquid b/layout/theme.liquid index 963bb22944c..b4bd68d9adc 100644 --- a/layout/theme.liquid +++ b/layout/theme.liquid @@ -28,7 +28,6 @@ {% render 'meta-tags' %} - diff --git a/snippets/card-product.liquid b/snippets/card-product.liquid index a12e91e9136..080d897d125 100644 --- a/snippets/card-product.liquid +++ b/snippets/card-product.liquid @@ -389,7 +389,7 @@ data-min="{{ card_product.selected_or_first_available_variant.quantity_rule.min }}" id="quick-add-bulk-{{ card_product.selected_or_first_available_variant.id }}-{{ section.id }}" class="quick-add-bulk" - data-id="{{ card_product.selected_or_first_available_variant.id }}" + data-index="{{ card_product.selected_or_first_available_variant.id }}" > {% render 'quantity-input', variant: card_product.selected_or_first_available_variant, min: 0 %} @@ -416,7 +416,10 @@ {%- render 'loading-spinner' -%} - +