let allProducts = []; // Holds all products fetched let filteredProducts = []; // Holds the filtered subset for display let currentPage = 1; const productsPerPage = 20; // Fetch products and initialize filters async function fetchProducts() { let hasNextPage = true; let cursor = null; const pageSize = 50; const totalProducts = 200; let fetchedProducts = 0; while (hasNextPage && fetchedProducts < totalProducts) { const query = ` query MyQuery($pageSize: Int = ${pageSize}, $cursor: String) { site { newestProducts(first: $pageSize, after: $cursor, hideOutOfStock: false) { edges { node { description sku name entityId categories { edges { node { name id entityId } } } brand { name id entityId } prices { price { value } } } } pageInfo { hasNextPage endCursor } } } } `; const variables = { pageSize, cursor }; const res = await fetch('/graphql', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjaWQiOlsxXSwiY29ycyI6WyJodHRwczovL3d3dy5tYy1wb3dlcnNwb3J0cy5jb20iXSwiZWF0IjoxNzM0Nzg1NTgxLCJpYXQiOjE3MzQ2MTI3ODEsImlzcyI6IkJDIiwic2lkIjo5ODYyNzksInN1YiI6IkJDIiwic3ViX3R5cGUiOjAsInRva2VuX3R5cGUiOjF9._X6YoBnvgI229Pj9lngwVrMNSO425Z7QpHtkHp3PmVrOBoRZsvcs48V6EKWWX1O-j5yHiKJSl8zHXUCkxAra_g', }, body: JSON.stringify({ query, variables }), }); const data = await res.json(); console.log(data); const products = data.data.site.newestProducts.edges; const pageInfo = data.data.site.newestProducts.pageInfo; allProducts.push(...products.map(product => product.node)); cursor = pageInfo.endCursor; hasNextPage = pageInfo.hasNextPage; fetchedProducts += products.length; console.log(`Fetched ${fetchedProducts} products so far...`); } filteredProducts = [...allProducts]; // Initialize filteredProducts initializeFilters(); renderProducts(); } // Initialize filters (brand, category, price range) function initializeFilters() { populateFilterCheckboxes(); initializePriceFilter(); } // Populate brand and category checkboxes function populateFilterCheckboxes() { const brands = new Set(allProducts.map(product => product.brand.name)); const categories = new Set(allProducts.flatMap(product => product.categories.edges.map(cat => cat.node.name))); const brandCheckboxes = document.getElementById('brand-checkboxes'); const categoryCheckboxes = document.getElementById('category-checkboxes'); // Populate brands brands.forEach(brand => { const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.value = brand; checkbox.id = `brand-${brand}`; checkbox.addEventListener('change', applyFilters); const label = document.createElement('label'); label.htmlFor = `brand-${brand}`; label.textContent = brand; brandCheckboxes.appendChild(checkbox); brandCheckboxes.appendChild(label); }); // Populate categories categories.forEach(category => { const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.value = category; checkbox.id = `category-${category}`; checkbox.addEventListener('change', applyFilters); const label = document.createElement('label'); label.htmlFor = `category-${category}`; label.textContent = category; categoryCheckboxes.appendChild(checkbox); categoryCheckboxes.appendChild(label); }); } // Initialize price range filter function initializePriceFilter() { const maxPrice = Math.max(...allProducts.map(product => product.prices.price.value)); const priceSlider = document.getElementById('price-slider'); const maxPriceLabel = document.getElementById('max-price'); priceSlider.max = maxPrice; priceSlider.value = maxPrice; maxPriceLabel.textContent = maxPrice; priceSlider.addEventListener('input', applyFilters); } // Apply filters (brand, category, price) function applyFilters() { const selectedBrands = Array.from(document.querySelectorAll('#brand-checkboxes input:checked')).map(input => input.value); const selectedCategories = Array.from(document.querySelectorAll('#category-checkboxes input:checked')).map(input => input.value); const maxPrice = parseFloat(document.getElementById('price-slider').value); filteredProducts = allProducts.filter(product => { const matchesBrand = selectedBrands.length === 0 || selectedBrands.includes(product.brand.name); const matchesCategory = selectedCategories.length === 0 || product.categories.edges.some(cat => selectedCategories.includes(cat.node.name)); const matchesPrice = product.prices.price.value <= maxPrice; return matchesBrand && matchesCategory && matchesPrice; }); currentPage = 1; // Reset to the first page renderProducts(); } // Render products with pagination function renderProducts() { const productList = document.getElementById('product-list'); productList.innerHTML = ''; const startIndex = (currentPage - 1) * productsPerPage; const endIndex = startIndex + productsPerPage; const productsToRender = filteredProducts.slice(startIndex, endIndex); productsToRender.forEach(product => { const li = document.createElement('li'); li.className = 'product-item'; li.setAttribute('data-brand', product.brand.name); li.setAttribute('data-category', product.categories.edges.map(cat => cat.node.name).join(', ')); li.setAttribute('data-price', product.prices.price.value); li.setAttribute('data-currency', product.prices.price.currencyCode); li.innerHTML = ` ${product.name}
${product.name}
Brand: ${product.brand.name}
Categories: ${product.categories.edges.map(cat => cat.node.name).join(', ')}
Price: ${product.prices.price.value} ${product.prices.price.currencyCode} `; productList.appendChild(li); }); renderPagination(); } // Render pagination controls function renderPagination() { const paginationContainer = document.getElementById('pagination'); paginationContainer.innerHTML = ''; const totalPages = Math.ceil(filteredProducts.length / productsPerPage); for (let i = 1; i <= totalPages; i++) { const button = document.createElement('button'); button.textContent = i; button.className = i === currentPage ? 'active' : ''; button.addEventListener('click', () => { currentPage = i; renderProducts(); }); paginationContainer.appendChild(button); } } // Fetch products on page load fetchProducts();