// ======================================== // CATALOG.JS — Filter, Sort, Search, Paginate // ======================================== const ITEMS_PER_PAGE = 12; let currentFilters = { category: null, sizes: [], colors: [], minPrice: undefined, maxPrice: undefined, hasDiscount: false }; let currentSort = 'default'; let currentPage = 1; let currentView = 'grid'; document.addEventListener('DOMContentLoaded', () => { parseURLParams(); buildFilterUI(); applyAndRender(); setupEventListeners(); setupMobileFilter(); }); function parseURLParams() { const params = new URLSearchParams(window.location.search); if (params.get('category')) currentFilters.category = params.get('category'); if (params.get('search')) { const si = document.getElementById('searchInput'); if (si) si.value = params.get('search'); } if (params.get('filter') === 'discount') currentFilters.hasDiscount = true; if (params.get('filter') === 'new') currentSort = 'newest'; if (params.get('sort')) currentSort = params.get('sort'); // Update page title if (currentFilters.category && CATEGORIES[currentFilters.category]) { document.getElementById('catalogTitle').textContent = CATEGORIES[currentFilters.category].name; document.getElementById('catalogSubtitle').textContent = `${CATEGORIES[currentFilters.category].icon} ${CATEGORIES[currentFilters.category].name} kategoriyasidagi mahsulotlar`; } } function buildFilterUI() { // Categories const catContainer = document.getElementById('filterCategory'); catContainer.innerHTML = `
Barchasi
`; Object.entries(CATEGORIES).forEach(([slug, cat]) => { const count = getProductsByCategory(slug).length; catContainer.innerHTML += `
${cat.icon} ${cat.name} (${count})
`; }); catContainer.querySelectorAll('.filter-option').forEach(el => { el.addEventListener('click', () => { catContainer.querySelectorAll('.filter-option').forEach(e => e.classList.remove('active')); el.classList.add('active'); currentFilters.category = el.dataset.cat || null; currentPage = 1; applyAndRender(); }); }); // Sizes const sizeContainer = document.getElementById('filterSizes'); SIZES.forEach(size => { const btn = document.createElement('button'); btn.className = 'size-btn'; btn.textContent = size; btn.addEventListener('click', () => { btn.classList.toggle('active'); if (btn.classList.contains('active')) currentFilters.sizes.push(size); else currentFilters.sizes = currentFilters.sizes.filter(s => s !== size); currentPage = 1; applyAndRender(); }); sizeContainer.appendChild(btn); }); // Colors const colorContainer = document.getElementById('filterColors'); Object.entries(COLORS_MAP).forEach(([key, val]) => { const btn = document.createElement('button'); btn.className = 'color-btn'; btn.style.background = val.hex; btn.title = val.name; btn.addEventListener('click', () => { btn.classList.toggle('active'); if (btn.classList.contains('active')) currentFilters.colors.push(key); else currentFilters.colors = currentFilters.colors.filter(c => c !== key); currentPage = 1; applyAndRender(); }); colorContainer.appendChild(btn); }); // Discount toggle const discEl = document.getElementById('filterDiscount'); if (currentFilters.hasDiscount) discEl.classList.add('active'); discEl.addEventListener('click', () => { discEl.classList.toggle('active'); currentFilters.hasDiscount = discEl.classList.contains('active'); currentPage = 1; applyAndRender(); }); } function setupEventListeners() { // Sort document.getElementById('sortSelect').addEventListener('change', (e) => { currentSort = e.target.value; applyAndRender(); }); // Price filter document.getElementById('applyPrice').addEventListener('click', () => { const min = document.getElementById('priceMin').value; const max = document.getElementById('priceMax').value; currentFilters.minPrice = min ? parseInt(min) : undefined; currentFilters.maxPrice = max ? parseInt(max) : undefined; currentPage = 1; applyAndRender(); }); // Clear filters document.getElementById('clearFilters').addEventListener('click', clearAllFilters); // View toggle document.getElementById('gridViewBtn')?.addEventListener('click', () => { setView('grid'); }); document.getElementById('listViewBtn')?.addEventListener('click', () => { setView('list'); }); // Navbar search const si = document.getElementById('searchInput'); if (si) { si.addEventListener('input', debounce(() => { currentPage = 1; applyAndRender(); }, 300)); } } function setupMobileFilter() { const mobileBtn = document.getElementById('mobileFilterBtn'); const sidebar = document.getElementById('filterSidebar'); const overlay = document.getElementById('filterOverlay'); if (window.innerWidth <= 768) mobileBtn.style.display = 'inline-flex'; window.addEventListener('resize', () => { mobileBtn.style.display = window.innerWidth <= 768 ? 'inline-flex' : 'none'; }); mobileBtn?.addEventListener('click', () => { sidebar.classList.add('active'); overlay.classList.add('active'); }); overlay?.addEventListener('click', () => { sidebar.classList.remove('active'); overlay.classList.remove('active'); }); } function setView(view) { currentView = view; const grid = document.getElementById('productsGrid'); grid.classList.toggle('list-view', view === 'list'); document.getElementById('gridViewBtn')?.classList.toggle('active', view === 'grid'); document.getElementById('listViewBtn')?.classList.toggle('active', view === 'list'); } function clearAllFilters() { currentFilters = { category: null, sizes: [], colors: [], minPrice: undefined, maxPrice: undefined, hasDiscount: false }; currentSort = 'default'; currentPage = 1; document.getElementById('priceMin').value = ''; document.getElementById('priceMax').value = ''; document.getElementById('sortSelect').value = 'default'; document.querySelectorAll('.filter-option.active, .size-btn.active, .color-btn.active').forEach(el => el.classList.remove('active')); document.querySelector('[data-cat=""]')?.classList.add('active'); const si = document.getElementById('searchInput'); if (si) si.value = ''; applyAndRender(); } function applyAndRender() { let products = [...PRODUCTS]; // Search const query = document.getElementById('searchInput')?.value?.trim(); if (query) products = searchProducts(query); // Filter products = filterProducts(products, currentFilters); // Sort products = sortProducts(products, currentSort); // Update count document.getElementById('productCount').textContent = `${products.length} ta mahsulot`; // Pagination const totalPages = Math.ceil(products.length / ITEMS_PER_PAGE); const start = (currentPage - 1) * ITEMS_PER_PAGE; const pageProducts = products.slice(start, start + ITEMS_PER_PAGE); // Render products const grid = document.getElementById('productsGrid'); const noResults = document.getElementById('noResults'); grid.innerHTML = ''; if (pageProducts.length === 0) { grid.style.display = 'none'; noResults.style.display = 'block'; } else { grid.style.display = ''; noResults.style.display = 'none'; pageProducts.forEach(p => grid.appendChild(renderProductCard(p))); } renderPagination(totalPages); } function renderPagination(totalPages) { const container = document.getElementById('pagination'); container.innerHTML = ''; if (totalPages <= 1) return; for (let i = 1; i <= totalPages; i++) { const btn = document.createElement('button'); btn.className = `btn btn-sm ${i === currentPage ? 'btn-primary' : 'btn-outline'}`; btn.textContent = i; btn.addEventListener('click', () => { currentPage = i; applyAndRender(); window.scrollTo({ top: 0, behavior: 'smooth' }); }); container.appendChild(btn); } } function debounce(fn, ms) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; }