feat: add price filter and dynamic slider to catalog
All checks were successful
Build and Push Docker Image / build (push) Successful in 41s

- Implemented JavaScript-based price slider for catalog filtering
- Updated catalog views to handle min/max price inputs and compute slider bounds
- Enhanced templates (`index.html`, `side-bar.html`) with filtering form and updated URLs
- Added CSS for price slider styling and form layout
- Introduced utility functions for URL building and price parsing
- Expanded tests for price filtering, sliders, and sidebar active states
- Updated context processor and header for dynamic navigation with price filters
This commit is contained in:
2026-05-16 11:12:24 +02:00
parent 52cbc1c2b3
commit 3d356c7d6a
11 changed files with 579 additions and 11 deletions

View File

@@ -1,9 +1,9 @@
<aside>
<section class="categories a-section">
<h2>Категории</h2>
<a href="/catalog/" class="category {% if selected_category.id == None %}active{% endif %}">Все товары</a>
<a href="{{ all_items_url }}" class="category {% if selected_category.id == None %}active{% endif %}">Все товары</a>
{% for category in categories %}
<a href="/catalog/{{ category.slug }}/" class="category {% if selected_category.id == category.slug %}active{% endif %}">
<a href="{{ category.catalog_url }}" class="category {% if selected_category.id == category.slug %}active{% endif %}">
{{ category.name }}
</a>
{% empty %}
@@ -14,11 +14,11 @@
<section class="sub-categories a-section">
<h2>Подкатегории</h2>
{% if selected_category.id != None %}
<a href="/catalog/{{ selected_category.id }}/" class="category {% if selected_subcategory.id == None %}active{% endif %}">
<a href="{{ selected_category_url }}" class="category {% if selected_subcategory.id == None %}active{% endif %}">
Все подкатегории
</a>
{% for subcategory in subcategories %}
<a href="/catalog/{{ selected_category.id }}/?subcategory={{ subcategory.slug }}" class="category {% if selected_subcategory.id == subcategory.slug %}active{% endif %}">
<a href="{{ subcategory.catalog_url }}" class="category {% if selected_subcategory.id == subcategory.slug %}active{% endif %}">
{{ subcategory.name }}
</a>
{% empty %}
@@ -29,9 +29,54 @@
{% endif %}
</section>
<form action="">
<form action="{{ price_filter_action }}" method="get" class="catalog-filter-form">
<input type="hidden" name="q" value="{{ current_search_query }}">
{% if selected_subcategory.id != None %}
<input type="hidden" name="subcategory" value="{{ selected_subcategory.id }}">
{% endif %}
<section class="a-section cost-section">
<h2>Стоимость</h2>
<div
class="catalog-price-slider"
data-price-slider
data-min-bound="{{ price_slider_min_bound }}"
data-max-bound="{{ price_slider_max_bound }}"
>
<input type="hidden" name="min_price" value="{{ current_min_price }}" data-price-hidden-min>
<input type="hidden" name="max_price" value="{{ current_max_price }}" data-price-hidden-max>
<div class="catalog-price-slider__values" aria-live="polite">
<span data-price-label-min>{{ price_slider_selected_min }} руб.</span>
<span data-price-label-max>{{ price_slider_selected_max }} руб.</span>
</div>
<div class="catalog-price-slider__controls">
<div class="catalog-price-slider__track">
<div class="catalog-price-slider__track-fill" data-price-track-fill></div>
</div>
<input
type="range"
min="{{ price_slider_min_bound }}"
max="{{ price_slider_max_bound }}"
step="0.01"
value="{{ price_slider_selected_min }}"
class="catalog-price-slider__range"
aria-label="Минимальная цена"
data-price-range-min
>
<input
type="range"
min="{{ price_slider_min_bound }}"
max="{{ price_slider_max_bound }}"
step="0.01"
value="{{ price_slider_selected_max }}"
class="catalog-price-slider__range"
aria-label="Максимальная цена"
data-price-range-max
>
</div>
</div>
<button type="submit" class="catalog-filter-submit">Применить</button>
</section>
<section class="a-section color-section">