PRODUCTS

Stones

'; } } } function buildCategories(items) { const categoriesMap = new Map(); items.forEach(function (item) { // Normalizando os nomes vindos do backend: const catId = item.CategoryID; const catName = item.CategoryName || item.categoryName; // fallback caso venha minúsculo if (catId && catName) { if (!categoriesMap.has(catId)) { categoriesMap.set(catId, { id: catId, name: catName, count: 0 }); } categoriesMap.get(catId).count++; } }); const categories = Array.from(categoriesMap.values()) .sort((a, b) => String(a.name).localeCompare(String(b.name))); categories.unshift({ id: null, name: "All Categories", count: items.length }); const filterList = $("filter-list"); if (!filterList) return; filterList.innerHTML = ""; categories.forEach(function (cat) { const filterDiv = document.createElement("div"); filterDiv.className = "filter-item" + (cat.id === null ? " active" : ""); filterDiv.dataset.categoryId = cat.id; const nameDiv = document.createElement("div"); nameDiv.className = "filter-item-name"; nameDiv.textContent = cat.name; const countDiv = document.createElement("div"); countDiv.className = "filter-item-count"; countDiv.textContent = cat.count + " item" + (cat.count !== 1 ? "s" : ""); filterDiv.appendChild(nameDiv); filterDiv.appendChild(countDiv); filterDiv.addEventListener("click", function () { document.querySelectorAll(".filter-item").forEach(f => f.classList.remove("active")); filterDiv.classList.add("active"); activeFilter = cat.id; // null = todos renderGallery(); }); filterList.appendChild(filterDiv); }); } function bindSearch() { const input = $("gallerySearch"); if (!input) return; input.addEventListener("input", function () { searchText = (this.value || "").trim().toLowerCase(); renderGallery(); }); } function passesFilters(item) { // Categoria if (activeFilter !== null && item.CategoryID !== activeFilter) return false; // Busca por nome (ItemName) if (searchText) { const name = (item.ItemName || "").toLowerCase(); if (!name.includes(searchText)) return false; } return true; } function renderGallery() { const container = $("gallery"); if (!container) return; container.innerHTML = ""; let count = 0; data.forEach(function (item) { if (!passesFilters(item)) return; count++; const div = document.createElement("div"); div.className = "gallery-item"; div.addEventListener("click", function () { window.openProductModal(item.ItemID); }); if (item.Filename && String(item.Filename).trim() !== "") { const wrapper = document.createElement("div"); wrapper.className = "gallery-image-wrapper"; const img = document.createElement("img"); img.src = S3_BASE + item.Filename + "?width=500"; img.alt = item.ItemName || ""; img.className = "gallery-image"; wrapper.appendChild(img); div.appendChild(wrapper); } else { const placeholder = document.createElement("div"); placeholder.className = "gallery-placeholder"; placeholder.textContent = "Image Coming Soon"; div.appendChild(placeholder); } const info = document.createElement("div"); info.className = "gallery-info"; const name = document.createElement("p"); name.className = "gallery-name"; name.textContent = item.ItemName || ""; info.appendChild(name); const sub = document.createElement("p"); sub.className = "gallery-sub"; sub.textContent = item.CategoryName || item.categoryName || ""; info.appendChild(sub); div.appendChild(info); container.appendChild(div); }); if (count === 0) { container.innerHTML = ''; } } // Expondo no window porque você chama do HTML onclick e também do addEventListener window.openProductModal = async function (itemId) { const modal = $("productModal"); const modalBody = $("modalBody"); const modalTitle = $("modalTitle"); if (!modal || !modalBody || !modalTitle) return; modal.classList.add("active"); modalTitle.textContent = "Loading..."; modalBody.innerHTML = ""; const loading = document.createElement("p"); loading.style.textAlign = "center"; loading.style.padding = "40px"; loading.style.gridColumn = "1 / -1"; loading.textContent = "Loading product details..."; modalBody.appendChild(loading); try { const response = await fetch(API_DETAILS + encodeURIComponent(itemId)); const result = await response.json(); const product = Array.isArray(result) && result.length > 0 ? result[0] : null; modalTitle.textContent = (product && (product.Name || product.ItemName)) ? (product.Name || product.ItemName) : "Product Details"; modalBody.innerHTML = ""; // Image if (product && product.FileName && String(product.FileName).trim() !== "") { const img = document.createElement("img"); img.src = S3_BASE + product.FileName + "?width=800"; img.alt = product.ItemName || product.Name || ""; img.className = "modal-image"; modalBody.appendChild(img); } else { const placeholder = document.createElement("div"); placeholder.className = "gallery-placeholder"; placeholder.style.minHeight = "400px"; placeholder.textContent = "Image Coming Soon"; modalBody.appendChild(placeholder); } // Details container const detailsDiv = document.createElement("div"); detailsDiv.className = "modal-details"; const infoGrid = document.createElement("div"); infoGrid.className = "modal-info-grid"; function addInfoRow(label, value) { // aceita string vazia? não. se quiser mostrar mesmo vazio, remova esse if: if (value === undefined || value === null || String(value).trim() === "") return; const row = document.createElement("div"); row.className = "modal-info-row"; const labelDiv = document.createElement("div"); labelDiv.className = "modal-info-label"; labelDiv.textContent = label; const valueDiv = document.createElement("div"); valueDiv.className = "modal-info-value"; valueDiv.textContent = value; row.appendChild(labelDiv); row.appendChild(valueDiv); infoGrid.appendChild(row); } if (product) { addInfoRow("TYPE", product.ProductFormValue); addInfoRow("CATEGORY", product.ProductSubCategory); addInfoRow("THICKNESS", product.ProductThickness); addInfoRow("COLOR", product.ProductColor); addInfoRow("GROUP", product.ProductGroup); addInfoRow("FINISH", product.Finish); } detailsDiv.appendChild(infoGrid); modalBody.appendChild(detailsDiv); } catch (err) { console.error("Erro ao buscar detalhes do produto:", err); modalTitle.textContent = "Error"; modalBody.innerHTML = '

Error loading product details

'; } }; window.closeModal = function () { const modal = $("productModal"); if (modal) modal.classList.remove("active"); }; // Eventos do modal (clique fora + ESC) document.addEventListener("click", function (e) { const modal = $("productModal"); if (!modal) return; if (e.target === modal) window.closeModal(); }); document.addEventListener("keydown", function (e) { if (e.key === "Escape") window.closeModal(); }); init(); })();