Add product banner feature

This commit is contained in:
2025-08-14 10:05:32 +02:00
commit 7f3edddbc8
6 changed files with 1683 additions and 0 deletions

43
slick/index.xslt Normal file
View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<iai:component><iai:componentsdata><cdata-start/>
<div id="idm_products_banner" class="idm-products-banner">
<div class="idm-products-banner__header">
<h2 class="idm-products-banner__title"></h2>
<p class="idm-products-banner__text"></p>
</div>
<div class="idm-products-banner__skeletons">
<div class="idm-products-banner__product skeleton">
<div class="idm-products-banner__product-img-container">
<div class="idm-products-banner__skeleton-img"></div>
</div>
<div class="idm-products-banner__product-info">
<div class="idm-products-banner__product-name-container">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--name"></div>
</div>
<div class="idm-products-banner__product-prices">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--price"></div>
</div>
</div>
</div>
<div class="idm-products-banner__product skeleton">
<div class="idm-products-banner__product-img-container">
<div class="idm-products-banner__skeleton-img"></div>
</div>
<div class="idm-products-banner__product-info">
<div class="idm-products-banner__product-name-container">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--name"></div>
</div>
<div class="idm-products-banner__product-prices">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--price"></div>
</div>
</div>
</div>
</div>
<div class="idm-products-banner__products idm_hidden"></div>
</div>
<cdata-end/></iai:componentsdata></iai:component>

489
slick/src/main.js Normal file
View File

@@ -0,0 +1,489 @@
///////////////////////////////////////////////////////////
// dodatek po stronie panelu
///////////////////////////////////////////////////////////
const tytul = "TYTUL";
const tekst = "TEKST";
const produkty = [173632, 75469, 85452, 25065, 4147];
window.idmInteractiveBannerObj = {
idmInteractiveBannerIds: typeof produkty !== "undefined" ? produkty : null,
idmInteractiveBannerTitle: typeof tytul !== "undefined" ? tytul : "",
idmInteractiveBannerText: typeof tekst !== "undefined" ? tekst : "",
};
///////////////////////////////////////////////////////////
// pobranie zmiennych, obiekty mapujące
///////////////////////////////////////////////////////////
const idmInteractiveBannerIds = window.idmInteractiveBannerObj?.idmInteractiveBannerIds || null;
const idmInteractiveBannerTitle = window.idmInteractiveBannerObj?.idmInteractiveBannerTitle || "";
const idmInteractiveBannerText = window.idmInteractiveBannerObj?.idmInteractiveBannerText || "";
const IDM_ZONE_TEXT_MAP = {
promotion: `${<iai:variable vid="Promocja"/>}`,
discount: `${<iai:variable vid="Promocja"/>}`,
bestseller: `${<iai:variable vid="Bestseller"/>}`,
new: `${<iai:variable vid="Nowość"/>}`,
};
const IDM_ZONE_CLASS_MAP = {
promotion: "idm-products-banner__label--promo",
discount: "idm-products-banner__label--promo",
bestseller: "idm-products-banner__label--bestseller",
new: "idm-products-banner__label--new",
};
///////////////////////////////////////////////////////////
// ustawienie elementów headera
///////////////////////////////////////////////////////////
function idmSetBannerTitle(titleElement) {
if (idmInteractiveBannerTitle) {
titleElement.textContent = idmInteractiveBannerTitle;
}
}
function idmSetBannerText(textElement) {
if (idmInteractiveBannerText) {
textElement.textContent = idmInteractiveBannerText;
}
}
///////////////////////////////////////////////////////////
// ulubione
///////////////////////////////////////////////////////////
// uwaga, trzeba odkryć komponent w układzie Lista zakupowa - Javascript + CSS + XSLT
function idmAttachFavoritesEvents() {
document.querySelectorAll(".idm-products-banner__favorites-icon").forEach(el => {
el.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const icon = e.target.closest(".idm-products-banner__favorites-icon");
app_shop.fn.shoppingList.addProductToList([
[icon.getAttribute("data-id"), icon.getAttribute("data-size")]
]);
});
});
}
///////////////////////////////////////////////////////////
// dodanie do porównania
///////////////////////////////////////////////////////////
function idmHandleAddToCompare(e) {
const compareBtnEl = e.target.closest(".idm-products-banner__compare-btn");
if (!compareBtnEl || !compareBtnEl?.dataset?.compareId) return;
e.preventDefault();
idmAddToCompare(compareBtnEl, compareBtnEl.dataset.compareId);
}
async function idmAddToCompare(btnEl, compareId) {
try {
btnEl.classList.add("--loading");
const compareUrl = `/${app_shop?.vars?.language?.symbol || "de"}/settings.html?comparers=add&product=${compareId}`;
const res = await fetch(compareUrl);
console.log(res);
if (!res.ok) throw new Error(`${<iai:variable vid="Wystąpił błąd"/>}`);
btnEl.classList.add("--success");
const compareContainerQuery = "#menu_compare_product";
if (document.querySelector(compareContainerQuery)) {
app_shop.fn.load(
window.location.pathname,
[[compareContainerQuery, compareContainerQuery]],
function () {},
"?set_render=content"
);
}
setTimeout(() => {
btnEl.classList.remove("--success");
}, 2000);
} catch (err) {
console.error(err);
Alertek.Error(`${<iai:variable vid="Coś poszło nie tak. Spróbuj ponownie później"/>}`);
} finally {
btnEl.classList.remove("--loading");
}
}
///////////////////////////////////////////////////////////
// produkty
///////////////////////////////////////////////////////////
function idmGetGraphQLQuery(ids) {
return JSON.stringify({
query: `{
products(searchInput: {productsId: ${JSON.stringify(ids)}}, settingsInput: {limit: 50}) {
products {
id
type
name
zones
icon
link
sizes { id amount }
awardedParameters { name values { name } }
price {
rebateCodeActive
price { gross { value formatted } }
omnibusPrice { gross { value formatted } }
max { gross { value formatted } }
beforeRebate { gross { value formatted } }
}
unit {
id
name
sellBy
}
opinion { rating count }
}
}
}`
});
}
// helpery
const escapeHtml = (v = "") =>
String(v)
.replace(/&/g, "&amp;").replace(/</g, "&lt;")
.replace(/>/g, "&gt;").replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
const slot = (cond, html) => (cond ? html : "");
// label
function idmMarkupZoneLabel(zone) {
if (!zone) return "";
return `
<strong class="idm-products-banner__label-icons">
<span class="idm-products-banner__label ${IDM_ZONE_CLASS_MAP[zone] || ""}">
${IDM_ZONE_TEXT_MAP[zone] || ""}
</span>
</strong>`;
}
// porównanie
function idmMarkupCompareBtn(productId, options) {
if (!options?.compare) return "";
return `
<div class="idm-products-banner__compare-btn" data-compare-id="${escapeHtml(productId)}">
<button class="idm-products-banner__compare-icon" alt="${<iai:variable vid="Porównaj"/>}">
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 20 17" fill="none">
<path d="M19.3972 5.76602C19.3889 5.67435 19.3639 5.58268 19.3222 5.49102L16.5639 0.991016C16.5639 0.991016 16.5389 0.966016 16.5306 0.957682C16.4722 0.874349 16.3889 0.799349 16.2972 0.749349C16.1972 0.699349 16.0889 0.666016 16.0056 0.666016H15.9556C15.9556 0.666016 15.9139 0.666016 15.8889 0.666016C15.8472 0.666016 15.7972 0.666016 15.7472 0.682682L4.08056 4.10768C4.08056 4.10768 4.02223 4.13268 4.01389 4.14102C3.98056 4.15768 3.94723 4.17435 3.91389 4.19102C3.83889 4.24102 3.78056 4.29935 3.73889 4.35768L0.938894 8.87435C0.938894 8.87435 0.922228 8.91602 0.913894 8.93268C0.872228 9.01602 0.847228 9.10768 0.838894 9.19935V9.24935C0.788894 10.216 1.12223 11.1493 1.77223 11.866C2.42223 12.5827 3.31389 13.0077 4.29723 13.0577C5.26389 13.0077 6.15556 12.5827 6.81389 11.866C7.46389 11.1493 7.79723 10.216 7.75556 9.25768C7.75556 9.23268 7.75556 9.21602 7.74723 9.19935C7.73889 9.10768 7.71389 9.01602 7.67223 8.93268L5.40556 5.22435L9.39723 4.04935V15.5493H6.56389V16.991H13.6639V15.5493H10.8389V3.62435L14.3472 2.59102L12.5889 5.44102C12.5889 5.44102 12.5722 5.48268 12.5639 5.49935C12.5222 5.58268 12.4972 5.67435 12.4889 5.75768V5.81602C12.4306 6.78268 12.7722 7.71602 13.4222 8.43268C14.0722 9.14935 14.9639 9.57435 15.9472 9.62435C16.9139 9.57435 17.8056 9.14935 18.4639 8.43268C19.1139 7.71602 19.4472 6.78268 19.4056 5.82435V5.76602H19.3972ZM17.8806 6.54935C17.7889 6.96602 17.5639 7.35768 17.2389 7.64935C16.8806 7.97435 16.4222 8.16602 15.9472 8.19102C15.4722 8.15768 15.0139 7.96602 14.6556 7.64935C14.3389 7.35768 14.1139 6.97435 14.0139 6.54935H17.8806ZM14.4972 5.10768L15.9472 2.74935L17.3972 5.10768H14.4972ZM2.84723 8.53268L4.29723 6.17435L5.74723 8.53268H2.84723ZM6.23056 9.97435C6.13056 10.391 5.91389 10.7827 5.58889 11.0743C5.23056 11.3993 4.77223 11.591 4.29723 11.616C3.82223 11.5827 3.36389 11.391 3.00556 11.0743C2.68889 10.7827 2.46389 10.3993 2.36389 9.97435H6.23056Z" fill="#111111"/>
</svg>
</button>
</div>`;
}
// ulubione
function idmMarkupFavoritesIcon(productId, sizeId, options) {
if (!options?.favorites) return "";
return `
<div class="idm-products-banner__favorites-icon" data-id="${escapeHtml(productId)}" data-size="${escapeHtml(sizeId || 'uniw')}">
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 22 22" fill="none">
<path d="M11 19.5478C10.7861 19.5478 10.5684 19.5096 10.3469 19.4332C10.1253 19.3568 9.93053 19.2346 9.76248 19.0665L8.18123 17.6228C6.56179 16.1408 5.09894 14.6704 3.79269 13.2113C2.48644 11.7523 1.83331 10.1443 1.83331 8.38737C1.83331 6.95126 2.31456 5.75195 3.27706 4.78945C4.23956 3.82695 5.43887 3.3457 6.87498 3.3457C7.6847 3.3457 8.44859 3.51758 9.16665 3.86133C9.8847 4.20508 10.4958 4.67487 11 5.2707C11.5041 4.67487 12.1153 4.20508 12.8333 3.86133C13.5514 3.51758 14.3153 3.3457 15.125 3.3457C16.5611 3.3457 17.7604 3.82695 18.7229 4.78945C19.6854 5.75195 20.1666 6.95126 20.1666 8.38737C20.1666 10.1443 19.5173 11.7561 18.2187 13.2228C16.9201 14.6895 15.4458 16.1638 13.7958 17.6457L12.2375 19.0665C12.0694 19.2346 11.8746 19.3568 11.6531 19.4332C11.4316 19.5096 11.2139 19.5478 11 19.5478ZM10.1291 7.10404C9.68609 6.47765 9.21248 6.00022 8.70831 5.67175C8.20415 5.34327 7.59303 5.17904 6.87498 5.17904C5.95831 5.17904 5.19442 5.48459 4.58331 6.0957C3.9722 6.70681 3.66665 7.4707 3.66665 8.38737C3.66665 9.18181 3.94929 10.0259 4.51456 10.9197C5.07984 11.8134 5.75588 12.6804 6.54269 13.5207C7.32949 14.361 8.13922 15.1478 8.97185 15.8811C9.80449 16.6145 10.4805 17.2179 11 17.6915C11.5194 17.2179 12.1955 16.6145 13.0281 15.8811C13.8607 15.1478 14.6705 14.361 15.4573 13.5207C16.2441 12.6804 16.9201 11.8134 17.4854 10.9197C18.0507 10.0259 18.3333 9.18181 18.3333 8.38737C18.3333 7.4707 18.0278 6.70681 17.4166 6.0957C16.8055 5.48459 16.0416 5.17904 15.125 5.17904C14.4069 5.17904 13.7958 5.34327 13.2916 5.67175C12.7875 6.00022 12.3139 6.47765 11.8708 7.10404C11.7639 7.25681 11.634 7.3714 11.4812 7.44779C11.3285 7.52418 11.168 7.56237 11 7.56237C10.8319 7.56237 10.6715 7.52418 10.5187 7.44779C10.366 7.3714 10.2361 7.25681 10.1291 7.10404Z" fill="black"/>
</svg>
</div>`;
}
// ikona
function idmMarkupImage(link, icon) {
return `
<a href="${escapeHtml(link)}" class="idm-products-banner__product-img-link">
<img src="${escapeHtml(icon)}" alt="" class="idm-products-banner__products-img">
</a>`;
}
// nazwa
function idmMarkupName(name, link) {
return `
<div class="idm-products-banner__product-name-container">
<a href="${escapeHtml(link)}" class="idm-products-banner__product-name-link">
<p class="idm-products-banner__product-name">${escapeHtml(name)}</p>
</a>
</div>`;
}
// ceny
function idmMarkupPrices(priceObj) {
const current = priceObj?.price?.gross?.formatted || "";
const max = priceObj?.max?.gross?.formatted || "";
const hasOmnibus = priceObj?.omnibusPrice?.gross?.formatted;
let mainPrice = "";
if (current && max && max !== current) {
mainPrice = `${escapeHtml(current)} <del class="idm-products-banner__price-max">${escapeHtml(max)}</del>`;
} else if (current) {
mainPrice = escapeHtml(current);
} else if (max) {
mainPrice = `<span class="idm-products-banner__price-max">${escapeHtml(max)}</span>`;
}
const oldPrice = hasOmnibus
? `<span>${<iai:variable vid="Najniższa cena z 30 dni przed obniżką"/>}</span> <del>${escapeHtml(current || max)}</del>`
: "";
return `
<div class="idm-products-banner__product-prices">
<div class="idm-products-banner__product-price-container">
<div class="idm-products-banner__product-prices-box">
<strong class="idm-products-banner__price">${mainPrice}</strong>
<p class="idm-products-banner__price-omnibus">${oldPrice}</p>
</div>
</div>
</div>`;
}
// dodawanie do koszyka
function idmMarkupAddToBasket(product, size, options) {
if (!options?.addToBasket) return "";
const can = product?.type === "product" && product?.sizes?.length === 1 && size;
if (!can) return "";
const sellBy = size?.unitSellby || 1;
const precision = size?.unitPrecision || 0;
const max = (typeof size?.amount === "number" && size.amount > 0) ? size.amount : "";
return `
<div class="idm-products-banner__add-to-basket">
<form class="idm-products-banner__add-to-basket-form" action="/basketchange.php" method="post">
<input type="hidden" name="mode" value="1">
<input type="hidden" name="product" value="${escapeHtml(product.id)}">
<input type="hidden" name="size" value="${escapeHtml(size.id)}">
<div class="idm-products-banner__qty"
data-sell-by="${escapeHtml(String(sellBy))}"
data-precision="${escapeHtml(String(precision))}"
data-max="${escapeHtml(String(max))}">
<button type="button" class="idm-products-banner__qty-decrease"></button>
<input type="number"
name="number"
class="idm-products-banner__qty-input"
value="${escapeHtml(String(sellBy))}"
step="${escapeHtml(String(sellBy))}"
min="${escapeHtml(String(sellBy))}"
max="${escapeHtml(String(max))}">
<button type="button" class="idm-products-banner__qty-increase">+</button>
</div>
<button type="submit" class="btn --solid --medium idm-products-banner__add-to-basket-button">
<span>${<iai:variable vid="Do koszyka" />}</span>
</button>
</form>
</div>`;
}
// link więcej opcji
function idmMarkupMoreOptions(link) {
return `
<div class="idm-products-banner__add-to-basket">
<a class="btn --solid --medium idm-products-banner__add-to-basket-link" href="${escapeHtml(link)}">
${<iai:variable vid="Więcej opcji"/>}
</a>
</div>`;
}
// assembler produktu
function idmRenderProductCard(product, options = {}) {
const zone = product?.zones?.[0];
const size = product?.sizes?.[0];
const headIcons = `
${idmMarkupCompareBtn(product.id, options)}
${idmMarkupFavoritesIcon(product.id, size?.id, options)}
${idmMarkupZoneLabel(zone)}
`;
const addSection =
(options?.addToBasket && product?.type === "product" && product?.sizes?.length === 1 && size)
? idmMarkupAddToBasket(product, size, options)
: idmMarkupMoreOptions(product.link);
return `
<div class="idm-products-banner__product product">
<div class="idm-products-banner__product-img-container">
${headIcons}
${idmMarkupImage(product.link, product.icon)}
</div>
<div class="idm-products-banner__product-info">
${idmMarkupName(product.name, product.link)}
${idmMarkupPrices(product.price)}
${addSection}
</div>
</div>`;
}
// tworzenie, ustawienie opcji
function idmCreateProductMarkup(products, options = { compare: true, favorites: true, addToBasket: true }) {
return products.map(p => idmRenderProductCard(p, options)).join("");
}
async function idmRenderBannerProducts(container) {
const skeletons = document.querySelector(".idm-products-banner__skeletons");
if (!idmInteractiveBannerIds) return;
try {
container.innerHTML = "";
const response = await fetch("/graphql/v1/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: idmGetGraphQLQuery(idmInteractiveBannerIds),
});
const json = await response.json();
const productsData = json?.data?.products?.products;
console.log(productsData);
if (!productsData) return;
const sorted = idmInteractiveBannerIds
.map(id => productsData.find(p => p.id === id))
.filter(Boolean);
container.innerHTML = idmCreateProductMarkup(sorted);
idmInitSlickSlider(container);
idmAttachFavoritesEvents();
// +/- i walidacja inputów ilości
document.addEventListener("click", (e) => {
const wrapper = e.target.closest(".idm-products-banner__qty");
if (!wrapper) return;
const input = wrapper.querySelector(".idm-products-banner__qty-input");
const step = parseFloat(wrapper.dataset.sellBy || "1");
const precision = parseInt(wrapper.dataset.precision || "0");
const max = parseFloat(wrapper.dataset.max || "999999");
let current = parseFloat(input.value) || 0;
if (e.target.classList.contains("idm-products-banner__qty-increase")) {
current += step;
if (current > max) current = max;
} else if (e.target.classList.contains("idm-products-banner__qty-decrease")) {
current -= step;
if (current < step) current = step;
}
input.value = current.toFixed(precision);
});
document.addEventListener("blur", (e) => {
if (!e.target.classList.contains("idm-products-banner__qty-input")) return;
const input = e.target;
const wrapper = input.closest(".idm-products-banner__qty");
const step = parseFloat(wrapper.dataset.sellBy || "1");
const precision = parseInt(wrapper.dataset.precision || "0");
const max = parseFloat(wrapper.dataset.max || "999999");
let val = parseFloat(input.value);
if (isNaN(val) || val < step) {
val = step;
} else if (val > max) {
val = max;
} else {
val = Math.round(val / step) * step;
}
input.value = val.toFixed(precision);
}, true);
// ukrycie skeletona
skeletons?.classList.add("idm_hidden");
container.classList.remove("idm_hidden");
// event porównania (delegacja)
document.addEventListener("click", idmHandleAddToCompare);
} catch (err) {
console.error("Błąd pobierania produktów:", err);
}
}
///////////////////////////////////////////////////////////
// slider i wyrównanie wysokości
///////////////////////////////////////////////////////////
function idmInitSlickSlider(container) {
$(container).on("init", function () {
app_shop.fn.setHeight({
selectors: [
".idm-products-banner .idm-products-banner__product-img-container",
".idm-products-banner .idm-products-banner__product-name",
".idm-products-banner .idm-products-banner__price",
".idm-products-banner .idm-products-banner__price-omnibus",
".idm-products-banner .idm-products-banner__add-to-basket",
".idm-products-banner .product"
],
container: ".idm-products-banner__products .slick-track"
});
});
$(container).slick({
slidesToShow: 2,
slidesToScroll: 1,
autoplay: false,
dots: false,
arrows: true,
prevArrow: '<button class="slick-prev"><i class="fa fa-chevron-left"></i></button>',
nextArrow: '<button class="slick-next"><i class="fa fa-chevron-right"></i></button>',
responsive: [
{ breakpoint: 979, settings: { slidesToShow: 2 } },
{ breakpoint: 757, settings: { slidesToShow: 2 } },
],
});
}
///////////////////////////////////////////////////////////
// start działania
///////////////////////////////////////////////////////////
function idmWaitForBannerElements() {
let attempts = 0;
const interval = setInterval(() => {
let initialized = 0;
const bannerTitle = document.querySelector(".idm-products-banner__title");
if (bannerTitle) {
idmSetBannerTitle(bannerTitle);
initialized++;
}
const bannerText = document.querySelector(".idm-products-banner__text");
if (bannerText) {
idmSetBannerText(bannerText);
initialized++;
}
const bannerContainer = document.querySelector(".idm-products-banner__products");
if (bannerContainer) {
idmRenderBannerProducts(bannerContainer);
initialized++;
}
const bannerHeader = document.querySelector(".idm-products-banner__header");
if (bannerHeader) {
initialized++;
}
if (initialized >= 4) {
clearInterval(interval);
} else if (++attempts >= 10) {
clearInterval(interval);
console.warn("Niektóre wymagane elementy DOM nie zostały znalezione");
}
}, 500);
}
document.addEventListener("DOMContentLoaded", function () {
idmWaitForBannerElements();
});

290
slick/src/style.less Normal file
View File

@@ -0,0 +1,290 @@
.idm-products-banner {
display: flex;
flex-direction: column;
margin: 3rem 0;
background: #eaebe9;
&__header {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 42rem;
background: #000;
}
&__title {
color: #fff;
font-size: 4rem;
}
&__text {
color: #fff;
font-size: 2rem;
}
&__products {
width: 100%;
&.idm_hidden {
display: none;
}
}
&__product {
padding: 1rem;
background: none;
text-align: center;
}
&__product-name-link {
text-decoration: none;
}
&__product-name {
color: #333;
margin: 1rem 0;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
&__price-omnibus {
font-size: 1.2rem;
margin-top: 1rem;
}
&__price-max {
color: #acacac;
margin-left: 1rem;
}
&__product-img-container {
position: relative;
}
&__products-img {
width: 100%;
}
.slick-prev.slick-arrow {
&::before {
content: "\f104";
font-family: "FONTAWESOME";
}
}
.slick-next.slick-arrow {
&::before {
content: "\f105";
font-family: "FONTAWESOME";
}
}
&__favorites-icon {
position: absolute;
top: 2rem;
right: 1rem;
z-index: 100;
cursor: pointer;
width: 3rem;
height: 3rem;
&:hover {
opacity: 0.6;
}
}
&__label-icons {
position: absolute;
bottom: 0;
left: 0;
text-align: left;
}
&__label {
padding: 0.4rem 0.8rem;
text-transform: uppercase;
background: #000;
color: #fff;
&--promo { }
&--new { }
&--bestseller { }
}
&__compare-btn {
position: absolute;
top: 2rem;
left: 2rem;
background: #fff;
&.--success {
svg {
display: none;
}
&::before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='25' viewBox='0 0 25 25' fill='none'%3E%3Cpath d='M10.0516 18.5L4.35156 12.8L5.77656 11.375L10.0516 15.65L19.2266 6.475L20.6516 7.9L10.0516 18.5Z' fill='%23009263'/%3E%3C/svg%3E");
width: 3rem;
height: 3rem;
}
}
&.--loading:not(.--success) { }
&:not(.--success):hover {
opacity: 0.6;
}
}
&__compare-icon { }
&__add-to-basket {
&_btn {
background: #000;
color: #fff;
padding: 1rem 2rem;
width: 100%;
border-radius: 0.6rem;
margin-top: 1rem;
text-transform: uppercase;
}
}
&__skeletons {
width: 100%;
display: flex;
@media (min-width: 757px) {
width: 50%;
}
&.idm_hidden {
display: none;
}
.idm-products-banner__product.skeleton {
width: 50%;
}
}
&__skeleton-img {
width: 100%;
background: #ddd;
aspect-ratio: 1;
}
&__skeleton-text {
&--name {
width: 100%;
height: 2rem;
background: #ddd;
margin-top: 2rem;
}
&--price {
width: 50%;
height: 2rem;
background: #ddd;
margin: 2rem auto;
}
}
@keyframes skeletonPulse {
0% { background-color: #ddd; }
50% { background-color: #eaeaea; }
100% { background-color: #ddd; }
}
&__skeleton-img,
&__skeleton-text {
animation: skeletonPulse 1.5s ease-in-out infinite;
}
&__product-prices { }
&__product-price-container { }
&__product-prices-box { }
&__price { }
&__qty {
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
gap: 1rem;
}
&__qty-input {
height: 4rem;
text-align: center;
border: 1px solid #ccc;
width: 60%;
max-width: unset;
min-width: unset;
}
&__qty button {
background: #000;
height: 4rem;
width: 4rem;
color: #fff;
border-radius: 0.5rem;
min-width: 4rem;
}
&__add-to-basket-form {
display: flex;
flex-direction: column;
gap: 2rem;
width: 100%;
}
.btn.--solid.--medium.idm-products-banner__add-to-basket-button {
height: 4rem;
background: #000;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #000;
}
.btn.--solid.--medium.idm-products-banner__add-to-basket-link {
width: 100%;
height: 4rem;
display: flex;
align-items: center;
justify-content: center;
background: #000;
border: 1px solid #000;
margin-top: auto;
}
&__add-to-basket {
display: flex;
align-items: end;
flex-direction: column;
width: 80%;
margin: 0 auto;
}
@media (min-width: 757px) {
flex-direction: row;
align-items: center;
&__header {
width: 50%;
}
&__title {
font-size: 5rem;
}
&__products {
width: 50%;
}
&__product {
&-img_container { }
}
}
}

49
swiper/index.xslt Normal file
View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<iai:component><iai:componentsdata><cdata-start/>
<div id="idm_products_banner" class="idm-products-banner">
<div class="idm-products-banner__header">
<h2 class="idm-products-banner__title"></h2>
<p class="idm-products-banner__text"></p>
</div>
<div class="idm-products-banner__skeletons">
<div class="idm-products-banner__product skeleton">
<div class="idm-products-banner__product-img-container">
<div class="idm-products-banner__skeleton-img"></div>
</div>
<div class="idm-products-banner__product-info">
<div class="idm-products-banner__product-name-container">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--name"></div>
</div>
<div class="idm-products-banner__product-prices">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--price"></div>
</div>
</div>
</div>
<div class="idm-products-banner__product skeleton">
<div class="idm-products-banner__product-img-container">
<div class="idm-products-banner__skeleton-img"></div>
</div>
<div class="idm-products-banner__product-info">
<div class="idm-products-banner__product-name-container">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--name"></div>
</div>
<div class="idm-products-banner__product-prices">
<div class="idm-products-banner__skeleton-text idm-products-banner__skeleton-text--price"></div>
</div>
</div>
</div>
</div>
<div class="idm-products-banner__products-container swiper idm_hidden">
<div class="idm-products-banner__products swiper-wrapper"></div>
<div class="idm-products-banner__nav">
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
</div>
</div>
<cdata-end/></iai:componentsdata></iai:component>

507
swiper/src/main.js Normal file
View File

@@ -0,0 +1,507 @@
///////////////////////////////////////////////////////////
// dodatek po stronie panelu
///////////////////////////////////////////////////////////
const tytul = "TYTUL";
const tekst = "TEKST";
const produkty = [173632, 75469, 85452, 25065, 4147];
window.idmInteractiveBannerObj = {
idmInteractiveBannerIds: typeof produkty !== "undefined" ? produkty : null,
idmInteractiveBannerTitle: typeof tytul !== "undefined" ? tytul : "",
idmInteractiveBannerText: typeof tekst !== "undefined" ? tekst : "",
};
///////////////////////////////////////////////////////////
// pobranie zmiennych, obiekty mapujące
///////////////////////////////////////////////////////////
const idmInteractiveBannerIds = window.idmInteractiveBannerObj?.idmInteractiveBannerIds || null;
const idmInteractiveBannerTitle = window.idmInteractiveBannerObj?.idmInteractiveBannerTitle || "";
const idmInteractiveBannerText = window.idmInteractiveBannerObj?.idmInteractiveBannerText || "";
const IDM_ZONE_TEXT_MAP = {
promotion: `${<iai:variable vid="Promocja"/>}`,
discount: `${<iai:variable vid="Promocja"/>}`,
bestseller: `${<iai:variable vid="Bestseller"/>}`,
new: `${<iai:variable vid="Nowość"/>}`,
};
const IDM_ZONE_CLASS_MAP = {
promotion: "idm-products-banner__label--promo",
discount: "idm-products-banner__label--promo",
bestseller: "idm-products-banner__label--bestseller",
new: "idm-products-banner__label--new",
};
///////////////////////////////////////////////////////////
// ustawienie elementów headera
///////////////////////////////////////////////////////////
function idmSetBannerTitle(titleElement) {
if (idmInteractiveBannerTitle) {
titleElement.textContent = idmInteractiveBannerTitle;
}
}
function idmSetBannerText(textElement) {
if (idmInteractiveBannerText) {
textElement.textContent = idmInteractiveBannerText;
}
}
///////////////////////////////////////////////////////////
// ulubione
///////////////////////////////////////////////////////////
// uwaga, trzeba odkryć komponent w układzie Lista zakupowa - Javascript + CSS + XSLT
function idmAttachFavoritesEvents() {
document.querySelectorAll(".idm-products-banner__favorites-icon").forEach(el => {
el.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const icon = e.target.closest(".idm-products-banner__favorites-icon");
app_shop.fn.shoppingList.addProductToList([
[icon.getAttribute("data-id"), icon.getAttribute("data-size")]
]);
});
});
}
///////////////////////////////////////////////////////////
// dodanie do porównania
///////////////////////////////////////////////////////////
function idmHandleAddToCompare(e) {
const compareBtnEl = e.target.closest(".idm-products-banner__compare-btn");
if (!compareBtnEl || !compareBtnEl?.dataset?.compareId) return;
e.preventDefault();
idmAddToCompare(compareBtnEl, compareBtnEl.dataset.compareId);
}
async function idmAddToCompare(btnEl, compareId) {
try {
btnEl.classList.add("--loading");
const compareUrl = `/${app_shop?.vars?.language?.symbol || "de"}/settings.html?comparers=add&product=${compareId}`;
const res = await fetch(compareUrl);
console.log(res);
if (!res.ok) throw new Error(`${<iai:variable vid="Wystąpił błąd"/>}`);
btnEl.classList.add("--success");
const compareContainerQuery = "#menu_compare_product";
if (document.querySelector(compareContainerQuery)) {
app_shop.fn.load(
window.location.pathname,
[[compareContainerQuery, compareContainerQuery]],
function () {},
"?set_render=content"
);
}
setTimeout(() => {
btnEl.classList.remove("--success");
}, 2000);
} catch (err) {
console.error(err);
Alertek.Error(`${<iai:variable vid="Coś poszło nie tak. Spróbuj ponownie później"/>}`);
} finally {
btnEl.classList.remove("--loading");
}
}
///////////////////////////////////////////////////////////
// produkty
///////////////////////////////////////////////////////////
function idmGetGraphQLQuery(ids) {
return JSON.stringify({
query: `{
products(searchInput: {productsId: ${JSON.stringify(ids)}}, settingsInput: {limit: 50}) {
products {
id
type
name
zones
icon
link
sizes { id amount }
awardedParameters { name values { name } }
price {
rebateCodeActive
price { gross { value formatted } }
omnibusPrice { gross { value formatted } }
max { gross { value formatted } }
beforeRebate { gross { value formatted } }
}
unit {
id
name
sellBy
}
opinion { rating count }
}
}
}`
});
}
// helpery
const escapeHtml = (v = "") =>
String(v)
.replace(/&/g, "&amp;").replace(/</g, "&lt;")
.replace(/>/g, "&gt;").replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
const slot = (cond, html) => (cond ? html : "");
// label
function idmMarkupZoneLabel(zone) {
if (!zone) return "";
return `
<strong class="idm-products-banner__label-icons">
<span class="idm-products-banner__label ${IDM_ZONE_CLASS_MAP[zone] || ""}">
${IDM_ZONE_TEXT_MAP[zone] || ""}
</span>
</strong>`;
}
// porównanie
function idmMarkupCompareBtn(productId, options) {
if (!options?.compare) return "";
return `
<div class="idm-products-banner__compare-btn" data-compare-id="${escapeHtml(productId)}">
<button class="idm-products-banner__compare-icon" alt="${<iai:variable vid="Porównaj"/>}">
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 20 17" fill="none">
<path d="M19.3972 5.76602C19.3889 5.67435 19.3639 5.58268 19.3222 5.49102L16.5639 0.991016C16.5639 0.991016 16.5389 0.966016 16.5306 0.957682C16.4722 0.874349 16.3889 0.799349 16.2972 0.749349C16.1972 0.699349 16.0889 0.666016 16.0056 0.666016H15.9556C15.9556 0.666016 15.9139 0.666016 15.8889 0.666016C15.8472 0.666016 15.7972 0.666016 15.7472 0.682682L4.08056 4.10768C4.08056 4.10768 4.02223 4.13268 4.01389 4.14102C3.98056 4.15768 3.94723 4.17435 3.91389 4.19102C3.83889 4.24102 3.78056 4.29935 3.73889 4.35768L0.938894 8.87435C0.938894 8.87435 0.922228 8.91602 0.913894 8.93268C0.872228 9.01602 0.847228 9.10768 0.838894 9.19935V9.24935C0.788894 10.216 1.12223 11.1493 1.77223 11.866C2.42223 12.5827 3.31389 13.0077 4.29723 13.0577C5.26389 13.0077 6.15556 12.5827 6.81389 11.866C7.46389 11.1493 7.79723 10.216 7.75556 9.25768C7.75556 9.23268 7.75556 9.21602 7.74723 9.19935C7.73889 9.10768 7.71389 9.01602 7.67223 8.93268L5.40556 5.22435L9.39723 4.04935V15.5493H6.56389V16.991H13.6639V15.5493H10.8389V3.62435L14.3472 2.59102L12.5889 5.44102C12.5889 5.44102 12.5722 5.48268 12.5639 5.49935C12.5222 5.58268 12.4972 5.67435 12.4889 5.75768V5.81602C12.4306 6.78268 12.7722 7.71602 13.4222 8.43268C14.0722 9.14935 14.9639 9.57435 15.9472 9.62435C16.9139 9.57435 17.8056 9.14935 18.4639 8.43268C19.1139 7.71602 19.4472 6.78268 19.4056 5.82435V5.76602H19.3972ZM17.8806 6.54935C17.7889 6.96602 17.5639 7.35768 17.2389 7.64935C16.8806 7.97435 16.4222 8.16602 15.9472 8.19102C15.4722 8.15768 15.0139 7.96602 14.6556 7.64935C14.3389 7.35768 14.1139 6.97435 14.0139 6.54935H17.8806ZM14.4972 5.10768L15.9472 2.74935L17.3972 5.10768H14.4972ZM2.84723 8.53268L4.29723 6.17435L5.74723 8.53268H2.84723ZM6.23056 9.97435C6.13056 10.391 5.91389 10.7827 5.58889 11.0743C5.23056 11.3993 4.77223 11.591 4.29723 11.616C3.82223 11.5827 3.36389 11.391 3.00556 11.0743C2.68889 10.7827 2.46389 10.3993 2.36389 9.97435H6.23056Z" fill="#111111"/>
</svg>
</button>
</div>`;
}
// ulubione
function idmMarkupFavoritesIcon(productId, sizeId, options) {
if (!options?.favorites) return "";
return `
<div class="idm-products-banner__favorites-icon" data-id="${escapeHtml(productId)}" data-size="${escapeHtml(sizeId || 'uniw')}">
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 22 22" fill="none">
<path d="M11 19.5478C10.7861 19.5478 10.5684 19.5096 10.3469 19.4332C10.1253 19.3568 9.93053 19.2346 9.76248 19.0665L8.18123 17.6228C6.56179 16.1408 5.09894 14.6704 3.79269 13.2113C2.48644 11.7523 1.83331 10.1443 1.83331 8.38737C1.83331 6.95126 2.31456 5.75195 3.27706 4.78945C4.23956 3.82695 5.43887 3.3457 6.87498 3.3457C7.6847 3.3457 8.44859 3.51758 9.16665 3.86133C9.8847 4.20508 10.4958 4.67487 11 5.2707C11.5041 4.67487 12.1153 4.20508 12.8333 3.86133C13.5514 3.51758 14.3153 3.3457 15.125 3.3457C16.5611 3.3457 17.7604 3.82695 18.7229 4.78945C19.6854 5.75195 20.1666 6.95126 20.1666 8.38737C20.1666 10.1443 19.5173 11.7561 18.2187 13.2228C16.9201 14.6895 15.4458 16.1638 13.7958 17.6457L12.2375 19.0665C12.0694 19.2346 11.8746 19.3568 11.6531 19.4332C11.4316 19.5096 11.2139 19.5478 11 19.5478ZM10.1291 7.10404C9.68609 6.47765 9.21248 6.00022 8.70831 5.67175C8.20415 5.34327 7.59303 5.17904 6.87498 5.17904C5.95831 5.17904 5.19442 5.48459 4.58331 6.0957C3.9722 6.70681 3.66665 7.4707 3.66665 8.38737C3.66665 9.18181 3.94929 10.0259 4.51456 10.9197C5.07984 11.8134 5.75588 12.6804 6.54269 13.5207C7.32949 14.361 8.13922 15.1478 8.97185 15.8811C9.80449 16.6145 10.4805 17.2179 11 17.6915C11.5194 17.2179 12.1955 16.6145 13.0281 15.8811C13.8607 15.1478 14.6705 14.361 15.4573 13.5207C16.2441 12.6804 16.9201 11.8134 17.4854 10.9197C18.0507 10.0259 18.3333 9.18181 18.3333 8.38737C18.3333 7.4707 18.0278 6.70681 17.4166 6.0957C16.8055 5.48459 16.0416 5.17904 15.125 5.17904C14.4069 5.17904 13.7958 5.34327 13.2916 5.67175C12.7875 6.00022 12.3139 6.47765 11.8708 7.10404C11.7639 7.25681 11.634 7.3714 11.4812 7.44779C11.3285 7.52418 11.168 7.56237 11 7.56237C10.8319 7.56237 10.6715 7.52418 10.5187 7.44779C10.366 7.3714 10.2361 7.25681 10.1291 7.10404Z" fill="black"/>
</svg>
</div>`;
}
// ikona
function idmMarkupImage(link, icon) {
return `
<a href="${escapeHtml(link)}" class="idm-products-banner__product-img-link">
<img src="${escapeHtml(icon)}" alt="" class="idm-products-banner__products-img">
</a>`;
}
// nazwa
function idmMarkupName(name, link) {
return `
<div class="idm-products-banner__product-name-container">
<a href="${escapeHtml(link)}" class="idm-products-banner__product-name-link">
<p class="idm-products-banner__product-name">${escapeHtml(name)}</p>
</a>
</div>`;
}
// ceny
function idmMarkupPrices(priceObj) {
const current = priceObj?.price?.gross?.formatted || "";
const max = priceObj?.max?.gross?.formatted || "";
const hasOmnibus = priceObj?.omnibusPrice?.gross?.formatted;
let mainPrice = "";
if (current && max && max !== current) {
mainPrice = `${escapeHtml(current)} <del class="idm-products-banner__price-max">${escapeHtml(max)}</del>`;
} else if (current) {
mainPrice = escapeHtml(current);
} else if (max) {
mainPrice = `<span class="idm-products-banner__price-max">${escapeHtml(max)}</span>`;
}
const oldPrice = hasOmnibus
? `<span>${<iai:variable vid="Najniższa cena z 30 dni przed obniżką"/>}</span> <del>${escapeHtml(current || max)}</del>`
: "";
return `
<div class="idm-products-banner__product-prices">
<div class="idm-products-banner__product-price-container">
<div class="idm-products-banner__product-prices-box">
<strong class="idm-products-banner__price">${mainPrice}</strong>
<p class="idm-products-banner__price-omnibus">${oldPrice}</p>
</div>
</div>
</div>`;
}
// dodawanie do koszyka
function idmMarkupAddToBasket(product, size, options) {
if (!options?.addToBasket) return "";
const can = product?.type === "product" && product?.sizes?.length === 1 && size;
if (!can) return "";
const sellBy = size?.unitSellby || 1;
const precision = size?.unitPrecision || 0;
const max = (typeof size?.amount === "number" && size.amount > 0) ? size.amount : "";
return `
<div class="idm-products-banner__add-to-basket">
<form class="idm-products-banner__add-to-basket-form" action="/basketchange.php" method="post">
<input type="hidden" name="mode" value="1">
<input type="hidden" name="product" value="${escapeHtml(product.id)}">
<input type="hidden" name="size" value="${escapeHtml(size.id)}">
<div class="idm-products-banner__qty"
data-sell-by="${escapeHtml(String(sellBy))}"
data-precision="${escapeHtml(String(precision))}"
data-max="${escapeHtml(String(max))}">
<button type="button" class="idm-products-banner__qty-decrease"></button>
<input type="number"
name="number"
class="idm-products-banner__qty-input"
value="${escapeHtml(String(sellBy))}"
step="${escapeHtml(String(sellBy))}"
min="${escapeHtml(String(sellBy))}"
max="${escapeHtml(String(max))}">
<button type="button" class="idm-products-banner__qty-increase">+</button>
</div>
<button type="submit" class="btn --solid --medium idm-products-banner__add-to-basket-button">
<span>${<iai:variable vid="Do koszyka" />}</span>
</button>
</form>
</div>`;
}
// link więcej opcji
function idmMarkupMoreOptions(link) {
return `
<div class="idm-products-banner__add-to-basket">
<a class="btn --solid --medium idm-products-banner__add-to-basket-link" href="${escapeHtml(link)}">
${<iai:variable vid="Więcej opcji"/>}
</a>
</div>`;
}
// assembler produktu
function idmRenderProductCard(product, options = {}) {
const zone = product?.zones?.[0];
const size = product?.sizes?.[0];
const headIcons = `
${idmMarkupCompareBtn(product.id, options)}
${idmMarkupFavoritesIcon(product.id, size?.id, options)}
${idmMarkupZoneLabel(zone)}
`;
const addSection =
(options?.addToBasket && product?.type === "product" && product?.sizes?.length === 1 && size)
? idmMarkupAddToBasket(product, size, options)
: idmMarkupMoreOptions(product.link);
return `
<div class="idm-products-banner__product swiper-slide product">
<div class="idm-products-banner__product-img-container">
${headIcons}
${idmMarkupImage(product.link, product.icon)}
</div>
<div class="idm-products-banner__product-info">
${idmMarkupName(product.name, product.link)}
${idmMarkupPrices(product.price)}
${addSection}
</div>
</div>`;
}
// tworzenie, ustawienie opcji
function idmCreateProductMarkup(products, options = { compare: true, favorites: true, addToBasket: true }) {
return products.map(p => idmRenderProductCard(p, options)).join("");
}
async function idmRenderBannerProducts(container) {
const skeletons = document.querySelector(".idm-products-banner__skeletons");
if (!idmInteractiveBannerIds) return;
try {
container.innerHTML = "";
const response = await fetch("/graphql/v1/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: idmGetGraphQLQuery(idmInteractiveBannerIds),
});
const json = await response.json();
const productsData = json?.data?.products?.products;
console.log(productsData);
if (!productsData) return;
const sorted = idmInteractiveBannerIds
.map(id => productsData.find(p => p.id === id))
.filter(Boolean);
container.innerHTML = idmCreateProductMarkup(sorted);
idmInteractiveBannerSliderSwiper.init();
idmAttachFavoritesEvents();
// +/- i walidacja inputów ilości
document.addEventListener("click", (e) => {
const wrapper = e.target.closest(".idm-products-banner__qty");
if (!wrapper) return;
const input = wrapper.querySelector(".idm-products-banner__qty-input");
const step = parseFloat(wrapper.dataset.sellBy || "1");
const precision = parseInt(wrapper.dataset.precision || "0");
const max = parseFloat(wrapper.dataset.max || "999999");
let current = parseFloat(input.value) || 0;
if (e.target.classList.contains("idm-products-banner__qty-increase")) {
current += step;
if (current > max) current = max;
} else if (e.target.classList.contains("idm-products-banner__qty-decrease")) {
current -= step;
if (current < step) current = step;
}
input.value = current.toFixed(precision);
});
document.addEventListener("blur", (e) => {
if (!e.target.classList.contains("idm-products-banner__qty-input")) return;
const input = e.target;
const wrapper = input.closest(".idm-products-banner__qty");
const step = parseFloat(wrapper.dataset.sellBy || "1");
const precision = parseInt(wrapper.dataset.precision || "0");
const max = parseFloat(wrapper.dataset.max || "999999");
let val = parseFloat(input.value);
if (isNaN(val) || val < step) {
val = step;
} else if (val > max) {
val = max;
} else {
val = Math.round(val / step) * step;
}
input.value = val.toFixed(precision);
}, true);
// ukrycie skeletona
skeletons?.classList.add("idm_hidden");
container.closest('.idm-products-banner__products-container').classList.remove("idm_hidden");
// event porównania
document.addEventListener("click", idmHandleAddToCompare);
} catch (err) {
console.error("Błąd pobierania produktów:", err);
}
}
///////////////////////////////////////////////////////////
// slider i wyrównanie wysokości
///////////////////////////////////////////////////////////
const idmInteractiveBannerSliderSwiperOptions = {
loop: false,
autoHeight: false,
centeredSlides: false,
spaceBetween: 0,
simulateTouch: true,
cssMode: false,
slidesPerView: 2,
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
pagination: {
el: ".swiper-pagination",
clickable: true,
},
breakpoints: {
757: {
slidesPerView: 2,
autoHeight: true,
},
979: {
slidesPerView: 2,
},
},
};
const idmInteractiveBannerSliderSwiper = new HotspotSlider({
selector: ".idm-products-banner__products-container",
options: idmInteractiveBannerSliderSwiperOptions,
hotspotName: "idmInteractiveBannerSliderSwiper",
callbackAfter: () => {
console.log('juz')
app_shop.fn.setHeight({
selectors: [
".idm-products-banner .idm-products-banner__product-img-container",
".idm-products-banner .idm-products-banner__product-name",
".idm-products-banner .idm-products-banner__price",
".idm-products-banner .idm-products-banner__price-omnibus",
".idm-products-banner .idm-products-banner__add-to-basket",
".idm-products-banner .product"
],
container: ".idm-products-banner__products"
});
console.log('juz2')
}
});
///////////////////////////////////////////////////////////
// start działania
///////////////////////////////////////////////////////////
function idmWaitForBannerElements() {
let attempts = 0;
const interval = setInterval(() => {
let initialized = 0;
const bannerTitle = document.querySelector(".idm-products-banner__title");
if (bannerTitle) {
idmSetBannerTitle(bannerTitle);
initialized++;
}
const bannerText = document.querySelector(".idm-products-banner__text");
if (bannerText) {
idmSetBannerText(bannerText);
initialized++;
}
const bannerContainer = document.querySelector(".idm-products-banner__products");
if (bannerContainer) {
idmRenderBannerProducts(bannerContainer);
initialized++;
}
const bannerHeader = document.querySelector(".idm-products-banner__header");
if (bannerHeader) {
initialized++;
}
if (initialized >= 4) {
clearInterval(interval);
} else if (++attempts >= 10) {
clearInterval(interval);
console.warn("Niektóre wymagane elementy DOM nie zostały znalezione");
}
}, 500);
}
document.addEventListener("DOMContentLoaded", function () {
idmWaitForBannerElements();
});

305
swiper/src/style.less Normal file
View File

@@ -0,0 +1,305 @@
.idm-products-banner {
display: flex;
flex-direction: column;
margin: 3rem 0;
background: #eaebe9;
&__header {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 42rem;
background: #000;
}
&__title {
color: #fff;
font-size: 4rem;
}
&__text {
color: #fff;
font-size: 2rem;
}
&__products-container {
width: 100%;
&.idm_hidden {
display: none;
}
}
&__products {
width: 100%;
}
&__product {
padding: 1rem;
background: none;
text-align: center;
}
&__product-name-link {
text-decoration: none;
}
&__product-name {
color: #333;
margin: 1rem 0;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
&__price-omnibus {
font-size: 1.2rem;
margin: 1rem 0;
}
&__price-max {
color: #acacac;
margin-left: 1rem;
}
&__product-img-container {
position: relative;
}
&__products-img {
width: 100%;
}
.swiper-button-prev {
&::before {
content: "\f104";
font-family: "FONTAWESOME";
}
}
.swiper-button-next {
&::before {
content: "\f105";
font-family: "FONTAWESOME";
}
}
&__favorites-icon {
position: absolute;
top: 2rem;
right: 1rem;
z-index: 100;
cursor: pointer;
width: 3rem;
height: 3rem;
&:hover {
opacity: 0.6;
}
}
&__label-icons {
position: absolute;
bottom: 0;
left: 0;
text-align: left;
}
&__label {
padding: 0.4rem 0.8rem;
text-transform: uppercase;
background: #000;
color: #fff;
&--promo { }
&--new { }
&--bestseller { }
}
&__compare-btn {
position: absolute;
top: 2rem;
left: 2rem;
background: #fff;
&.--success {
svg {
display: none;
}
&::before {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='25' viewBox='0 0 25 25' fill='none'%3E%3Cpath d='M10.0516 18.5L4.35156 12.8L5.77656 11.375L10.0516 15.65L19.2266 6.475L20.6516 7.9L10.0516 18.5Z' fill='%23009263'/%3E%3C/svg%3E");
width: 3rem;
height: 3rem;
}
}
&.--loading:not(.--success) { }
&:not(.--success):hover {
opacity: 0.6;
}
}
&__compare-icon { }
&__add-to-basket {
&_btn {
background: #000;
color: #fff;
padding: 1rem 2rem;
width: 100%;
border-radius: 0.6rem;
margin-top: 1rem;
text-transform: uppercase;
}
}
&__skeletons {
width: 100%;
display: flex;
@media (min-width: 757px) {
width: 50%;
}
&.idm_hidden {
display: none;
}
.idm-products-banner__product.skeleton {
width: 50%;
}
}
&__skeleton-img {
width: 100%;
background: #ddd;
aspect-ratio: 1;
}
&__skeleton-text {
&--name {
width: 100%;
height: 2rem;
background: #ddd;
margin-top: 2rem;
}
&--price {
width: 50%;
height: 2rem;
background: #ddd;
margin: 2rem auto;
}
}
@keyframes skeletonPulse {
0% { background-color: #ddd; }
50% { background-color: #eaeaea; }
100% { background-color: #ddd; }
}
&__skeleton-img,
&__skeleton-text {
animation: skeletonPulse 1.5s ease-in-out infinite;
}
&__product-prices { }
&__product-price-container { }
&__product-prices-box {
color: #333;
}
&__price { }
&__qty {
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
gap: 1rem;
}
&__qty-input {
height: 3rem;
text-align: center;
border: 1px solid #ccc;
width: 60%;
max-width: unset;
min-width: unset;
}
&__qty button {
background: #000;
height: 3rem;
width: 3rem;
color: #fff;
border-radius: 0.5rem;
min-width: 3rem;
}
&__add-to-basket-form {
display: flex;
flex-direction: column;
gap: 2rem;
width: 100%;
}
.btn.--solid.--medium.idm-products-banner__add-to-basket-button {
height: 4rem;
background: #000;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #000;
}
.btn.--solid.--medium.idm-products-banner__add-to-basket-link {
width: 100%;
height: 4rem;
display: flex;
align-items: center;
justify-content: center;
background: #000;
border: 1px solid #000;
margin-top: auto;
}
&__add-to-basket {
display: flex;
align-items: end;
flex-direction: column;
width: 80%;
margin: 0 auto;
}
@media (min-width: 757px) {
flex-direction: row;
align-items: center;
&__header {
width: 50%;
}
&__title {
font-size: 5rem;
}
&__products-container {
width: 50%;
}
&__product {
&-img_container { }
}
}
&__qty-input {
height: 4rem;
}
&__qty button {
height: 4rem;
width: 4rem;
min-width: 4rem;
}
}