Fix bugow zwiazanych z dodawaniem do koszyka

This commit is contained in:
2025-12-19 11:09:02 +01:00
parent e62958a584
commit 8fadf8c07d
5 changed files with 216 additions and 60 deletions

187
klasa.js
View File

@@ -441,7 +441,11 @@ class IdmHotspot{
slidesPerView: 4,
centeredSlides: false,
},
}
},
// navigation: {
// nextEl: `#${this.id} .swiper-button-next`,
// prevEl: `#${this.id} .swiper-button-prev`,
// },
}
// ============================
// DOMYŚLNE OPCJE HOTSPOTA
@@ -481,13 +485,13 @@ class IdmHotspot{
// SWIPER
swiper: true,
swiperScrollbar: false,
}
},
}
/**
* Konstruktor
* @param {object} object - Dane konfiguracyjne hotspotu
*/
constructor({id, title, classes, placement, source, query, options = {}, hotspotEl, products, cssVariables}){
constructor({id, title, classes, placement, source, query, options = {}, banner, hotspotEl, products, cssVariables}){
this.id = id || "";
this.title = title || "";
this.classes = classes || "";
@@ -509,8 +513,10 @@ class IdmHotspot{
...IdmHotspot.idmDefaultHotspotOptions.cssVariables,
...cssVariables,
};
this.banner = banner || false
//
// this.hotspots = {};
this.priceType = app_shop?.vars?.priceType || "gross";
@@ -629,9 +635,9 @@ class IdmHotspot{
return markup;
}
/**
* Tworzy markup dla pojedynczego produktu.
*/
/**
* Tworzy markup dla pojedynczego produktu.
*/
markupProduct(prod){
// markup pojedynczego produktu
let singleMarkup = "";
@@ -663,7 +669,7 @@ class IdmHotspot{
${this.markupSeries(prod)}
${this.markupOpinions(prod)}
<a class="product__name" tabindex="0" href="${prod.link}" title="${prod.name}">${prod.name}</a>
${this.markupPrice({prod})}
${this.markupPrice(prod)}
${this.markupAddToBasket(prod)}
</div>`;
}
@@ -694,7 +700,8 @@ class IdmHotspot{
}
markupVersions(prod){
if(!this.options?.selectVersion || !prod.group?.versions || prod.group?.versions?.length < 2 ) return "";
if(!this.options?.selectVersion) return "";
if(!prod.group?.versions || prod.group?.versions?.length < 2 ) return `<div class="product__versions --desktop-hidden"></div>`;
// let MAX_VERSION_AMOUNT = 5;
// if(app_shop.vars.view > 2){
@@ -843,7 +850,7 @@ class IdmHotspot{
}
markupPrice({prod, sizeId}){
markupPrice(prod, sizeId=false){
let priceRoot = prod.price;
const getOmnibusDetailsObject = {productData: prod};
@@ -911,19 +918,26 @@ class IdmHotspot{
}
markupAddToBasket(prod){
let markup = "";
if(!this.options.addToBasket) return markup;
const prodTotalAmount = this.getProdTotalAmount(prod);
const prodCurrentSizeAmount = this.options.selectSize ? prod.sizes.find(size=>size.amount !== 0).amount : prod.sizes[0].amount;
let markup = "";
if(!this.options.addToBasket) return markup;
const prodCurrentSizeAmount = this.options.selectSize ? prod.sizes.find(size=>size.amount !== 0).amount : prod.sizes[0].amount;
const prodTotalAmount = this.options.selectSize ? this.getProdTotalAmount(prod) : prodCurrentSizeAmount;
/* Sprawdzanie czy hotpsot znajduje się w formularzu */
const addToBasketHTMLTag = this.isClosestForm ? "div" : "form";
// link do produktu jak nie jest to zwykły produkt
const buttonMarkup = `<button type="${this.isClosestForm ? "button" : "submit"}" class="btn --solid --medium add_to_basket__button" tabindex="0" data-success="${idmHotspotTextObject["Dodany"]}" data-error="${idmHotspotTextObject["Wystąpił błąd"]}" data-text="${idmHotspotTextObject["Do koszyka"]}">
<span>${idmHotspotTextObject["Do koszyka"]}</span>
</button>`
if(prod.type !== "product" || prodTotalAmount === 0) markup = `<a class="btn --solid --medium add_to_basket__link" href="${prod.href}">Zobacz produkt</a>`;
else if(this.options.addToBasket === "range") // +-
markup = `<form class="add_to_basket --range" action="/basketchange.php" type="post">
<input name="mode" type="hidden" value="1">
<input name="product" type="hidden" value="${prod.id}">
markup = `<${addToBasketHTMLTag} class="add_to_basket --range" ${this.isClosestForm ? "" : `action="/basketchange.php" type="post"`}>
<input class="product__add_mode" ${this.isClosestForm ? "" : `name="mode"`} type="hidden" value="1">
<input class="product__add_id" ${this.isClosestForm ? "" : `name="product"`} type="hidden" value="${prod.id}">
${this.markupSize(prod)}
<div class="idm-products-banner__qty"
data-sell-by="${prod.unit?.sellBy}"
@@ -933,8 +947,8 @@ class IdmHotspot{
<button type="button" class="idm-products-banner__qty-decrease" aria-label="${idmHotspotTextObject["Zmniejsz ilość"]}"></button>
<input type="number"
name="number"
class="idm-products-banner__qty-input"
${this.isClosestForm ? "" : `name="number"`}
class="idm-products-banner__qty-input product__add_number"
value="${prod.unit?.sellBy}"
step="${prod.unit?.sellBy}"
min="${prod.unit?.sellBy}"
@@ -945,27 +959,23 @@ class IdmHotspot{
<button type="button" class="idm-products-banner__qty-increase" aria-label="${idmHotspotTextObject["Zwiększ ilość"]}">+</button>
</div>
<button type="submit" class="btn --solid --medium add_to_basket__button" tabindex="0" data-success="${idmHotspotTextObject["Dodany"]}" data-error="${idmHotspotTextObject["Wystąpił błąd"]}" data-text="${idmHotspotTextObject["Do koszyka"]}">
<span>${idmHotspotTextObject["Do koszyka"]}</span>
</button>
</form>`;
${buttonMarkup}
</${addToBasketHTMLTag}>`;
else // Zwykłe dodanie do koszyka
markup = `
<form class="add_to_basket" action="/basketchange.php" type="post">
<input name="mode" type="hidden" value="1">
<input name="product" type="hidden" value="${prod.id}">
<${addToBasketHTMLTag} class="add_to_basket" ${this.isClosestForm ? "" : `action="/basketchange.php" type="post"`}>
<input class="product__add_mode" type="hidden" value="1" ${this.isClosestForm ? "" : `name="mode"`}>
<input class="product__add_id" type="hidden" value="${prod.id}" ${this.isClosestForm ? "" : `name="product"`}>
${this.markupSize(prod)}
<input name="number" type="hidden" value="${prod.unit?.sellBy}">
<button type="submit" class="btn --solid --medium add_to_basket__button" tabindex="0" data-success="${idmHotspotTextObject["Dodany"]}" data-error="${idmHotspotTextObject["Wystąpił błąd"]}" data-text="${idmHotspotTextObject["Do koszyka"]}">
<span>${idmHotspotTextObject["Do koszyka"]}</span>
</button>
</form>`;
<input class="product__add_number" type="hidden" value="${prod.unit?.sellBy}" ${this.isClosestForm ? "" : `name="number"`}>
${buttonMarkup}
</${addToBasketHTMLTag}>`;
return markup;
}
markupSize(prod){
// return `<input name="size" type="hidden" value="${prod.sizes[0].id}">`;
if(!this.options?.selectSize || prod.sizes.length === 1) return `<input name="size" type="hidden" value="${prod.sizes[0].id}">`;
if(!this.options?.selectSize || prod.sizes.length === 1) return `<input class="product__add_size" name="size" type="hidden" value="${prod.sizes[0].id}">`;
const sizesName = `${this.id}-${prod.id}`;
@@ -973,7 +983,7 @@ class IdmHotspot{
let selectedDefault = false;
return `
<input name="size" type="hidden" value="${prod.sizes[0].id}">
<input class="product__add_size" type="hidden" value="${prod.sizes[0].id}" ${this.isClosestForm ? "" : `name="size"`}>
<div class="product__select_sizes">
${prod.sizes.reduce((acc, val, index)=>{
const inputId = `${sizesName}-${val.id}`;
@@ -1052,6 +1062,11 @@ class IdmHotspot{
`
}
// Banner
markupBannerContainer({html, position}){
return `<div class="idm_hotspot__banner ${position ? `--${position}` : ""} ${position === "slider" ? `swiper-slide` : ""}">${html}</div>`
}
// ========================================================
// HANDLERY ZDARZEŃ
// ========================================================
@@ -1060,7 +1075,7 @@ class IdmHotspot{
* Obsługuje dodanie produktu do koszyka (GraphQL).
*/
async handleAddToBasket(e){
const formEl = e.target.closest("form.add_to_basket");
const formEl = e.target.closest(`${this.isClosestForm ? "div" : "form"}.add_to_basket`);
if(!formEl) return;
try{
// pobieranie danych i elementów
@@ -1068,9 +1083,9 @@ class IdmHotspot{
const buttonEl = formEl.querySelector(".add_to_basket__button");
e.preventDefault();
const id = formEl.querySelector("input[name='product']")?.value;
const size = formEl.querySelector("input[type='hidden'][name='size']")?.value;
const number = formEl.querySelector("input[name='number']")?.value;
const id = formEl.querySelector("input.product__add_id")?.value;
const size = formEl.querySelector("input.product__add_size")?.value;
const number = formEl.querySelector("input.product__add_number")?.value;
// dodanie do koszyka
const res = await fetch(`/graphql/v1/`, {
@@ -1096,8 +1111,7 @@ class IdmHotspot{
const existingBasketBlockQuantity = document.querySelector(`.basket__block[data-product-id="${id}"][data-product-size="${size}"] input.buy__more_input.quantity__input[type="number"]`);
// Dodanie do ilości produktu jeśli już był dodany do koszyka
if(existingBasketBlockQuantity) existingBasketBlockQuantity.value = +existingBasketBlockQuantity.value + 1;
if(existingBasketBlockQuantity) existingBasketBlockQuantity.value = +existingBasketBlockQuantity.value + number;
// Przeładowanie koszyka na stronie basketedit.html
app_shop.fn?.basket?.reloadForm();
@@ -1250,7 +1264,7 @@ class IdmHotspot{
//1. Zmiana Wybranego inputa
const sizeId = inputEl?.dataset?.value;
const hiddenSizeInputEl = e.target.closest("form.add_to_basket")?.querySelector("input[type='hidden'][name='size']");
const hiddenSizeInputEl = e.target.closest("form.add_to_basket")?.querySelector("input.product__add_size");
if(!hiddenSizeInputEl || !sizeId) return inputEl.checked = false;
@@ -1265,7 +1279,7 @@ class IdmHotspot{
const priceEl = productEl.querySelector(".product__prices");
if(!priceEl) return;
priceEl.outerHTML = this.markupPrice({prod: productData, sizeId});
priceEl.outerHTML = this.markupPrice(productData, sizeId);
this.setHeightDefault();
@@ -1853,6 +1867,8 @@ class IdmHotspot{
</h3>`);
}
if(this.banner) this.placeBanners();
await this.initSwiper();
// IDM setHeight
@@ -1867,6 +1883,43 @@ class IdmHotspot{
}
}
placeBanners(){
if(!this.placeBanners) return;
const productsWrapperEl = this.hotspotEl.querySelector(".products__wrapper");
for(let [key, value] of Object.entries(this.banner)){
const currBannerMarkup = this.markupBannerContainer({html: value?.html || "", position: key.split("-")[0] });
if(key === "top"){
productsWrapperEl.insertAdjacentHTML("beforebegin", currBannerMarkup);
}
else if(key === "left"){
productsWrapperEl.insertAdjacentHTML("beforebegin", currBannerMarkup);
}
else if(key === "right"){
productsWrapperEl.insertAdjacentHTML("afterend", currBannerMarkup);
}
else if(key === "bottom"){
productsWrapperEl.insertAdjacentHTML("afterend", currBannerMarkup);
}
else{
const slidePosition = Number(key.split("-")[1]) - 1;
if(!Number.isInteger(slidePosition)) return;
const allProducts = productsWrapperEl.querySelectorAll(".product");
let productIndex = slidePosition;
if(slidePosition > allProducts.length - 1) productIndex = allProducts.length - 1;
if(slidePosition < 0) productIndex = 0
const bannerPosition = slidePosition < 0 ? "beforebegin" : "afterend";
allProducts[productIndex]?.insertAdjacentHTML(bannerPosition, currBannerMarkup)
}
value?.callbackFn?.(this);
}
}
afterInitOnce(){
if(this.initialized) return;
@@ -1928,25 +1981,44 @@ class IdmHotspot{
/**
* Inicjuje instancję Swipera dla hotspotu.
*/
async initSwiper(){
async initSwiper(isReinitialized){
try{
// swiper || slick
if(this.options?.swiper){
// Wywołanie swipera
const selectedSwiper = new HotspotSlider({
this.swiperFn = new HotspotSlider({
selector: `#${this.id} .swiper`,
hotspotName: `${this.id}`,
options: this.options.swiper,
});
await selectedSwiper.init();
await this.swiperFn.init();
// // //Wywołanie swipera v2 (nie działa jeszcze)
// const { Slider } = await appModules?.load("Slider");
// if(!Slider) throw new Error("Brak modułu slidera")
// const idmSwiper = new Slider();
// await idmSwiper.init(this.options.swiper);
// if(!this.hotspotEl.querySelector(".swiper")) throw new Error("Brak elementu swipera")
// this.swiperFn = await idmSwiper.setupSlider({ element: this.hotspotEl.querySelector(".swiper") });
if(this.options.swiperScrollbar) new IdmSwiperProgress(selectedSwiper, `#${this.id} .swiper`);
if(this.options.swiperScrollbar && !isReinitialized) this.swiperFnProgress = new IdmSwiperProgress(this.swiperFn, `#${this.id} .swiper`);
else if(this.options.swiperScrollbar && isReinitialized) this.swiperFnProgress.reattachSwiperFn(this.swiperFn);
}
}catch(err){
console.error(idmHotspotTextObject["Wystąpił błąd z inicjalizacją. Proszę odśwież stronę"], err);
}
}
async reInitSwiper(differentOptions){
try{
if(differentOptions) this.options.swiper = differentOptions;
this.swiperFn?.slider?.slider?.destroy?.();
this.initSwiper(true);
}catch(err){
console.error(idmHotspotTextObject["Wystąpił błąd z inicjalizacją. Proszę odśwież stronę"], err);
}
}
/**
* Inicjuje eventy dla produktów w hotspotcie.
*/
@@ -1958,13 +2030,15 @@ class IdmHotspot{
initSingleEvent(prodEl){
// DODAWANIE DO KOSZYKA
if(this.options?.addToBasket){
const addToBasketEl = prodEl.querySelector("form.add_to_basket");
// Warunek this.isClosestForm w przypadku gdy hotspot znajduje się już w środku formularza
const addToBasketEl = prodEl.querySelector(`${this.isClosestForm ? "button.add_to_basket__button" : "form.add_to_basket"}`);
addToBasketEl?.addEventListener(`${this.isClosestForm ? "click" : "submit"}`, this.handleAddToBasket);
addToBasketEl?.addEventListener("submit", this.handleAddToBasket);
// + -
if(this?.options?.addToBasket === "range"){
addToBasketEl?.querySelector(".idm-products-banner__qty")?.addEventListener("click",this.handleQuantityButtonClick);
addToBasketEl?.querySelector(".idm-products-banner__qty-input")?.addEventListener("input",this.handleQuantityInputChange);
addToBasketEl?.closest(".add_to_basket")?.querySelector(".idm-products-banner__qty")?.addEventListener("click",this.handleQuantityButtonClick);
addToBasketEl?.closest(".add_to_basket")?.querySelector(".idm-products-banner__qty-input")?.addEventListener("input",this.handleQuantityInputChange);
}
}
// Dodaj do ulubionych
@@ -2023,6 +2097,9 @@ class IdmHotspot{
// Ustawienie wszystkich zmiennych CSS
this.cssSetAll();
// Sprawdzenie czy hotspot znajduje się w formularzu(dla doawania do koszyka)
this.isClosestForm = !!this.hotspotEl.closest("form");
if(this.options?.lazy) this.handleObserveHotspotOnce();
else this.fillHotspot();
}
@@ -2064,6 +2141,13 @@ class IdmSwiperProgress {
this.swiper.on("breakpoint", () => {this.updateBarWidth()});
}
reattachSwiperFn(newSwiperFn){
this.swiper = newSwiperFn?.slider?.slider ?? newSwiperFn?.slider ?? newSwiperFn;
this.progressEl.style.width = "";
this.progressEl.style.left = "";
this.updateBarWidth();
}
updateBarWidth() {
const { slidesPerGroup, slidesPerView } = this.swiper.params;
const totalSlides = this.swiper.slides.length;
@@ -2138,7 +2222,6 @@ class IdmSwiperProgress {
handle.addEventListener("touchstart", startDrag);
}
}
// ========================================================
// TOOLTIP
// ========================================================
@@ -2242,7 +2325,7 @@ async function idmPrepareHotspotObject(selectedContainerEl){
}
if(Object.keys(source).length === 0){
console.error();
console.error("Brak metody pobrania ramek rekomendacji");
selectedContainerEl?.remove();
return;
}