Spaces:
Sleeping
Sleeping
| // ======================================== | |
| // 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 = `<div class="filter-option ${!currentFilters.category ? 'active' : ''}" data-cat=""> | |
| <div class="filter-checkbox"></div><span>Barchasi</span> | |
| </div>`; | |
| Object.entries(CATEGORIES).forEach(([slug, cat]) => { | |
| const count = getProductsByCategory(slug).length; | |
| catContainer.innerHTML += `<div class="filter-option ${currentFilters.category === slug ? 'active' : ''}" data-cat="${slug}"> | |
| <div class="filter-checkbox"></div><span>${cat.icon} ${cat.name} (${count})</span> | |
| </div>`; | |
| }); | |
| 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); }; | |
| } | |