From 890175a35dad43dda1417be48fae434cb76ef489 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= <igor@istepien.dev>
Date: Wed, 4 Oct 2023 00:26:32 +0200
Subject: [PATCH 1/2] product quick view fixes

---
 _dev/js/theme/components/product.js           |  8 +++++---
 .../handler/product/productPopStateHandler.js |  4 +++-
 .../updateProductCustomizationHandler.js      |  4 +++-
 .../updateProductDOMElementsHandler.js        | 20 ++++++++++---------
 .../handler/product/updateProductHandler.js   | 11 +++++++---
 .../product/updateQuantityInputHandler.js     |  4 +++-
 .../utils/productEventContextSelector.js      | 13 ++++++++++++
 _dev/js/theme/core/selectors.js               | 17 ++++++++--------
 templates/catalog/_partials/quickview.tpl     |  5 ++++-
 9 files changed, 59 insertions(+), 27 deletions(-)
 create mode 100644 _dev/js/theme/core/product/utils/productEventContextSelector.js

diff --git a/_dev/js/theme/components/product.js b/_dev/js/theme/components/product.js
index a611c987..3cc7f8a4 100644
--- a/_dev/js/theme/components/product.js
+++ b/_dev/js/theme/components/product.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
 import prestashop from 'prestashop';
 import useCustomQuantityInput from './useCustomQuantityInput';
 import { each } from '../utils/DOMHelpers';
+import productEventContextSelector from "../core/product/utils/productEventContextSelector";
 
 $(() => {
   const createInputFile = () => {
@@ -29,7 +30,7 @@ $(() => {
       init();
     };
 
-    each('.js-product-qty-spinner', initQtySpinner);
+    each(`${productEventContextSelector()} .js-product-qty-spinner`, initQtySpinner);
   };
 
   initProductQuantityInput();
@@ -56,10 +57,11 @@ $(() => {
 
   prestashop.on('updatedProduct', (event) => {
     createInputFile();
+    const contextSelector = productEventContextSelector();
 
     if (updateEvenType === 'updatedProductCombination') {
-      $('.js-product-images').replaceWith(event.product_cover_thumbnails);
-      $('.js-product-images-modal').replaceWith(event.product_images_modal);
+      $(`${contextSelector} .js-product-images`).replaceWith(event.product_cover_thumbnails);
+      $(`${contextSelector} .js-product-images-modal`).replaceWith(event.product_images_modal);
       prestashop.emit('updatedProductCombination', event);
     }
 
diff --git a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js
index 12c2d69c..4f4b5082 100644
--- a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js
+++ b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js
@@ -1,6 +1,7 @@
 import prestashop from 'prestashop';
 import productFormDataPersister from '../../persister/productFormDataPersister';
 import productStateStore from '../../store/productStateStore';
+import productEventContextSelector from "../../utils/productEventContextSelector";
 
 const { setOnPopState, isFormChanged } = productStateStore();
 
@@ -12,6 +13,7 @@ const { get } = productFormDataPersister();
  * @param {Event} event
  */
 const productPopStateHandler = (event) => {
+  const contextElement = document.querySelector(productEventContextSelector());
   setOnPopState(true);
 
   const formData = event?.state?.form || get();
@@ -20,7 +22,7 @@ const productPopStateHandler = (event) => {
     return;
   }
 
-  const form = document.querySelector(`${prestashop.selectors.product.actions} .js-product-form`);
+  const form = contextElement.querySelector(`${prestashop.selectors.product.actions} .js-product-form`);
 
   const handleFormElementState = (data) => {
     const element = form.querySelector(`[name="${data.name}"]`);
diff --git a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js
index 48d3d692..afcd7dd5 100644
--- a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js
@@ -1,4 +1,5 @@
 import prestashop from 'prestashop';
+import productEventContextSelector from "../../utils/productEventContextSelector";
 
 /**
  * Update product customization input value
@@ -9,7 +10,8 @@ import prestashop from 'prestashop';
  * @return {void}
  */
 const updateProductCustomizationHandler = (eventType, { id_customization: idCustomization }) => {
-  const customizationIdInput = document.querySelector(prestashop.selectors.cart.productCustomizationId);
+  const contextElement = document.querySelector(productEventContextSelector());
+  const customizationIdInput = contextElement.querySelector(prestashop.selectors.cart.productCustomizationId);
 
   // refill customizationId input value when updating quantity or combination
   if (
diff --git a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js
index 160468a9..03c0e06c 100644
--- a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js
@@ -1,6 +1,7 @@
 import prestashop from 'prestashop';
 import parseToHtml from '../../../../utils/parseToHtml';
 import { each } from '../../../../utils/DOMHelpers';
+import productEventContextSelector from "../../utils/productEventContextSelector";
 
 /**
  * Replace element with new html string
@@ -41,15 +42,16 @@ const updateProductDOMElementsHandler = ({
                                            product_add_to_cart,
                                            /* eslint-enable */
 }) => {
-  each(prestashop.selectors.product.imageContainer, (el) => replaceElement(el, product_cover_thumbnails));
-  each(prestashop.selectors.product.prices, (el) => replaceElement(el, product_prices));
-  each(prestashop.selectors.product.customization, (el) => replaceElement(el, product_customization));
-  each(prestashop.selectors.product.variantsUpdate, (el) => replaceElement(el, product_variants));
-  each(prestashop.selectors.product.discounts, (el) => replaceElement(el, product_discounts));
-  each(prestashop.selectors.product.additionalInfos, (el) => replaceElement(el, product_additional_info));
-  each(prestashop.selectors.product.details, (el) => replaceElement(el, product_details));
-  each(prestashop.selectors.product.flags, (el) => replaceElement(el, product_flags));
-  each(prestashop.selectors.product.addToCart, (el) => replaceElement(el, product_add_to_cart));
+  const contextSelector = productEventContextSelector();
+
+  each(`${contextSelector} ${prestashop.selectors.product.prices}`, (el) => replaceElement(el, product_prices));
+  each(`${contextSelector} ${prestashop.selectors.product.customization}`, (el) => replaceElement(el, product_customization));
+  each(`${contextSelector} ${prestashop.selectors.product.variantsUpdate}`, (el) => replaceElement(el, product_variants));
+  each(`${contextSelector} ${prestashop.selectors.product.discounts}`, (el) => replaceElement(el, product_discounts));
+  each(`${contextSelector} ${prestashop.selectors.product.additionalInfos}`, (el) => replaceElement(el, product_additional_info));
+  each(`${contextSelector} ${prestashop.selectors.product.details}`, (el) => replaceElement(el, product_details));
+  each(`${contextSelector} ${prestashop.selectors.product.flags}`, (el) => replaceElement(el, product_flags));
+  each(`${contextSelector} ${prestashop.selectors.product.addToCart}`, (el) => replaceElement(el, product_add_to_cart));
 };
 
 export default updateProductDOMElementsHandler;
diff --git a/_dev/js/theme/core/product/handler/product/updateProductHandler.js b/_dev/js/theme/core/product/handler/product/updateProductHandler.js
index 9d2c25f7..7d2a489d 100644
--- a/_dev/js/theme/core/product/handler/product/updateProductHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateProductHandler.js
@@ -8,6 +8,7 @@ import updateQuantityInputHandler from './updateQuantityInputHandler';
 import updateProductCustomizationHandler from './updateProductCustomizationHandler';
 import updateProductDOMElementsHandler from './updateProductDOMElementsHandler';
 import { fromSerializeObject } from '../../../../utils/formSerialize';
+import productEventContextSelector from "../../utils/productEventContextSelector";
 
 const { getCurrentRequestDelayedId, setCurrentRequestDelayedId } = productStateStore();
 
@@ -18,7 +19,9 @@ const { getCurrentRequestDelayedId, setCurrentRequestDelayedId } = productStateS
  * @return {Promise<void>}
  */
 const updateProductHandler = async ({ eventType }) => {
-  const productActions = document.querySelector(prestashop.selectors.product.actions);
+  const isQuickView = isQuickViewOpen();
+  const contextElement = document.querySelector(productEventContextSelector());
+  const productActions = contextElement.querySelector(prestashop.selectors.product.actions);
   const quantityWantedInput = productActions.querySelector(prestashop.selectors.quantityWanted);
 
   const form = productActions.querySelector('.js-product-form');
@@ -38,7 +41,7 @@ const updateProductHandler = async ({ eventType }) => {
     const payload = {
       quantity_wanted: Number.parseInt(quantityWantedInput.value, 10),
       preview: isProductPreview() ? 1 : 0,
-      quickview: isQuickViewOpen() ? 1 : 0,
+      quickview: isQuickView ? 1 : 0,
       ...formSerialized,
       id_product: Number.parseInt(formSerialized.id_product, 10),
       id_product_attribute: Number.parseInt(idProductAttribute, 10),
@@ -53,7 +56,9 @@ const updateProductHandler = async ({ eventType }) => {
       updateProductCustomizationHandler(eventType, data);
       updateQuantityInputHandler(eventType, data);
 
-      document.dispatchEvent(updateRatingEvent);
+      if (isQuickView) {
+        document.dispatchEvent(updateRatingEvent);
+      }
 
       const { persist, get: getPersistedData } = productFormDataPersister();
       persist(form);
diff --git a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js
index 9339378d..f9d41637 100644
--- a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js
@@ -1,4 +1,5 @@
 import prestashop from 'prestashop';
+import productEventContextSelector from "../../utils/productEventContextSelector";
 
 /**
  * Update quantity input value
@@ -11,9 +12,10 @@ const updateQuantityInputHandler = (eventType, { product_minimal_quantity: produ
     productMinimalQuantity,
     10,
   );
+  const contextElement = document.querySelector(productEventContextSelector());
 
   if (!Number.isNaN(minimalProductQuantity) && eventType !== 'updatedProductQuantity') {
-    const newQtyInput = document.querySelector(`${prestashop.selectors.product.actions} ${prestashop.selectors.quantityWanted}`);
+    const newQtyInput = contextElement.querySelector(`${prestashop.selectors.product.actions} ${prestashop.selectors.quantityWanted}`);
     newQtyInput.value = minimalProductQuantity;
   }
 };
diff --git a/_dev/js/theme/core/product/utils/productEventContextSelector.js b/_dev/js/theme/core/product/utils/productEventContextSelector.js
new file mode 100644
index 00000000..a656a59f
--- /dev/null
+++ b/_dev/js/theme/core/product/utils/productEventContextSelector.js
@@ -0,0 +1,13 @@
+import isQuickViewOpen from "./isQuickViewOpen";
+import prestashop from "prestashop";
+
+const productEventContextSelector = () => {
+  const {
+    quickViewModal,
+    container,
+  } = prestashop.selectors.product;
+
+  return isQuickViewOpen() ? quickViewModal : container;
+}
+
+export default productEventContextSelector;
diff --git a/_dev/js/theme/core/selectors.js b/_dev/js/theme/core/selectors.js
index 368d9291..ee546be5 100644
--- a/_dev/js/theme/core/selectors.js
+++ b/_dev/js/theme/core/selectors.js
@@ -12,7 +12,8 @@ prestashop.selectors = {
     modalProductCover: '.js-modal-product-cover',
     cover: '.js-qv-product-cover',
     customizationModal: '.js-customization-modal',
-    imageContainer: '.js-quickview js-images-container, .page-product:not(.js-quickview-open) .js-product-container .images-container',
+    quickViewModal: '.js-quickview',
+    imageContainer: '.js-product-images',
     container: '.js-product-container',
     availability: '.js-product-availability',
     actions: '.js-product-actions',
@@ -21,16 +22,16 @@ prestashop.selectors = {
     miniature: '.js-product-miniature',
     minimalQuantity: '.js-product-minimal-quantity',
     addToCart: '.js-product-add-to-cart',
-    prices: '.js-quickview .js-product-prices, .page-product:not(.js-quickview-open) .js-product-prices',
+    prices: '.js-product-prices',
     inputCustomization: '.js-product-actions .js-product-customization-id',
     // eslint-disable-next-line max-len
-    customization: '.js-quickview .js-product-customization, .page-product:not(.js-quickview-open) .js-product-container .js-product-customization',
-    variantsUpdate: '.js-quickview .js-product-variants, .page-product:not(.js-quickview-open) .js-product-container .js-product-variants',
-    discounts: '.js-quickview .js-product-discounts, .page-product:not(.js-quickview-open) .js-product-container .js-product-discounts',
+    customization: '.js-product-customization',
+    variantsUpdate: '.js-product-variants',
+    discounts: '.js-product-discounts',
     // eslint-disable-next-line max-len
-    additionalInfos: '.js-quickview .js-product-additional-info, .page-product:not(.js-quickview-open) .js-product-container .js-product-additional-info',
-    details: '.js-quickview .js-product-details, .page-product:not(.js-quickview-open) .js-product-container .js-product-details',
-    flags: '.js-quickview .js-product-flags, .page-product:not(.js-quickview-open) .js-product-container .js-product-flags',
+    additionalInfos: '.js-product-additional-info',
+    details: '.js-product-details',
+    flags: '.js-product-flags',
   },
   listing: {
     searchFilterToggler: '.js-search-toggler',
diff --git a/templates/catalog/_partials/quickview.tpl b/templates/catalog/_partials/quickview.tpl
index 8340e886..52b6b69d 100644
--- a/templates/catalog/_partials/quickview.tpl
+++ b/templates/catalog/_partials/quickview.tpl
@@ -48,7 +48,10 @@
           {/block}
           {block name='product_buy'}
             <div class="product-actions js-product-actions">
-              <form action="{$urls.pages.cart}" method="post" id="add-to-cart-or-refresh">
+              <form action="{$urls.pages.cart}"
+                    method="post"
+                    id="add-to-cart-or-refresh"
+                    class="js-product-form">
                 <input type="hidden" name="token" value="{$static_token}">
                 <input type="hidden" name="id_product" value="{$product.id}" id="product_page_product_id">
                 <input type="hidden" name="id_customization" value="{$product.id_customization}" id="product_customization_id" class="js-product-customization-id">

From a03c37b7fad5e35ad8679dd616915a1777f81992 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= <igor@istepien.dev>
Date: Wed, 4 Oct 2023 00:27:54 +0200
Subject: [PATCH 2/2] es-lint fix

---
 _dev/js/theme/components/product.js                         | 2 +-
 .../core/product/handler/product/productPopStateHandler.js  | 2 +-
 .../handler/product/updateProductCustomizationHandler.js    | 2 +-
 .../handler/product/updateProductDOMElementsHandler.js      | 2 +-
 .../core/product/handler/product/updateProductHandler.js    | 2 +-
 .../product/handler/product/updateQuantityInputHandler.js   | 2 +-
 .../theme/core/product/utils/productEventContextSelector.js | 6 +++---
 7 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/_dev/js/theme/components/product.js b/_dev/js/theme/components/product.js
index 3cc7f8a4..4a11a510 100644
--- a/_dev/js/theme/components/product.js
+++ b/_dev/js/theme/components/product.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
 import prestashop from 'prestashop';
 import useCustomQuantityInput from './useCustomQuantityInput';
 import { each } from '../utils/DOMHelpers';
-import productEventContextSelector from "../core/product/utils/productEventContextSelector";
+import productEventContextSelector from '../core/product/utils/productEventContextSelector';
 
 $(() => {
   const createInputFile = () => {
diff --git a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js
index 4f4b5082..77182d60 100644
--- a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js
+++ b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js
@@ -1,7 +1,7 @@
 import prestashop from 'prestashop';
 import productFormDataPersister from '../../persister/productFormDataPersister';
 import productStateStore from '../../store/productStateStore';
-import productEventContextSelector from "../../utils/productEventContextSelector";
+import productEventContextSelector from '../../utils/productEventContextSelector';
 
 const { setOnPopState, isFormChanged } = productStateStore();
 
diff --git a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js
index afcd7dd5..ddd6c71c 100644
--- a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js
@@ -1,5 +1,5 @@
 import prestashop from 'prestashop';
-import productEventContextSelector from "../../utils/productEventContextSelector";
+import productEventContextSelector from '../../utils/productEventContextSelector';
 
 /**
  * Update product customization input value
diff --git a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js
index 03c0e06c..b8221c1d 100644
--- a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js
@@ -1,7 +1,7 @@
 import prestashop from 'prestashop';
 import parseToHtml from '../../../../utils/parseToHtml';
 import { each } from '../../../../utils/DOMHelpers';
-import productEventContextSelector from "../../utils/productEventContextSelector";
+import productEventContextSelector from '../../utils/productEventContextSelector';
 
 /**
  * Replace element with new html string
diff --git a/_dev/js/theme/core/product/handler/product/updateProductHandler.js b/_dev/js/theme/core/product/handler/product/updateProductHandler.js
index 7d2a489d..20aa2695 100644
--- a/_dev/js/theme/core/product/handler/product/updateProductHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateProductHandler.js
@@ -8,7 +8,7 @@ import updateQuantityInputHandler from './updateQuantityInputHandler';
 import updateProductCustomizationHandler from './updateProductCustomizationHandler';
 import updateProductDOMElementsHandler from './updateProductDOMElementsHandler';
 import { fromSerializeObject } from '../../../../utils/formSerialize';
-import productEventContextSelector from "../../utils/productEventContextSelector";
+import productEventContextSelector from '../../utils/productEventContextSelector';
 
 const { getCurrentRequestDelayedId, setCurrentRequestDelayedId } = productStateStore();
 
diff --git a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js
index f9d41637..4ca8f82d 100644
--- a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js
+++ b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js
@@ -1,5 +1,5 @@
 import prestashop from 'prestashop';
-import productEventContextSelector from "../../utils/productEventContextSelector";
+import productEventContextSelector from '../../utils/productEventContextSelector';
 
 /**
  * Update quantity input value
diff --git a/_dev/js/theme/core/product/utils/productEventContextSelector.js b/_dev/js/theme/core/product/utils/productEventContextSelector.js
index a656a59f..cebfd0c0 100644
--- a/_dev/js/theme/core/product/utils/productEventContextSelector.js
+++ b/_dev/js/theme/core/product/utils/productEventContextSelector.js
@@ -1,5 +1,5 @@
-import isQuickViewOpen from "./isQuickViewOpen";
-import prestashop from "prestashop";
+import prestashop from 'prestashop';
+import isQuickViewOpen from './isQuickViewOpen';
 
 const productEventContextSelector = () => {
   const {
@@ -8,6 +8,6 @@ const productEventContextSelector = () => {
   } = prestashop.selectors.product;
 
   return isQuickViewOpen() ? quickViewModal : container;
-}
+};
 
 export default productEventContextSelector;