index-shop/assets/js/product-loader.js

228 lines
7.3 KiB
JavaScript
Raw Normal View History

(async function () {
const container = document.querySelector("[data-product-loader]");
if (!container) return;
const handle = container.dataset.shopifyHandle;
const language = container.dataset.language || 'fr';
const isEnglish = language === 'en';
const loadingState = container.querySelector(".product-loading");
const contentState = container.querySelector(".product-content");
const errorState = container.querySelector(".product-error");
try {
const cart = new ShopifyCart({
domain: "nv7cqv-bu.myshopify.com",
storefrontAccessToken: "dec3d35a2554384d149c72927d1cfd1b",
});
const product = await cart.getProductByHandle(handle);
if (!product) {
throw new Error("Product not found");
}
renderProduct(product, isEnglish);
loadingState.style.display = "none";
contentState.removeAttribute("style");
setTimeout(() => {
if (typeof Swiper !== "undefined" && product.images.edges.length > 0) {
new Swiper(".product-gallery", {
loop: product.images.edges.length > 1,
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
pagination: {
el: ".swiper-pagination",
clickable: true,
},
keyboard: {
enabled: true,
},
});
}
}, 100);
} catch (error) {
console.error("Error loading product:", error);
loadingState.style.display = "none";
errorState.style.display = "block";
}
function renderProduct(product, isEnglish) {
renderTitle(product, isEnglish);
renderPrice(product);
renderDetails(product, isEnglish);
renderImages(product, isEnglish);
renderOptions(product);
setupAddToCart(product);
}
function renderTitle(product, isEnglish) {
const titleEl = document.querySelector("[data-product-title]");
if (titleEl) {
const title = isEnglish && product.titleEn?.value
? product.titleEn.value
: product.title;
titleEl.textContent = title;
}
}
function renderPrice(product) {
const priceEl = document.querySelector("[data-product-price]");
if (priceEl) {
const price = parseFloat(product.priceRange.minVariantPrice.amount);
priceEl.textContent = price.toFixed(2) + "€";
}
}
function renderDetails(product, isEnglish) {
const detailsEl = document.querySelector("[data-product-details]");
if (detailsEl) {
const description = isEnglish && product.descriptionEn?.value
? product.descriptionEn.value
: product.descriptionHtml || "";
detailsEl.innerHTML = description;
}
}
function renderImages(product, isEnglish) {
const imagesContainer = document.querySelector("[data-product-images]");
if (imagesContainer && product.images.edges.length > 0) {
const productTitle = isEnglish && product.titleEn?.value
? product.titleEn.value
: product.title;
imagesContainer.innerHTML = product.images.edges
.map((edge) => {
const img = edge.node;
return `
<div class="swiper-slide">
<figure>
<img src="${img.url}"
alt="${img.altText || productTitle}"
loading="lazy" />
</figure>
</div>
`;
})
.join("");
}
}
function renderOptions(product) {
if (product.variants.edges.length <= 1) return;
const firstVariant = product.variants.edges[0].node;
if (!firstVariant.selectedOptions || firstVariant.selectedOptions.length === 0) return;
const mainOption = firstVariant.selectedOptions[0];
const optionValues = new Set();
product.variants.edges.forEach(edge => {
const variant = edge.node;
if (variant.selectedOptions && variant.selectedOptions[0]) {
optionValues.add(variant.selectedOptions[0].value);
}
});
if (optionValues.size <= 1) return;
const optionsContainer = document.querySelector("[data-product-options]");
const optionsList = document.querySelector("[data-product-options-list]");
if (!optionsContainer || !optionsList) return;
const optionName = mainOption.name;
const optionSlug = optionName.toLowerCase().replace(/\s+/g, '-');
optionsList.innerHTML = Array.from(optionValues).map((value) => {
const uniqueId = `${optionSlug}-${value.toLowerCase().replace(/\s+/g, '-')}`;
const variant = product.variants.edges.find(e =>
e.node.selectedOptions && e.node.selectedOptions[0]?.value === value
)?.node;
const isAvailable = variant?.availableForSale || false;
return `
<li>
<input
type="radio"
id="${uniqueId}"
name="${optionSlug}"
value="${value}"
data-variant-id="${variant ? variant.id.replace('gid://shopify/ProductVariant/', '') : ''}"
${!isAvailable ? 'disabled' : ''}
/>
<label for="${uniqueId}">${value}</label>
</li>
`;
}).join('');
optionsContainer.style.display = 'block';
const radios = optionsList.querySelectorAll('input[type="radio"]');
const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]");
const buttonText = addToCartBtn?.querySelector('[data-button-text]');
radios.forEach(radio => {
radio.addEventListener('change', function() {
const variantId = this.dataset.variantId;
if (addToCartBtn) {
addToCartBtn.dataset.variantId = variantId;
addToCartBtn.removeAttribute('disabled');
}
if (buttonText) {
buttonText.textContent = addToCartBtn.dataset.defaultText || 'Ajouter au panier';
}
const allLi = optionsList.querySelectorAll('li');
allLi.forEach(li => li.classList.remove('is-selected'));
this.closest('li').classList.add('is-selected');
});
});
}
function setupAddToCart(product) {
const addToCartBtn = document.querySelector("[data-shopify-add-to-cart]");
if (!addToCartBtn) return;
const productId = product.id.replace("gid://shopify/Product/", "");
addToCartBtn.dataset.productId = productId;
const hasMultipleVariants = product.variants.edges.length > 1;
const firstVariant = product.variants.edges[0]?.node;
const hasOptions = firstVariant?.selectedOptions && firstVariant.selectedOptions.length > 0;
const uniqueOptions = new Set();
product.variants.edges.forEach(edge => {
if (edge.node.selectedOptions && edge.node.selectedOptions[0]) {
uniqueOptions.add(edge.node.selectedOptions[0].value);
}
});
const hasMultipleOptions = uniqueOptions.size > 1;
if (hasMultipleVariants && hasOptions && hasMultipleOptions) {
addToCartBtn.setAttribute('disabled', 'disabled');
const buttonText = addToCartBtn.querySelector('[data-button-text]');
if (buttonText) {
buttonText.textContent = addToCartBtn.dataset.textChooseOption || 'Choisissez une option';
}
} else {
const firstAvailableVariant = product.variants.edges.find(
(e) => e.node.availableForSale
);
if (firstAvailableVariant) {
const variantId = firstAvailableVariant.node.id.replace(
"gid://shopify/ProductVariant/",
""
);
addToCartBtn.dataset.variantId = variantId;
}
}
}
})();