Wybór Rozmiarów - wersja prosta wizualne
This commit is contained in:
129
klasa.js
129
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 `<div class="product__yousave --hidden">
|
||||
<span class="product__yousave --label"></span>
|
||||
<span class="product__yousave --value"></span>
|
||||
@@ -652,9 +650,7 @@ class IdmHotspot{
|
||||
${this.markupVersions(prod)}
|
||||
${this.markupOpinions(prod)}
|
||||
<a class="product__name" tabindex="0" href="${prod.link}" title="${prod.name}">${prod.name}</a>
|
||||
<div class="product__prices mb-auto ${prodExchangedData?.classes?.add?.reduce((acc,val) => acc + " " + val,"")}">
|
||||
${this.markupPrice(prod, prodExchangedData)}
|
||||
</div>
|
||||
${this.markupPrice({prod})}
|
||||
${this.markupAddToBasket(prod)}
|
||||
</div>`;
|
||||
}
|
||||
@@ -790,13 +786,26 @@ class IdmHotspot{
|
||||
</div>`
|
||||
}
|
||||
|
||||
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 `
|
||||
<div class="product__prices mb-auto ${prodExchangedData?.classes?.add?.reduce((acc,val) => acc + " " + val,"")}">
|
||||
<strong class="price --normal --main ${price.value === 0 ? "--hidden" : ""}">
|
||||
<span class="price__sub">${price.formatted}</span>
|
||||
<span class="price_sellby">
|
||||
@@ -812,6 +821,7 @@ class IdmHotspot{
|
||||
${prodExchangedData?.newPriceEffectiveUntil?.visible ? `<span class="price --new-price new_price">${prodExchangedData?.newPriceEffectiveUntil?.html}</span>` : ""}
|
||||
${this.markupOmnibus(prodExchangedData?.omnibus)}
|
||||
${prodExchangedData?.max?.visible ? `<span class="price --max">${prodExchangedData?.max?.html}</span>` : ""}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
<div class="idm-products-banner__qty"
|
||||
data-sell-by="${prod.unit?.sellBy}"
|
||||
data-precision="${prod.unit?.precision}"
|
||||
data-max="${prod.sizes[0].amount === -1 ? 999999 : prod.sizes[0].amount}"
|
||||
data-max="${prodCurrentSizeAmount === -1 ? 999999 : prodCurrentSizeAmount}"
|
||||
>
|
||||
<button type="button" class="idm-products-banner__qty-decrease" aria-label="${idmHotspotTextObject["Zmniejsz ilość"]}">−</button>
|
||||
|
||||
@@ -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", `
|
||||
<style>
|
||||
${this.cssVersionColumnStyle()}
|
||||
${this.options?.selectVersion ? this.cssVersionColumnStyle() : ""}
|
||||
${this.cssSkeletonStyle()}
|
||||
</style>`)
|
||||
}
|
||||
@@ -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}`);
|
||||
|
||||
20
ramka.txt
20
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
|
||||
rozmiary i wersje - dropdown
|
||||
|
||||
|
||||
Dodawanie do this.products klikniętego produktu na wersje, ale tak żeby nie wczytywał się ponownie, jakaś baza danych wersji??
|
||||
34
style.less
34
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user