From 61d6b024cc2e73c116a7737865a63138acc18e4e Mon Sep 17 00:00:00 2001 From: "pawel.gaca" Date: Tue, 16 Dec 2025 14:11:59 +0100 Subject: [PATCH] =?UTF-8?q?Wyb=C3=B3r=20Rozmiar=C3=B3w=20-=20wersja=20pros?= =?UTF-8?q?ta=20wizualne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- klasa.js | 129 +++++++++++++++++++++++++++++++++++++---------------- ramka.txt | 20 +++++---- style.less | 34 +++++++++++--- 3 files changed, 129 insertions(+), 54 deletions(-) diff --git a/klasa.js b/klasa.js index 3bbbc83..aa1ad7e 100644 --- a/klasa.js +++ b/klasa.js @@ -485,6 +485,7 @@ class IdmHotspot{ this.query = query || {}; // this.type = type; this.products = products || null; + this.productsVersions = []; this.hotspotEl = hotspotEl || null; @@ -632,9 +633,6 @@ class IdmHotspot{ } markupProductInnerHTML(prod){ - // IDM DO POPRAWKI - const prodExchangedData = app_shop?.fn?.getOmnibusDetails?.({productData: prod}) || app_shop.fn?.idmGetOmnibusDetails({productData: prod}); - return `
@@ -652,9 +650,7 @@ class IdmHotspot{ ${this.markupVersions(prod)} ${this.markupOpinions(prod)} ${prod.name} -
- ${this.markupPrice(prod, prodExchangedData)} -
+ ${this.markupPrice({prod})} ${this.markupAddToBasket(prod)}
`; } @@ -790,13 +786,26 @@ class IdmHotspot{ ` } - markupPrice(prod, prodExchangedData){ - const price = prod.price.price[this.priceType]; + markupPrice({prod, sizeId}){ + let priceRoot = prod.price; + + const getOmnibusDetailsObject = {productData: prod}; + // Znalezienie ceny wybranego rozmiaru + if(this.options?.selectSize){ + const currentSizeId = sizeId || prod.sizes?.find(size=>size.amount!==0)?.id || prod.sizes?.size?.[0]?.id; + + priceRoot = prod.sizes.find(size=>size.id === currentSizeId)?.price || priceRoot; + getOmnibusDetailsObject.sizeId = currentSizeId; + }; + + const prodExchangedData = app_shop?.fn?.getOmnibusDetails?.(getOmnibusDetailsObject) || app_shop.fn?.idmGetOmnibusDetails(getOmnibusDetailsObject); + const price = priceRoot.price[this.priceType]; const unit = prod.unit; const pointsPrice = prod?.points; - const convertedPrice = prod.price?.unitConvertedPrice?.[this.priceType]?.formatted; + const convertedPrice = priceRoot?.unitConvertedPrice?.[this.priceType]?.formatted; return ` +
${price.formatted} @@ -812,6 +821,7 @@ class IdmHotspot{ ${prodExchangedData?.newPriceEffectiveUntil?.visible ? `${prodExchangedData?.newPriceEffectiveUntil?.html}` : ""} ${this.markupOmnibus(prodExchangedData?.omnibus)} ${prodExchangedData?.max?.visible ? `${prodExchangedData?.max?.html}` : ""} +
`; } @@ -848,6 +858,7 @@ class IdmHotspot{ 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; // link do produktu jak nie jest to zwykły produkt @@ -860,7 +871,7 @@ class IdmHotspot{
@@ -870,7 +881,7 @@ class IdmHotspot{ value="${prod.unit?.sellBy}" step="${prod.unit?.sellBy}" min="${prod.unit?.sellBy}" - max="${prod.sizes[0].amount === -1 ? 999999 : prod.sizes[0].amount}" + max="${prodCurrentSizeAmount === -1 ? 999999 : prodCurrentSizeAmount}" aria-label="${idmHotspotTextObject["Ilość"]}" > @@ -1181,12 +1192,38 @@ class IdmHotspot{ const inputEl = e.target.closest("input[type='radio']"); if(!inputEl) return; - const newValue = inputEl?.dataset?.value; + //1. Zmiana Wybranego inputa + const sizeId = inputEl?.dataset?.value; const hiddenSizeInputEl = e.target.closest("form.add_to_basket")?.querySelector("input[type='hidden'][name='size']"); - if(!hiddenSizeInputEl || !newValue) return inputEl.checked = false; + if(!hiddenSizeInputEl || !sizeId) return inputEl.checked = false; - hiddenSizeInputEl.value = newValue; + hiddenSizeInputEl.value = sizeId; + + // 2. Zmiana ceny + const productEl = e.target.closest(".product.hotspot__product"); + const productData = this.searchForProductData(+productEl?.dataset.id) + const currSizeData = productData?.sizes.find(size=>size.id === sizeId); + if(!currSizeData || !productData) return; + + const priceEl = productEl.querySelector(".product__prices"); + if(!priceEl) return; + + priceEl.outerHTML = this.markupPrice({prod: productData, sizeId}); + + this.setHeightDefault(); + + // 3. Zmiana maksymalnej ilości produktu dozwolonego do kupienia dla range + if(this.options.addToBasket === "range"){ + const qtyContainer = productEl.querySelector(".idm-products-banner__qty"); + const qtyInput = qtyContainer?.querySelector("input.idm-products-banner__qty-input"); + if(!qtyContainer || !qtyInput) return console.error("Brak elementów qty"); + + + qtyContainer.dataset.max = currSizeData.amount; + qtyInput.max = currSizeData.amount; + if(qtyInput.value > currSizeData.amount) qtyInput.value = currSizeData.amount - (currSizeData.amount % +qtyInput.step); + } } /** @@ -1224,6 +1261,7 @@ class IdmHotspot{ } cssVariableVersionColumnCount(){ + if(!this.options?.selectVersion) return false; this.cssSetVariable("--version-desktop-columns", this.cssVariables?.version?.columnDesktop || 5) this.cssSetVariable("--version-tablet-columns", this.cssVariables?.version?.columnTablet || 3) this.cssSetVariable("--version-mobile-columns", this.cssVariables?.version?.columnMobile || 4) @@ -1290,7 +1328,7 @@ class IdmHotspot{ cssInsertStyleTag(){ this.hotspotEl.insertAdjacentHTML("beforeend", ` `) } @@ -1305,7 +1343,7 @@ class IdmHotspot{ // ======================================================== getProdTotalAmount(prod){ - return prod.sizes.reduce((acc, val) => val === -1 || acc === -1 ? -1 : acc + val, 0); + return prod.sizes.reduce((acc, val) => val.amount === -1 || acc === -1 ? -1 : acc + val.amount, 0); } /** @@ -1347,22 +1385,38 @@ class IdmHotspot{ if (selectors?.length) selectors.forEach(adjustAllHeights) } + setHeightDefault(){ + this.setHeight({ + selectors: [ + `#${this.id} .product__prices`, + `#${this.id} .product__name`, + ], + container: `#${this.id} .products__wrapper`, + }); + } + + /** * Przeładowanie pojedynczego produktu */ async reloadProduct(prodEl, newProdId){ try{ prodEl.classList.add("--loading"); - const res = await fetch(`/graphql/v1/`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: IDM_PRODUCT_GQL(`productId: ${newProdId}`, this.priceType), - }); - const data = await res.json(); + let productData = this.searchForProductData(newProdId); + + if(!productData){ + const res = await fetch(`/graphql/v1/`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: IDM_PRODUCT_GQL(`productId: ${newProdId}`, this.priceType), + }); + const data = await res.json(); + productData = data?.data?.product?.product; + if(productData) this.productsVersions.push(productData); + } - const productData = data?.data?.product?.product; if(!productData) throw new Error("Nie udało się pobrać danych o produkcie"); @@ -1374,13 +1428,7 @@ class IdmHotspot{ else prodEl.classList.remove("--phone"); this.initSingleEvent(prodEl); - this.setHeight({ - selectors: [ - `#${this.id} .product__prices`, - `#${this.id} .product__name`, - ], - container: `#${this.id} .products__wrapper`, - }); + this.setHeightDefault(); }catch(err){ Alertek?.Error(idmHotspotTextObject["Błąd przy pobieraniu danych"]); console.error(err); @@ -1389,6 +1437,15 @@ class IdmHotspot{ } } + + searchForProductData(searchedId){ + let productData; + + productData = this.products.find(prod=>prod.id === +searchedId) || this.productsVersions.find(prod=>prod.id === +searchedId) || null; + + return productData; + } + // ======================================================== // XML to GraphQL // ======================================================== @@ -1741,13 +1798,7 @@ class IdmHotspot{ await this.initSwiper(); // IDM setHeight - this.setHeight({ - selectors: [ - `#${this.id} .product__prices`, - `#${this.id} .product__name`, - ], - container: `#${this.id} .products__wrapper`, - }); + this.setHeightDefault(); this.initEvents(); console.log(`Initialized hotspot #${this.id}`); diff --git a/ramka.txt b/ramka.txt index daa9041..f1a27ec 100644 --- a/ramka.txt +++ b/ramka.txt @@ -2,16 +2,18 @@ bugi selectSize + addToBasket="range" -- wybór rozmiaru/wersji?? Wykluczenie powtarzających się wersji +- Wykluczenie powtarzających się wersji + wersja max 5 zdjęć i później + może???? +Wyświetlanie filmu na hover? - zakres cen????????????? - Wybór kolorystyczny??? - AAAAA - banner na hotspocie - stary szablon -- blokowanie dodawania do koszyka jeśli ilość jest maksymalna -- informacje o producencie albo serri gdzieś nad produktem +- blokowanie dodawania do koszyka jeśli ilość jest maksymalna(chyba tylko nowy szablon ma app_shop.vars.basket) +- informacje o producencie albo seri gdzieś nad produktem - czy zapisywać wszystkie hotspoty do jakiegoś app_shop.fn.idmHotspots = {"#idmMainHotspot1": {}} - czy jakoś inteligentnie ucinać niepotrzebne query na podstawie wybranych opcji? chyba za dużo roboty i nie ma sensu @@ -19,13 +21,15 @@ wersja max 5 zdjęć i później + może???? - własne klasy Stara ramka -- getProductXML=t - slick -cacheowanie ramek do indexedDB +cacheowanie ramek do indexedD -awaitowanie idmHotspot +zapisywanie querySelectorów produktów?? +awaitowanie idmHotspot???(raczej nie przez intersection observer) -fix cssVariables jak nie ma wesji -zapisywanie querySelectorów produktów \ No newline at end of file +rozmiary i wersje - dropdown + + +Dodawanie do this.products klikniętego produktu na wersje, ale tak żeby nie wczytywał się ponownie, jakaś baza danych wersji?? \ No newline at end of file diff --git a/style.less b/style.less index 7cbaf0e..86bdd50 100644 --- a/style.less +++ b/style.less @@ -131,6 +131,14 @@ top: -1px; transition: all 0.3s; border-radius: 5px; + &:after{ + content: ""; + position: absolute; + opacity: 0; + height: calc(100% + 8px); + top: -4px; + width: 100%; + } } @@ -400,24 +408,28 @@ gap: 1rem; padding: 0.3rem; background: #fff; + width: 100%; input[type="radio"]{ display: none; } .product__size_select{ - width: 4.5rem; + // width: 4.5rem; + width: calc(26% - 1.5rem); height: 4.5rem; display: flex; justify-content: center; align-items: center; overflow: hidden; border: 1px solid #ccc; - transition: border 0.2s; - &:hover{ - border-color: #000; - } - &:not(:has(input:checked)){ - cursor: pointer; + transition: all 0.2s; + white-space: nowrap; + border-radius: 8px; + + &:has(input:disabled){ + opacity: 0.6; + cursor: not-allowed!important; } + &:has(input:checked){ box-shadow: 0 0 0 1px #000; border-color: #000; @@ -433,6 +445,14 @@ top: calc(100%); padding-top: 1rem; } + .product__select_sizes .product__size_select{ + &:hover:not(:has(input:disabled)){ + border-color: #000; + } + &:not(:has(input:checked)){ + cursor: pointer; + } + } .product:hover .product__select_sizes{ clip-path: inset(0 0 0 0); }