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}
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();