diff --git a/_dev/js/theme/core/cart/cartAddProduct.js b/_dev/js/theme/core/cart/cartAddProduct.js deleted file mode 100644 index 7bbca68e..00000000 --- a/_dev/js/theme/core/cart/cartAddProduct.js +++ /dev/null @@ -1,78 +0,0 @@ -import useAlertToast from '@js/theme/components/useAlertToast'; -import sprintf from '@js/theme/utils/sprintf'; -import useEvent from '@js/theme/components/event/useEvent'; - -const { on } = useEvent(); -const { danger } = useAlertToast(); - -const eventHandler = async (event) => { - event.preventDefault(); - - const form = event.currentTarget?.form; - const addToCartButton = event.currentTarget; - - addToCartButton.setAttribute('disabled', true); - - const isQuantityInputValid = (input) => { - let validInput = true; - - const minimalValue = parseInt((input?.getAttribute('min') || 0), 10); - - if (minimalValue && input.value < minimalValue) { - validInput = false; - } - - return validInput; - }; - - const idProduct = form.querySelector('[name=id_product]').value; - const quantityInput = form.querySelector('[name=qty]'); - const quantity = quantityInput?.value || 0; - const idProductAttribute = form.querySelector('[name=id_product_attribute]')?.value || 0; - const idCustomization = form.querySelector('[name=id_customization]')?.value || 0; - - const onInvalidQuantity = (input) => { - danger(sprintf(prestashop.t.alert.minimalQuantity, input.getAttribute('min'))); - }; - - if (quantityInput && !isQuantityInputValid(quantityInput)) { - onInvalidQuantity(quantityInput); - addToCartButton.removeAttribute('disabled'); - - return; - } - - try { - const resp = await prestashop.frontAPI.addToCart(idProduct, quantity, idProductAttribute, idCustomization); - - if (!resp.hasError) { - prestashop.emit('updateCart', { - reason: { - idProduct: resp.id_product, - idProductAttribute: resp.id_product_attribute, - idCustomization: resp.id_customization, - linkAction: 'add-to-cart', - cart: resp.cart, - }, - resp, - }); - } else { - prestashop.emit('handleError', { - eventType: 'addProductToCart', - resp, - }); - } - } catch (error) { - danger(error.message); - } - - setTimeout(() => { - addToCartButton.removeAttribute('disabled'); - }, 1000); -}; - -const cartAddProduct = () => { - on(document, 'click', '[data-button-action="add-to-cart"]', eventHandler); -}; - -export default cartAddProduct; diff --git a/_dev/js/theme/core/cart/cartController.js b/_dev/js/theme/core/cart/cartController.js index b61588ef..ba333818 100644 --- a/_dev/js/theme/core/cart/cartController.js +++ b/_dev/js/theme/core/cart/cartController.js @@ -3,6 +3,7 @@ import useEvent from '../../components/event/useEvent'; import submitVoucherHandler from './handler/voucher/submitVoucherHandler'; import codeLinkSubmitHandler from './handler/voucher/codeLinkSubmitHandler'; import deleteVoucherHandler from './handler/voucher/deleteVoucherHandler'; +import addToCartHandler from "./handler/cart/addToCartHandler"; const { on } = useEvent(); @@ -20,6 +21,7 @@ const cartController = () => { on(document, 'submit', '.js-voucher-form', submitVoucherHandler); on(document, 'click', discountCode, codeLinkSubmitHandler); on(document, 'click', '.js-voucher-delete', deleteVoucherHandler); + on(document, 'click', '[data-button-action="add-to-cart"]', addToCartHandler); }; return { diff --git a/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js b/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js new file mode 100644 index 00000000..0c492421 --- /dev/null +++ b/_dev/js/theme/core/cart/handler/cart/addToCartHandler.js @@ -0,0 +1,86 @@ +import useAlertToast from "../../../../components/useAlertToast"; +import addToCartRequest from "../../request/addToCartRequest"; + +const { danger } = useAlertToast(); + +/** + * Handle add to cart event on form submit + * @param event {object} - submit event + * @returns {Promise} + */ +const addToCartHandler = async (event) => { + event.preventDefault(); + + const form = event.currentTarget?.form; + const addToCartButton = event.currentTarget; + + addToCartButton.setAttribute('disabled', true); + + const isQuantityInputValid = (input) => { + let validInput = true; + + const minimalValue = parseInt((input?.getAttribute('min') || 0), 10); + + if (minimalValue && input.value < minimalValue) { + validInput = false; + } + + return validInput; + }; + + const id_product = form.querySelector('[name=id_product]').value; + const quantityInput = form.querySelector('[name=qty]'); + const qty = quantityInput?.value || 0; + const id_product_attribute = form.querySelector('[name=id_product_attribute]')?.value || 0; + const id_customization = form.querySelector('[name=id_customization]')?.value || 0; + + const onInvalidQuantity = (input) => { + danger(sprintf(prestashop.t.alert.minimalQuantity, input.getAttribute('min'))); + }; + + if (quantityInput && !isQuantityInputValid(quantityInput)) { + onInvalidQuantity(quantityInput); + addToCartButton.removeAttribute('disabled'); + + return; + } + + const payload = { + id_product, + qty, + id_product_attribute, + id_customization, + }; + + const { getRequest } = addToCartRequest(payload); + + try { + const resp = await getRequest(); + + if (!resp.hasError) { + prestashop.emit('updateCart', { + reason: { + idProduct: resp.id_product, + idProductAttribute: resp.id_product_attribute, + idCustomization: resp.id_customization, + linkAction: 'add-to-cart', + cart: resp.cart, + }, + resp, + }); + } else { + prestashop.emit('handleError', { + eventType: 'addProductToCart', + resp, + }); + } + } catch (error) { + danger(error.message); + } + + setTimeout(() => { + addToCartButton.removeAttribute('disabled'); + }, 1000); +} + +export default addToCartHandler; diff --git a/_dev/js/theme/core/cart/index.js b/_dev/js/theme/core/cart/index.js index 679ca292..8c26a347 100644 --- a/_dev/js/theme/core/cart/index.js +++ b/_dev/js/theme/core/cart/index.js @@ -1,5 +1,4 @@ import updateCart from '@js/theme/core/cart/updateCart'; -import cartAddProduct from '@js/theme/core/cart/cartAddProduct'; import cartQuantity from '@js/theme/core/cart/cartQuantity'; import cartDelete from '@js/theme/core/cart/cartDelete'; import DOMReady from '@js/theme/utils/DOMReady'; @@ -13,7 +12,3 @@ DOMReady(() => { cartDelete(); init(); }); - -$(() => { - cartAddProduct(); -}); diff --git a/_dev/js/theme/core/cart/request/addToCartRequest.js b/_dev/js/theme/core/cart/request/addToCartRequest.js new file mode 100644 index 00000000..a9863257 --- /dev/null +++ b/_dev/js/theme/core/cart/request/addToCartRequest.js @@ -0,0 +1,72 @@ +import prestashop from "prestashop"; +import useHttpRequest from "../../../components/http/useHttpRequest"; + +/** + * @typedef ServerResponse + * @type {object} + * @property {string|string[]} errors - the errors returned by the server + * @property {number} id_product - product id + * @property {number} id_product_attribute - product attribute id + * @property {number} id_customization - product customization id + * @property {number} 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 {number} - product id - Required + * @param payload.qty {number} - product quantity - Required + * @param payload.id_product_attribute {number} - product id attribute - optional pass 0 if not set + * @param payload.id_customization {number} - customization id - optional pass 0 if not set + * @param payload.add {number} - optional + * @param payload.action {string} - optional + * @param payload.token {string} - optional + * @param payload.ajax {number} - optional + * @example + * const payload = { + * id_product: 1, // Required + * qty: 1, // Required + * id_product_attribute: 2, // optional + * id_customization: 3, // optional + * }; + * + * const { getRequest } = addToCartRequest(payload); + * + * try { + * const resp = await getRequest(); + * } catch (error) { + * console.error(error); + * } + * @returns {{getRequest: (function(): Promise)}} + */ +const addToCartRequest = (payload) => { + const { request } = useHttpRequest(prestashop.urls.pages.cart); + + const payloadToSend = { + add: 1, + action: 'update', + ajax: 1, + token: prestashop.static_token, + ...payload, + }; + + const getRequest = () => new Promise((resolve, reject) => { + request + .query(payloadToSend) + .post() + .json((resp) => { + resolve(resp); + }) + .catch(() => { + reject(Error(prestashop.t.alert.genericHttpError)); + }); + }); + + return { + getRequest, + }; +}; + +export default addToCartRequest; diff --git a/_dev/js/theme/core/cart/request/addVoucherToCartRequest.js b/_dev/js/theme/core/cart/request/addVoucherToCartRequest.js index 9288d154..fb77405e 100644 --- a/_dev/js/theme/core/cart/request/addVoucherToCartRequest.js +++ b/_dev/js/theme/core/cart/request/addVoucherToCartRequest.js @@ -9,7 +9,7 @@ import useHttpRequest from '../../../components/http/useHttpRequest'; * @property {number} id_product - always 0 * @property {number} id_product_attribute - always 0 * @property {number} quantity - always 0 - * @property {boolean} success - always 0 + * @property {boolean} success - success flag * @property {object} cart - cart front object */ diff --git a/_dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js b/_dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js index 0fa1f56f..a280f934 100644 --- a/_dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js +++ b/_dev/js/theme/core/cart/request/deleteVoucherFromCartRequest.js @@ -9,7 +9,7 @@ import useHttpRequest from '../../../components/http/useHttpRequest'; * @property {number} id_product - always 0 * @property {number} id_product_attribute - always 0 * @property {number} quantity - always 0 - * @property {boolean} success - always 0 + * @property {boolean} success - success flag * @property {object} cart - cart front object */ diff --git a/_dev/js/theme/frontAPI/apiAction.js b/_dev/js/theme/frontAPI/apiAction.js index 23465266..92e080b0 100644 --- a/_dev/js/theme/frontAPI/apiAction.js +++ b/_dev/js/theme/frontAPI/apiAction.js @@ -1,4 +1,3 @@ -import addToCartAction from '@js/theme/frontAPI/cart/addToCartAction'; import refreshCartPageAction from '@js/theme/frontAPI/cart/refreshCartPageAction'; import updateCartQuantityAction from '@js/theme/frontAPI/cart/updateCartQuantityAction'; import deleteFromCartAction from '@js/theme/frontAPI/cart/deleteFromCartAction'; @@ -16,7 +15,6 @@ prestashop.addAction = (actionName, actionFunction) => { prestashop.frontAPI[actionName] = actionFunction; }; -prestashop.addAction('addToCart', addToCartAction); prestashop.addAction('refreshCartPage', refreshCartPageAction); prestashop.addAction('updateCartQuantity', updateCartQuantityAction); prestashop.addAction('deleteFromCart', deleteFromCartAction); diff --git a/_dev/js/theme/frontAPI/cart/addToCartAction.js b/_dev/js/theme/frontAPI/cart/addToCartAction.js deleted file mode 100644 index a7f30b96..00000000 --- a/_dev/js/theme/frontAPI/cart/addToCartAction.js +++ /dev/null @@ -1,34 +0,0 @@ -import useHttpRequest from '@js/theme/components/http/useHttpRequest'; - -const addToCartAction = async (idProduct, quantity, idProductAttribute = 0, idCustomization = 0) => new Promise((resolve, reject) => { - const { request } = useHttpRequest(prestashop.urls.pages.cart); - - const payload = { - add: 1, - id_product: parseInt(idProduct, 10), - action: 'update', - token: prestashop.static_token, - qty: parseInt(quantity, 10), - ajax: 1, - }; - - if (idProductAttribute > 0) { - payload.id_product_attribute = parseInt(idProductAttribute, 10); - } - - 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 addToCartAction;