модерн

This commit is contained in:
2025-11-25 01:14:38 +03:00
parent b9e02af74a
commit 0f212bda69
2 changed files with 108 additions and 11 deletions

View File

@@ -55,6 +55,108 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
} }
// ========================================
// Фильтрация по категории
// ========================================
let selectedCategoryId = null;
// Добавляем обработчик клика на категорию для фильтрации
document.querySelectorAll('.category-header').forEach(header => {
header.addEventListener('click', function(e) {
// Игнорируем клики на кнопки управления и toggle
if (e.target.classList.contains('category-rename-btn') ||
e.target.classList.contains('category-add-child-btn') ||
e.target.classList.contains('category-name-input') ||
e.target.classList.contains('category-toggle') ||
e.target.closest('.category-toggle')) {
return;
}
const categoryNode = this.closest('.category-node');
const categoryId = categoryNode.dataset.categoryId;
// Toggle selection
if (selectedCategoryId === categoryId) {
// Deselect - show all
selectedCategoryId = null;
document.querySelectorAll('.category-header').forEach(h => h.classList.remove('active'));
} else {
// Select this category
selectedCategoryId = categoryId;
document.querySelectorAll('.category-header').forEach(h => h.classList.remove('active'));
this.classList.add('active');
}
filterProducts();
});
});
// Проверяет, находится ли категория в дереве выбранной категории
function isInCategoryTree(categoryId, rootCategoryId) {
if (categoryId === rootCategoryId) return true;
// Находим узел категории
const categoryNode = document.querySelector(`.category-node[data-category-id="${categoryId}"]`);
if (!categoryNode) return false;
// Проверяем всех предков
let currentNode = categoryNode;
while (currentNode) {
const nodeId = currentNode.dataset.categoryId;
if (nodeId === rootCategoryId) return true;
// Переходим к родительскому .category-node
const parentContainer = currentNode.parentElement.closest('.category-children');
if (parentContainer) {
currentNode = parentContainer.closest('.category-node');
} else {
break;
}
}
return false;
}
// Единая функция фильтрации товаров
function filterProducts() {
const catalogItems = document.querySelectorAll('.catalog-item');
catalogItems.forEach(item => {
let shouldShow = true;
// Применяем фильтр по категории
if (selectedCategoryId) {
const itemCategories = item.dataset.categoryIds ?
item.dataset.categoryIds.split(',').filter(id => id.trim()) : [];
// Проверяем, принадлежит ли товар выбранной категории или её потомкам
shouldShow = itemCategories.length > 0 && itemCategories.some(catId => {
return isInCategoryTree(catId.trim(), selectedCategoryId);
});
}
// Применяем фильтр по типу
const activeTypeBtn = document.querySelector('[data-filter].active');
if (activeTypeBtn && shouldShow) {
const filterType = activeTypeBtn.dataset.filter;
if (filterType !== 'all' && item.dataset.type !== filterType) {
shouldShow = false;
}
}
// Применяем поиск
const searchInput = document.getElementById('catalog-search');
if (searchInput && shouldShow) {
const query = searchInput.value.toLowerCase();
if (query && !item.textContent.toLowerCase().includes(query)) {
shouldShow = false;
}
}
item.style.display = shouldShow ? '' : 'none';
});
}
// ======================================== // ========================================
// Фильтр по типу (товары/комплекты) // Фильтр по типу (товары/комплекты)
// ======================================== // ========================================
@@ -67,10 +169,8 @@ document.addEventListener('DOMContentLoaded', function() {
this.classList.add('active', 'btn-primary'); this.classList.add('active', 'btn-primary');
this.classList.remove('btn-outline-primary'); this.classList.remove('btn-outline-primary');
const filter = this.dataset.filter; // Используем единую функцию фильтрации
document.querySelectorAll('.catalog-item').forEach(item => { filterProducts();
item.style.display = (filter === 'all' || item.dataset.type === filter) ? '' : 'none';
});
}); });
}); });
@@ -80,11 +180,8 @@ document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('catalog-search'); const searchInput = document.getElementById('catalog-search');
if (searchInput) { if (searchInput) {
searchInput.addEventListener('input', function() { searchInput.addEventListener('input', function() {
const query = this.value.toLowerCase(); // Используем единую функцию фильтрации
document.querySelectorAll('.catalog-item').forEach(item => { filterProducts();
const text = item.textContent.toLowerCase();
item.style.display = text.includes(query) ? '' : 'none';
});
}); });
} }

View File

@@ -194,7 +194,7 @@
<div class="card-body"> <div class="card-body">
<div class="row g-3 catalog-list" id="catalog-grid"> <div class="row g-3 catalog-list" id="catalog-grid">
{% for item in items %} {% for item in items %}
<div class="col-12 catalog-item" data-type="{{ item.item_type }}"> <div class="col-12 catalog-item" data-type="{{ item.item_type }}" data-category-ids="{% for cat in item.categories.all %}{{ cat.pk }}{% if not forloop.last %},{% endif %}{% endfor %}">
<div class="card h-100 shadow-sm border-0"> <div class="card h-100 shadow-sm border-0">
<div class="position-relative"> <div class="position-relative">
{% if item.main_photo %} {% if item.main_photo %}
@@ -217,7 +217,7 @@
{% endif %} {% endif %}
</div> </div>
<div class="d-flex justify-content-between align-items-center mt-1"> <div class="d-flex justify-content-between align-items-center mt-1">
<span class="fw-bold text-primary small">{{ item.actual_price|floatformat:0 }} </span> <span class="fw-bold text-primary small">{{ item.actual_price|floatformat:0 }} руб.</span>
<small class="text-muted">{{ item.sku }}</small> <small class="text-muted">{{ item.sku }}</small>
</div> </div>
</div> </div>