From dda40eb74550b35cbb0246d72c41e18a19eaac00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= Date: Sun, 24 Sep 2023 23:55:58 +0200 Subject: [PATCH] cart quantity action --- _dev/.eslintrc.js | 5 +- .../http/useHttpPayloadDefinition.js | 14 +- .../components/useCustomQuantityInput.js | 166 +++++++++++++++++- _dev/js/theme/core/cart/cartController.js | 24 +++ _dev/js/theme/core/cart/cartQuantity.js | 70 +------- .../cart/handler/cart/addToCartHandler.js | 2 +- .../cart/handler/cart/cartErrorsHandler.js | 0 .../handler/cart/deleteFromCartHandler.js | 2 +- .../handler/cart/quantityChangeHandler.js | 52 ++++++ .../handler/voucher/deleteVoucherHandler.js | 2 +- .../handler/voucher/submitVoucherHandler.js | 2 +- _dev/js/theme/core/cart/index.js | 3 + .../request/{ => cart}/addToCartRequest.js | 4 +- .../{ => cart}/deleteFromCartRequest.js | 4 +- .../request/cart/quantityChangeRequest.js | 109 ++++++++++++ .../{ => voucher}/addVoucherToCartRequest.js | 4 +- .../deleteVoucherFromCartRequest.js | 4 +- _dev/js/theme/frontAPI/apiAction.js | 2 - .../frontAPI/cart/updateCartQuantityAction.js | 44 ----- 19 files changed, 377 insertions(+), 136 deletions(-) create mode 100644 _dev/js/theme/core/cart/handler/cart/cartErrorsHandler.js create mode 100644 _dev/js/theme/core/cart/handler/cart/quantityChangeHandler.js rename _dev/js/theme/core/cart/request/{ => cart}/addToCartRequest.js (93%) rename _dev/js/theme/core/cart/request/{ => cart}/deleteFromCartRequest.js (93%) create mode 100644 _dev/js/theme/core/cart/request/cart/quantityChangeRequest.js rename _dev/js/theme/core/cart/request/{ => voucher}/addVoucherToCartRequest.js (91%) rename _dev/js/theme/core/cart/request/{ => voucher}/deleteVoucherFromCartRequest.js (91%) delete mode 100644 _dev/js/theme/frontAPI/cart/updateCartQuantityAction.js diff --git a/_dev/.eslintrc.js b/_dev/.eslintrc.js index 849ed84c..021e7f71 100644 --- a/_dev/.eslintrc.js +++ b/_dev/.eslintrc.js @@ -15,7 +15,10 @@ module.exports = { }, extends: ['airbnb-base'], rules: { - 'max-len': ['error', {code: 140}], + 'max-len': ['error', { + code: 140, + ignoreComments: true, + }], 'no-underscore-dangle': 'off', 'no-restricted-syntax': 'off', 'no-param-reassign': 'off' diff --git a/_dev/js/theme/components/http/useHttpPayloadDefinition.js b/_dev/js/theme/components/http/useHttpPayloadDefinition.js index b6828bec..4925b0ca 100644 --- a/_dev/js/theme/components/http/useHttpPayloadDefinition.js +++ b/_dev/js/theme/components/http/useHttpPayloadDefinition.js @@ -43,6 +43,8 @@ const useHttpPayloadDefinition = (payload, definition) => { payloadDefinition[fieldName] = setDefaultDefinitionForField(definitionForField); }); + const getValueType = (value) => typeof value; + const validate = (fieldName, value, fieldDefinition) => { const validateErrors = []; const { @@ -62,32 +64,32 @@ const useHttpPayloadDefinition = (payload, definition) => { switch (type) { case 'string': if (typeof value !== 'string') { - validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} string`); + validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} string, ${getValueType(value)} received`); } break; case 'float': if (typeof value !== 'number') { - validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} float`); + validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} float, ${getValueType(value)} received`); } break; case 'int': if (typeof value !== 'number') { - validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} int`); + validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} int, ${getValueType(value)} received`); } break; case 'boolean': if (typeof value !== 'boolean') { - validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} boolean`); + validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} boolean, ${getValueType(value)} received`); } break; case 'object': if (typeof value !== 'object') { - validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} object`); + validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} object, ${getValueType(value)} received`); } break; case 'array': if (!Array.isArray(value)) { - validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} array`); + validateErrors.push(`'${fieldName}' ${ERROR_MESSAGES.TYPE} array, ${getValueType(value)} received`); } break; default: diff --git a/_dev/js/theme/components/useCustomQuantityInput.js b/_dev/js/theme/components/useCustomQuantityInput.js index 56ce971b..ede1900b 100644 --- a/_dev/js/theme/components/useCustomQuantityInput.js +++ b/_dev/js/theme/components/useCustomQuantityInput.js @@ -1,3 +1,17 @@ +/** + * Custom quantity input + * @module useCustomQuantityInput + * @param {HTMLElement} spinnerElement - spinner element to initialize (required) + * @param {object} configuration - configuration object (optional) + * @param {string} configuration.spinnerInitializedClass - class to add when spinner is initialized (default: js-custom-qty-spinner-initialized) + * @param {string} configuration.spinnerInputClass - class of the input element (default: js-custom-qty-spinner-input) + * @param {string} configuration.spinnerBtnClassUp - class of the up button (default: js-custom-qty-btn-up) + * @param {string} configuration.spinnerBtnClassDown - class of the down button (default: js-custom-qty-btn-down) + * @param {int} configuration.defaultMinQty - default minimum quantity (default: 1) + * @param {int} configuration.defaultMaxQty - default maximum quantity (default: 1000000) + * @param {int} configuration.timeout - timeout in ms to wait before dispatching change event (default: 500) + * @param {function} configuration.onQuantityChange - callback function to call when quantity changes + */ const useCustomQuantityInput = (spinnerElement, { spinnerInitializedClass = 'js-custom-qty-spinner-initialized', spinnerInputClass = 'js-custom-qty-spinner-input', @@ -8,13 +22,52 @@ const useCustomQuantityInput = (spinnerElement, { timeout = 500, onQuantityChange = () => {}, }) => { + /** + * Timeout id + * @private + * @type {int|null} + */ let timeoutId = null; + /** + * Start value + * @private + * @type {int|null} + */ let startValue = null; + /** + * Minimum quantity + * @private + * @type {int|null} + */ let minQty = null; + + /** + * Maximum quantity + * @private + * @type {int|null} + */ let maxQty = null; + + /** + * Current quantity + * @private + * @type {int|null} + */ let currentQty = null; + + /** + * DOM elements + * @private + * @type {Object|null} + */ let DOMElements = null; + /** + * Set DOM elements + * @method setDOMElements + * @private + * @returns {{input: HTMLElement | undefined, btnUp: HTMLElement | undefined, btnDown: HTMLElement | undefined}} + */ const setDOMElements = () => { const elements = { input: spinnerElement?.querySelector(`.${spinnerInputClass}`), @@ -27,12 +80,30 @@ const useCustomQuantityInput = (spinnerElement, { return elements; }; + /** + * Get DOM elements + * @method getDOMElements + * @public + * @returns {{input: (HTMLElement|undefined), btnUp: (HTMLElement|undefined), btnDown: (HTMLElement|undefined)}} + */ const getDOMElements = () => (DOMElements || setDOMElements()); + /** + * Reset DOM elements + * @method resetDomElements + * @private + * @returns {void} + */ const resetDomElements = () => { DOMElements = null; }; + /** + * Set initial value + * @method setInitialValue + * @private + * @returns {void} + */ const setInitialValue = () => { const { input } = getDOMElements(); startValue = input.value ? parseInt(input.value, 10) : defaultMinQty; @@ -41,8 +112,20 @@ const useCustomQuantityInput = (spinnerElement, { maxQty = input.getAttribute('max') ? parseInt(input.getAttribute('max'), 10) : defaultMaxQty; }; + /** + * Should dispatch change event + * @method shouldDispatchChange + * @private + * @returns {boolean} + */ const shouldDispatchChange = () => currentQty !== startValue; + /** + * Get operation type + * @method getOperationType + * @private + * @returns {string} increase|decrease + */ const getOperationType = () => { if (currentQty > startValue) { return 'increase'; @@ -51,8 +134,20 @@ const useCustomQuantityInput = (spinnerElement, { return 'decrease'; }; + /** + * Get quantity difference + * @method getQtyDifference + * @private + * @returns {int} + */ const getQtyDifference = () => Math.abs(currentQty - startValue); + /** + * Dispatch change event + * @method dispatchChange + * @private + * @returns {void} + */ const dispatchChange = () => { clearTimeout(timeoutId); @@ -72,6 +167,13 @@ const useCustomQuantityInput = (spinnerElement, { }, timeout); }; + /** + * Set quantity + * @param {int} qty - quantity to set + * @method setQty + * @private + * @returns {void} + */ const setQty = (qty) => { const { input } = getDOMElements(); @@ -81,8 +183,15 @@ const useCustomQuantityInput = (spinnerElement, { dispatchChange(); }; - const handleClickUp = (e) => { - e.preventDefault(); + /** + * Handle click up + * @param {Event} event - event object + * @method handleClickUp + * @private + * @returns {void} + */ + const handleClickUp = (event) => { + event.preventDefault(); let newQty = parseInt(currentQty, 10) + 1; @@ -93,8 +202,15 @@ const useCustomQuantityInput = (spinnerElement, { setQty(newQty); }; - const handleClickDown = (e) => { - e.preventDefault(); + /** + * Handle click down + * @param {Event} event - event object + * @method handleClickDown + * @private + * @returns {void} + */ + const handleClickDown = (event) => { + event.preventDefault(); let newQty = parseInt(currentQty, 10) - 1; @@ -105,6 +221,12 @@ const useCustomQuantityInput = (spinnerElement, { setQty(newQty); }; + /** + * Handle input change + * @method handleInputChange + * @private + * @returns {void} + */ const handleInputChange = () => { const { input } = getDOMElements(); let newQty = parseInt(input.value, 10); @@ -120,14 +242,32 @@ const useCustomQuantityInput = (spinnerElement, { setQty(newQty); }; + /** + * Add initialized class + * @method setInitializedClass + * @private + * @returns {void} + */ const setInitializedClass = () => { spinnerElement?.classList.add(spinnerInitializedClass); }; + /** + * Remove initialized class + * @method removeInitializedClass + * @private + * @returns {void} + */ const removeInitializedClass = () => { spinnerElement?.classList.remove(spinnerInitializedClass); }; + /** + * Detach events from DOM elements + * @method detachEvents + * @private + * @returns {void} + */ const detachEvents = () => { const { input, btnUp, btnDown } = getDOMElements(); @@ -139,6 +279,12 @@ const useCustomQuantityInput = (spinnerElement, { input?.removeEventListener('blur', handleInputChange); }; + /** + * Attach events to DOM elements + * @method attachEvents + * @private + * @returns {void} + */ const attachEvents = () => { const { input, btnUp, btnDown } = getDOMElements(); @@ -150,11 +296,23 @@ const useCustomQuantityInput = (spinnerElement, { input?.addEventListener('blur', handleInputChange); }; + /** + * Destroy spinner instance and detach events + * @method destroy + * @static + * @returns {void} + */ const destroy = () => { detachEvents(); resetDomElements(); }; + /** + * Initialize spinner instance and attach events + * @method init + * @static + * @returns {void} + */ const init = () => { destroy(); setInitialValue(); diff --git a/_dev/js/theme/core/cart/cartController.js b/_dev/js/theme/core/cart/cartController.js index 0b778983..08bde422 100644 --- a/_dev/js/theme/core/cart/cartController.js +++ b/_dev/js/theme/core/cart/cartController.js @@ -5,6 +5,8 @@ import codeLinkSubmitHandler from './handler/voucher/codeLinkSubmitHandler'; import deleteVoucherHandler from './handler/voucher/deleteVoucherHandler'; import addToCartHandler from './handler/cart/addToCartHandler'; import deleteFromCartHandler from './handler/cart/deleteFromCartHandler'; +import quantityChangeHandler from './handler/cart/quantityChangeHandler'; +import useCustomQuantityInput from '../../components/useCustomQuantityInput'; const { on } = useEvent(); @@ -14,6 +16,22 @@ const { on } = useEvent(); * @returns {function} return.init initialize cart controller */ const cartController = () => { + const attachSpinnerEvents = () => { + const spinners = document.querySelectorAll('.js-custom-cart-qty-spinner'); + + spinners.forEach((spinner) => { + const { init, getDOMElements } = useCustomQuantityInput(spinner, { + onQuantityChange: ({ operation, qtyDifference }) => { + const { input } = getDOMElements(); + + quantityChangeHandler(operation, qtyDifference, input); + }, + }); + + init(); + }); + }; + const init = () => { const { discountCode, @@ -24,6 +42,12 @@ const cartController = () => { on(document, 'click', '.js-voucher-delete', deleteVoucherHandler); on(document, 'click', '[data-button-action="add-to-cart"]', addToCartHandler); on(document, 'click', '.js-remove-from-cart', deleteFromCartHandler); + + attachSpinnerEvents(); + + prestashop.on('updatedCart', () => { + attachSpinnerEvents(); + }); }; return { diff --git a/_dev/js/theme/core/cart/cartQuantity.js b/_dev/js/theme/core/cart/cartQuantity.js index d42a64cb..e47c490d 100644 --- a/_dev/js/theme/core/cart/cartQuantity.js +++ b/_dev/js/theme/core/cart/cartQuantity.js @@ -1,60 +1,12 @@ -import useCustomQuantityInput from '@js/theme/components/useCustomQuantityInput'; import useAlertToast from '@js/theme/components/useAlertToast'; import prestashop from 'prestashop'; -prestashop.cart = prestashop.cart || {}; - let errorMsg = ''; let isUpdateOperation = false; let hasError = false; const { danger } = useAlertToast(); -const checkUpdateOperation = (resp) => { - const { hasError: hasErrorOccurred, errors: errorData } = resp; - hasError = hasErrorOccurred ?? false; - errorMsg = errorData ?? ''; - - isUpdateOperation = true; -}; - -const handleQuantityChange = async ({ operation, qtyDifference, input }) => { - const { dataset } = input; - const { productAttributeId, productId, customizationId } = dataset; - - const simpleOperation = operation === 'decrease' ? 'down' : 'up'; - - document.querySelector('body').classList.add('cart-loading'); - - try { - const resp = await prestashop.frontAPI.updateCartQuantity( - simpleOperation, - productId, - productAttributeId, - qtyDifference, - customizationId, - ); - - checkUpdateOperation(resp); - - if (!resp.hasError) { - prestashop.emit('updateCart', { - reason: dataset || resp, - resp, - }); - } else { - prestashop.emit('handleError', { - eventType: 'updateProductQuantityInCart', - resp, - }); - } - } catch (error) { - danger(error.message); - } - - document.querySelector('body').classList.remove('cart-loading'); -}; - const switchErrorStat = () => { const checkoutButtons = document.querySelectorAll(prestashop.selectors.checkout.btn); @@ -84,32 +36,16 @@ const switchErrorStat = () => { } }; -const createSpinner = () => { - const spinners = document.querySelectorAll('.js-custom-cart-qty-spinner'); - - spinners.forEach((spinner) => { - const { init, getDOMElements } = useCustomQuantityInput(spinner, { - onQuantityChange: ({ - operation, qtyDifference, - }) => { - const { input } = getDOMElements(); - - handleQuantityChange({ operation, qtyDifference, input }); - }, - }); - - init(); - }); - +const handleErrors = () => { switchErrorStat(); }; const cartQuantity = () => { prestashop.on('updatedCart', () => { - createSpinner(); + handleErrors(); }); - createSpinner(); + handleErrors(); }; export default cartQuantity; diff --git a/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js b/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js index 954515b8..fb81b440 100644 --- a/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js +++ b/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js @@ -1,5 +1,5 @@ import useAlertToast from '../../../../components/useAlertToast'; -import addToCartRequest from '../../request/addToCartRequest'; +import addToCartRequest from '../../request/cart/addToCartRequest'; import sprintf from '../../../../utils/sprintf'; const { danger } = useAlertToast(); diff --git a/_dev/js/theme/core/cart/handler/cart/cartErrorsHandler.js b/_dev/js/theme/core/cart/handler/cart/cartErrorsHandler.js new file mode 100644 index 00000000..e69de29b diff --git a/_dev/js/theme/core/cart/handler/cart/deleteFromCartHandler.js b/_dev/js/theme/core/cart/handler/cart/deleteFromCartHandler.js index 017568b1..eb04a1b3 100644 --- a/_dev/js/theme/core/cart/handler/cart/deleteFromCartHandler.js +++ b/_dev/js/theme/core/cart/handler/cart/deleteFromCartHandler.js @@ -1,5 +1,5 @@ import useAlertToast from '../../../../components/useAlertToast'; -import deleteFromCartRequest from '../../request/deleteFromCartRequest'; +import deleteFromCartRequest from '../../request/cart/deleteFromCartRequest'; const { danger } = useAlertToast(); diff --git a/_dev/js/theme/core/cart/handler/cart/quantityChangeHandler.js b/_dev/js/theme/core/cart/handler/cart/quantityChangeHandler.js new file mode 100644 index 00000000..7e493216 --- /dev/null +++ b/_dev/js/theme/core/cart/handler/cart/quantityChangeHandler.js @@ -0,0 +1,52 @@ +import prestashop from 'prestashop'; +import quantityChangeRequest from '../../request/cart/quantityChangeRequest'; +import useAlertToast from '../../../../components/useAlertToast'; + +const { danger } = useAlertToast(); + +/** + * @param {string} operation - increase|decrease + * @param {int} qtyDifference - quantity difference + * @param {HTMLElement} input - input element + * @returns {Promise} + */ +const quantityChangeHandler = async (operation, qtyDifference, input) => { + const { dataset } = input; + const { productAttributeId, productId, customizationId } = dataset; + + const simpleOperation = operation === 'decrease' ? 'down' : 'up'; + + document.querySelector('body').classList.add('cart-loading'); + + const payload = { + qty: qtyDifference, + id_product: Number.parseInt(productId, 10), + id_product_attribute: Number.parseInt(productAttributeId, 10), + id_customization: Number.parseInt(customizationId, 10), + op: simpleOperation, + }; + + const { getRequest } = quantityChangeRequest(payload); + + try { + const resp = await getRequest(); + + if (!resp.hasError) { + prestashop.emit('updateCart', { + reason: dataset || resp, + resp, + }); + } else { + prestashop.emit('handleError', { + eventType: 'updateProductQuantityInCart', + resp, + }); + } + } catch (error) { + danger(error.message); + } + + document.querySelector('body').classList.remove('cart-loading'); +}; + +export default quantityChangeHandler; diff --git a/_dev/js/theme/core/cart/handler/voucher/deleteVoucherHandler.js b/_dev/js/theme/core/cart/handler/voucher/deleteVoucherHandler.js index 7ecaeef7..d245b31c 100644 --- a/_dev/js/theme/core/cart/handler/voucher/deleteVoucherHandler.js +++ b/_dev/js/theme/core/cart/handler/voucher/deleteVoucherHandler.js @@ -1,5 +1,5 @@ import useAlertToast from '../../../../components/useAlertToast'; -import deleteVoucherFromCartRequest from '../../request/deleteVoucherFromCartRequest'; +import deleteVoucherFromCartRequest from '../../request/voucher/deleteVoucherFromCartRequest'; const { danger } = useAlertToast(); diff --git a/_dev/js/theme/core/cart/handler/voucher/submitVoucherHandler.js b/_dev/js/theme/core/cart/handler/voucher/submitVoucherHandler.js index 512fa51a..72e8bbfa 100644 --- a/_dev/js/theme/core/cart/handler/voucher/submitVoucherHandler.js +++ b/_dev/js/theme/core/cart/handler/voucher/submitVoucherHandler.js @@ -1,4 +1,4 @@ -import addVoucherToCartRequest from '../../request/addVoucherToCartRequest'; +import addVoucherToCartRequest from '../../request/voucher/addVoucherToCartRequest'; import parseToHtml from '../../../../utils/parseToHtml'; import useAlertToast from '../../../../components/useAlertToast'; diff --git a/_dev/js/theme/core/cart/index.js b/_dev/js/theme/core/cart/index.js index 648a01c6..d0a1fe36 100644 --- a/_dev/js/theme/core/cart/index.js +++ b/_dev/js/theme/core/cart/index.js @@ -1,8 +1,11 @@ import updateCart from '@js/theme/core/cart/updateCart'; import cartQuantity from '@js/theme/core/cart/cartQuantity'; import DOMReady from '@js/theme/utils/DOMReady'; +import prestashop from 'prestashop'; import cartController from './cartController'; +prestashop.cart = prestashop.cart || {}; + const { init } = cartController(); DOMReady(() => { diff --git a/_dev/js/theme/core/cart/request/addToCartRequest.js b/_dev/js/theme/core/cart/request/cart/addToCartRequest.js similarity index 93% rename from _dev/js/theme/core/cart/request/addToCartRequest.js rename to _dev/js/theme/core/cart/request/cart/addToCartRequest.js index 8086c485..b47df9ea 100644 --- a/_dev/js/theme/core/cart/request/addToCartRequest.js +++ b/_dev/js/theme/core/cart/request/cart/addToCartRequest.js @@ -1,6 +1,6 @@ import prestashop from 'prestashop'; -import useDefaultHttpRequest from '../../../components/http/useDefaultHttpRequest'; -import useHttpPayloadDefinition from '../../../components/http/useHttpPayloadDefinition'; +import useDefaultHttpRequest from '../../../../components/http/useDefaultHttpRequest'; +import useHttpPayloadDefinition from '../../../../components/http/useHttpPayloadDefinition'; /** * @typedef ServerResponse diff --git a/_dev/js/theme/core/cart/request/deleteFromCartRequest.js b/_dev/js/theme/core/cart/request/cart/deleteFromCartRequest.js similarity index 93% rename from _dev/js/theme/core/cart/request/deleteFromCartRequest.js rename to _dev/js/theme/core/cart/request/cart/deleteFromCartRequest.js index 0a786e28..849441ac 100644 --- a/_dev/js/theme/core/cart/request/deleteFromCartRequest.js +++ b/_dev/js/theme/core/cart/request/cart/deleteFromCartRequest.js @@ -1,6 +1,6 @@ import prestashop from 'prestashop'; -import useDefaultHttpRequest from '../../../components/http/useDefaultHttpRequest'; -import useHttpPayloadDefinition from '../../../components/http/useHttpPayloadDefinition'; +import useDefaultHttpRequest from '../../../../components/http/useDefaultHttpRequest'; +import useHttpPayloadDefinition from '../../../../components/http/useHttpPayloadDefinition'; /** * @typedef ServerResponse diff --git a/_dev/js/theme/core/cart/request/cart/quantityChangeRequest.js b/_dev/js/theme/core/cart/request/cart/quantityChangeRequest.js new file mode 100644 index 00000000..b783bdfd --- /dev/null +++ b/_dev/js/theme/core/cart/request/cart/quantityChangeRequest.js @@ -0,0 +1,109 @@ +import prestashop from 'prestashop'; +import useDefaultHttpRequest from '../../../../components/http/useDefaultHttpRequest'; +import useHttpPayloadDefinition from '../../../../components/http/useHttpPayloadDefinition'; + +/** + * @typedef ServerResponse + * @type {object} + * @property {string|string[]} errors - the errors returned by the server + * @property {int} id_product - product id + * @property {int} id_product_attribute - product attribute id + * @property {int} id_customization - product customization id + * @property {int} quantity - product quantity + * @property {boolean} success - success flag + * @property {object} cart - cart front object + */ + +/** + * Add voucher to cart request + * @param payload {Object} - payload object to send + * @param payload.id_product {int} - product id - Required + * @param payload.qty {int} - product quantity - Required + * @param payload.id_product_attribute {int} - product id attribute - optional pass 0 if not set + * @param payload.id_customization {int} - customization id - optional pass 0 if not set + * @param payload.add {int} - optional + * @param payload.action {string} - optional + * @param payload.token {string} - optional + * @param payload.ajax {int} - optional + * @example + * const payload = { + * id_product: 1, // Required + * qty: 1, // Required + * op: 'up', // up|down Required + * id_product_attribute: 2, // optional + * id_customization: 3, // optional + * }; + * + * const { getRequest } = quantityChangeRequest(payload); + * + * try { + * const resp = await getRequest(); + * } catch (error) { + * console.error(error); + * } + * @returns {{getRequest: (function(): Promise)}} + */ +const quantityChangeRequest = (payload) => { + const payloadToSend = { + update: 1, + action: 'update', + ajax: 1, + token: prestashop.static_token, + ...payload, + }; + + const payloadDefinition = { + id_product: { + type: 'int', + required: true, + }, + qty: { + type: 'int', + required: true, + }, + id_product_attribute: { + type: 'int', + required: false, + }, + id_customization: { + type: 'int', + required: false, + }, + update: { + type: 'int', + required: true, + }, + action: { + type: 'string', + required: true, + }, + ajax: { + type: 'int', + required: true, + }, + op: { + type: 'string', + required: true, + }, + token: { + type: 'string', + required: true, + }, + }; + + const { validatePayload } = useHttpPayloadDefinition(payloadToSend, payloadDefinition); + + const validationErrors = validatePayload(); + + if (validationErrors.length) { + throw Error(validationErrors.join(',\n')); + } + + const getRequest = () => useDefaultHttpRequest(prestashop.urls.pages.cart, payloadToSend); + + return { + getRequest, + }; +}; + +export default quantityChangeRequest; diff --git a/_dev/js/theme/core/cart/request/addVoucherToCartRequest.js b/_dev/js/theme/core/cart/request/voucher/addVoucherToCartRequest.js similarity index 91% rename from _dev/js/theme/core/cart/request/addVoucherToCartRequest.js rename to _dev/js/theme/core/cart/request/voucher/addVoucherToCartRequest.js index 0fccea53..8836d141 100644 --- a/_dev/js/theme/core/cart/request/addVoucherToCartRequest.js +++ b/_dev/js/theme/core/cart/request/voucher/addVoucherToCartRequest.js @@ -1,6 +1,6 @@ import prestashop from 'prestashop'; -import useDefaultHttpRequest from '../../../components/http/useDefaultHttpRequest'; -import useHttpPayloadDefinition from '../../../components/http/useHttpPayloadDefinition'; +import useDefaultHttpRequest from '../../../../components/http/useDefaultHttpRequest'; +import useHttpPayloadDefinition from '../../../../components/http/useHttpPayloadDefinition'; /** * @typedef ServerResponse diff --git a/_dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js b/_dev/js/theme/core/cart/request/voucher/deleteVoucherFromCartRequest.js similarity index 91% rename from _dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js rename to _dev/js/theme/core/cart/request/voucher/deleteVoucherFromCartRequest.js index c725b93d..7512b11c 100644 --- a/_dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js +++ b/_dev/js/theme/core/cart/request/voucher/deleteVoucherFromCartRequest.js @@ -1,6 +1,6 @@ import prestashop from 'prestashop'; -import useDefaultHttpRequest from '../../../components/http/useDefaultHttpRequest'; -import useHttpPayloadDefinition from '../../../components/http/useHttpPayloadDefinition'; +import useDefaultHttpRequest from '../../../../components/http/useDefaultHttpRequest'; +import useHttpPayloadDefinition from '../../../../components/http/useHttpPayloadDefinition'; /** * @typedef ServerResponse diff --git a/_dev/js/theme/frontAPI/apiAction.js b/_dev/js/theme/frontAPI/apiAction.js index c54e0da4..b2ded63c 100644 --- a/_dev/js/theme/frontAPI/apiAction.js +++ b/_dev/js/theme/frontAPI/apiAction.js @@ -1,5 +1,4 @@ import refreshCartPageAction from '@js/theme/frontAPI/cart/refreshCartPageAction'; -import updateCartQuantityAction from '@js/theme/frontAPI/cart/updateCartQuantityAction'; import updateProductAction from '@js/theme/frontAPI/product/updateProductAction'; import updateListingFacetsAction from '@js/theme/frontAPI/listing/updateListingFacetsAction'; import updateAddressAction from '@js/theme/frontAPI/address/updateAddressAction'; @@ -15,7 +14,6 @@ prestashop.addAction = (actionName, actionFunction) => { }; prestashop.addAction('refreshCartPage', refreshCartPageAction); -prestashop.addAction('updateCartQuantity', updateCartQuantityAction); prestashop.addAction('updateProduct', updateProductAction); prestashop.addAction('updateListingFacets', updateListingFacetsAction); prestashop.addAction('updateAddress', updateAddressAction); diff --git a/_dev/js/theme/frontAPI/cart/updateCartQuantityAction.js b/_dev/js/theme/frontAPI/cart/updateCartQuantityAction.js deleted file mode 100644 index b194e9fc..00000000 --- a/_dev/js/theme/frontAPI/cart/updateCartQuantityAction.js +++ /dev/null @@ -1,44 +0,0 @@ -import useHttpRequest from '@js/theme/components/http/useHttpRequest'; - -const updateCartQuantityAction = async ( - operation, - idProduct, - idProductAttribute, - quantity, - idCustomization = 0, -) => new Promise((resolve, reject) => { - const { request } = useHttpRequest(prestashop.urls.pages.cart); - - const allowedOperations = ['up', 'down']; - - if (!allowedOperations.includes(operation)) { - reject(Error('Invalid operation')); - } - - const payload = { - update: 1, - id_product: parseInt(idProduct, 10), - id_product_attribute: parseInt(idProductAttribute, 10), - op: operation, - action: 'update', - token: prestashop.static_token, - qty: parseInt(quantity, 10), - ajax: 1, - }; - - if (idCustomization > 0) { - payload.id_customization = parseInt(idCustomization, 10); - } - - request - .query(payload) - .post() - .json((resp) => { - resolve(resp); - }) - .catch(() => { - reject(Error(prestashop.t.alert.genericHttpError)); - }); -}); - -export default updateCartQuantityAction;