/* Optimized Sliders TALLAS - Uses new backend structure */ const productCombinationsCache = {}; // Fetch product combinations using the new backend structure async function fetchAndCacheProductCombinations(productId, shopId) { try { let url = `/index.php?fc=module&module=productcombinationsfetch&controller=fetchCombinations&product_id=${productId}`; if (shopId) url += `&shop_id=${shopId}`; const response = await fetch(url); const data = await response.json(); if (data.success) { // Cache the entire product object productCombinationsCache[productId] = data.productCombinations; return data.productCombinations; } else { throw new Error(data.error); } } catch (err) { console.error('Fetch failed:', err); return null; } } // Render combinations for a product // Render combinations for a product function displayProductCombinations(productId, productElement) { const productData = productCombinationsCache[productId]; if (!productData || !productData.combinations) return; // Hide selector if only one size if (productData.isSingleSize) { // Get the only combination's label const onlyCombo = productData.combinations[0]; const attributes = onlyCombo.attributes_values; const sizeLabel = attributes['US / LAM Talla'] || attributes['US / EU Talla'] || attributes['US / LAM Size'] || attributes['US / EU Size'] || attributes['US / EU sizes kids'] || attributes['US / EU Talla Kids'] || Object.values(attributes)[0]; // Check if the label is a number or contains a number const isNumeric = /^\d+([.,]\d+)?$/.test(sizeLabel.trim()); // List of words that mean "unique size" const uniqueWords = ['Ășnica', 'unico', 'unique', 'one size', 'talla Ășnica', 'talla unica']; const isUnique = uniqueWords.some(word => sizeLabel.trim().toLowerCase().includes(word)); if (isUnique || !isNumeric) { // Hide if it's a unique size or not a number const container = productElement.querySelector('.product-combinations'); if (container) container.classList.add('acccesorios'); return; } // Otherwise, let it show as a normal size } // Remove previous combinations if any let productContainer = productElement.querySelector('.product-combinations'); if (productContainer) productContainer.remove(); productContainer = document.createElement('div'); productContainer.classList.add('product-combinations'); productContainer.style.display = 'block'; const title = document.createElement('span'); title.classList.add('combinations-title'); title.innerText = 'Talla'; const sizesContainer = document.createElement('div'); sizesContainer.classList.add('sizes_container'); const carousel = document.createElement('div'); carousel.classList.add('carousel-items', 'owl-carousel'); carousel.id = `carousel-items-${productId}`; // Render each combination productData.combinations.forEach(({ id_product_attribute, attributes_values }) => { // Find the size label (pick the first matching group) const sizeLabel = attributes_values['US / LAM Talla'] || attributes_values['US / EU Talla'] || attributes_values['US / LAM Size'] || attributes_values['US / EU Size'] || attributes_values['US / EU sizes kids'] || attributes_values['US / EU Talla Kids'] || Object.values(attributes_values)[0]; const carouselItem = document.createElement('div'); carouselItem.classList.add('carousel-item'); carouselItem.setAttribute('data-id-product-attribute', id_product_attribute); if (id_product_attribute == productData.defaultSizeId) { carouselItem.classList.add('selected'); } const itemValue = document.createElement('p'); itemValue.classList.add('item-value'); itemValue.innerText = sizeLabel.split("/")[1]; carouselItem.appendChild(itemValue); carousel.appendChild(carouselItem); }); sizesContainer.appendChild(carousel); productContainer.appendChild(title); productContainer.appendChild(sizesContainer); productElement.querySelector('.thumbnail-container').appendChild(productContainer); document.querySelectorAll(`#carousel-items-${productId}`).forEach(carouselEl => { initializeOwlCarousel(carouselEl); }); setupCarouselListeners(); } // Example: Render all visible products (call after DOM ready) async function renderProductCombinations(shopId = null) { const productElements = document.querySelectorAll('article[data-id-product]'); for (const productElement of productElements) { const productId = productElement.getAttribute('data-id-product'); if (!productCombinationsCache[productId]) { await fetchAndCacheProductCombinations(productId, shopId); } displayProductCombinations(productId, productElement); } } // Carousel and listeners (reuse your existing logic) function initializeOwlCarousel(selector) { $(selector).owlCarousel({ items: 4, loop: 0, margin: 5, nav: true, dots: false, responsive: { 0: { items: 3, margin: 5 }, 600: { items: 4 }, 1000: { items: 4, mouseDrag: false }, }, }); } function setupCarouselListeners() { document.querySelectorAll('.carousel-item').forEach(item => { item.addEventListener('click', onCarouselItemClick); }); } function onCarouselItemClick(event) { const selectedAttributeId = event.target.getAttribute('data-id-product-attribute'); const productId = event.target.closest('.owl-carousel').id.split('-')[2]; const form = document.querySelector(`article[data-id-product="${productId}"] .product-add-cart form`); if (form) { let existingInput = form.querySelector('input[name="id_product_attribute"]'); if (existingInput) form.removeChild(existingInput); const newInput = document.createElement('input'); newInput.type = 'hidden'; newInput.name = 'id_product_attribute'; newInput.value = selectedAttributeId; form.appendChild(newInput); const url = new URL(form.action); url.searchParams.set('id_product_attribute', selectedAttributeId); form.action = url.toString(); } // Highlight selection const carouselItems = event.target.closest('.owl-carousel').querySelectorAll('.carousel-item'); carouselItems.forEach(item => item.classList.remove('selected')); event.target.classList.add('selected'); } function qtyFromZeroToOne() { const inputs_qty = document.querySelectorAll( ".product-add-cart .input-qty" ); if (!inputs_qty) return; inputs_qty.forEach((input) => { input.value = "1"; }); } // On DOM ready // Retry logic for rendering product combinations function attemptRenderProductCombinations(retries = 3, delay = 1200) { renderProductCombinations().then(() => { // Check if any products were rendered (e.g., .product-combinations exists) const found = document.querySelectorAll('.product-combinations').length > 0; if (found || retries <= 1) { qtyFromZeroToOne(); setupPaginationListeners(); if (!found) { console.warn('No products rendered after retries.'); } } else { setTimeout(() => attemptRenderProductCombinations(retries - 1, delay), delay); } }); } document.addEventListener('DOMContentLoaded', () => { attemptRenderProductCombinations(); }); // Set up pagination listeners function setupPaginationListeners() { document.querySelectorAll("nav.pagination .js-search-link").forEach((link) => { if (link.classList.contains("added_sizes")) return; link.addEventListener("click", (event) => { event.preventDefault(); setTimeout(() => { setupPaginationListeners(); }, 1300); }); link.classList.add("added_sizes"); }); } function setupViewSwitcherListeners() { const viewSwitcherLinks = document.querySelectorAll('.view-switcher .js-search-link'); viewSwitcherLinks.forEach(link => { // Remove existing listeners to prevent duplicates link.removeEventListener('click', handleViewSwitch); link.addEventListener('click', handleViewSwitch); }); } function handleViewSwitch(e) { e.preventDefault(); console.log('View switcher click detected'); setTimeout(() => { renderProductCombinations(1); setupViewSwitcherListeners(); // Reattach listeners }, 200); } // Initial setup document.addEventListener('DOMContentLoaded', setupViewSwitcherListeners); // Handle AJAX updates if (typeof prestashop !== 'undefined') { prestashop.on('updateProductList', function () { setTimeout(() => { setupViewSwitcherListeners(); renderProductCombinations(1); // Also update combinations after filter changes }, 300); }); } // Monitor URL changes for filter updates let lastUrl = location.href; new MutationObserver(() => { if (location.href !== lastUrl && location.href.includes('facet_style=dropdown')) { lastUrl = location.href; setTimeout(setupViewSwitcherListeners, 400); } }).observe(document, { subtree: true, childList: true });