feat: add price filter and dynamic slider to catalog
All checks were successful
Build and Push Docker Image / build (push) Successful in 41s
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:
@@ -3,7 +3,7 @@
|
||||
<div class="container">
|
||||
<div class="header-top">
|
||||
<div class="logo"><a href="/">SantehRay</a></div>
|
||||
<form action="">
|
||||
<form action="/catalog/" method="get">
|
||||
<div class="search-wrap">
|
||||
<div class="search-select-wrap">
|
||||
<div class="search-category-dropdown" data-category-dropdown>
|
||||
@@ -67,9 +67,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<label>
|
||||
<input class="search-input" type="text" placeholder="Кто ищет, тот найдет...">
|
||||
<input class="search-input" type="text" name="q" value="{{ navigation_search_query }}" placeholder="Кто ищет, тот найдет...">
|
||||
</label>
|
||||
<button>
|
||||
<input type="hidden" name="min_price" value="{{ navigation_min_price }}">
|
||||
<input type="hidden" name="max_price" value="{{ navigation_max_price }}">
|
||||
<button type="submit" aria-label="Найти товары">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-search" viewBox="0 0 16 16">
|
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"></path>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
<link rel="stylesheet" href="{% static "css/catalog.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block add_js %}
|
||||
<script src="{% static 'js/catalog-price-slider.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- HEADER -->
|
||||
{% include "_fragments/header.html" with active="catalog" %}
|
||||
|
||||
Reference in New Issue
Block a user