Объединение списков товаров и комплектов в единый интерфейс
- Создан единый шаблон products_list.html для отображения товаров и комплектов - Удалены дублирующиеся шаблоны (product_list, productkit_list, products_unified_list, all_products_list) - Добавлены фильтры: тип (все/товары/комплекты), категория, статус, наличие, теги - Обновлен CombinedProductListView с поддержкой фильтрации по типу и тегам - Изменены URL маршруты: главная страница /products/ теперь показывает объединенный список - Обновлены success_url во всех CRUD представлениях для редиректа на объединенный список - Добавлена фильтрация по тегам с отображением количества выбранных элементов - Улучшена UX: компактный select для тегов с счетчиком выбранных - Все комментарии в коде переведены на русский язык
This commit is contained in:
@@ -1,258 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Все товары и комплекты{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Товары</h2>
|
||||
|
||||
<!-- Панель быстрых фильтров по категориям -->
|
||||
{% include 'components/category_filter_buttons.html' with categories=filters.categories current_category=filters.current.category show_type_filters=True %}
|
||||
|
||||
<!-- Панель фильтрации и действий -->
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<!-- Кнопки действий -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap">
|
||||
<h5 class="card-title mb-0 me-3">
|
||||
<i class="bi bi-funnel-fill"></i> Поиск и фильтры
|
||||
</h5>
|
||||
|
||||
{% if action_buttons %}
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
{% for button in action_buttons %}
|
||||
<a href="{{ button.url }}" class="btn {{ button.class|default:'btn-primary' }} btn-sm me-2 mb-2 mb-md-0">
|
||||
{% if button.icon %}<i class="bi bi-{{ button.icon }}"></i>{% endif %}
|
||||
{{ button.text }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<hr class="my-3">
|
||||
|
||||
<!-- Форма фильтров -->
|
||||
<form method="get" id="filterForm">
|
||||
<div class="row g-3">
|
||||
<!-- Поле поиска -->
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="search" class="form-label">
|
||||
<i class="bi bi-search"></i> Поиск
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="search"
|
||||
name="search"
|
||||
placeholder="Поиск по названию, артикулу..."
|
||||
value="{{ filters.current.search|default:'' }}"
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Фильтр по статусу -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="is_active" class="form-label">
|
||||
<i class="bi bi-toggle-on"></i> Статус
|
||||
</label>
|
||||
<select class="form-select" id="is_active" name="is_active">
|
||||
<option value="">Все</option>
|
||||
<option value="1" {% if filters.current.is_active == '1' %}selected{% endif %}>Активные</option>
|
||||
<option value="0" {% if filters.current.is_active == '0' %}selected{% endif %}>Неактивные</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Сохраняем текущую категорию при поиске -->
|
||||
{% if filters.current.category %}
|
||||
<input type="hidden" name="category" value="{{ filters.current.category }}">
|
||||
{% endif %}
|
||||
|
||||
<!-- Кнопки управления фильтрами -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label class="form-label d-none d-md-block"> </label>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
<i class="bi bi-check-circle"></i> Применить
|
||||
</button>
|
||||
<a href="{{ request.path }}" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-x-circle"></i> Сброс
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if items %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th style="width: 60px;">Тип</th>
|
||||
<th style="width: 80px;">Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Артикул</th>
|
||||
<th>Категория</th>
|
||||
<th>Цена продажи</th>
|
||||
<th>В наличии</th>
|
||||
<th>Статус</th>
|
||||
<th style="width: 200px;">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
<span class="badge bg-success" title="Товар поштучно">
|
||||
<i class="bi bi-box"></i>
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-info" title="Комплект">
|
||||
<i class="bi bi-box-seam"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.photos.all %}
|
||||
{% with photo=item.photos.first %}
|
||||
<img src="{{ photo.get_thumbnail_url }}" alt="{{ item.name }}" style="max-width: 50px; max-height: 50px;" class="img-thumbnail">
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<span class="text-muted small">Нет фото</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
<a href="{% url 'products:product-detail' item.pk %}">{{ item.name }}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'products:productkit-detail' item.pk %}">{{ item.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ item.sku }}</td>
|
||||
<td>
|
||||
{% if item.categories.all %}
|
||||
{% for category in item.categories.all %}
|
||||
<span class="badge bg-secondary">{{ category.name }}</span>{% if not forloop.last %} {% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">-</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.sale_price %}
|
||||
<span class="text-decoration-line-through text-muted small">{{ item.price|floatformat:2 }} руб.</span>
|
||||
<br>
|
||||
<strong class="text-danger">{{ item.sale_price|floatformat:2 }} руб.</strong>
|
||||
<span class="badge bg-danger ms-1">Акция</span>
|
||||
{% else %}
|
||||
<strong>{{ item.actual_price|floatformat:2 }} руб.</strong>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
{% if item.in_stock %}
|
||||
<span class="badge bg-success"><i class="bi bi-check-circle"></i> Да</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger"><i class="bi bi-x-circle"></i> Нет</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<!-- Для комплектов проверяем есть ли вариант в наличии -->
|
||||
<span class="text-muted small">-</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.is_active %}
|
||||
<span class="badge bg-info">Активен</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">Неактивен</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
{% if item.item_type == 'product' %}
|
||||
<a href="{% url 'products:product-detail' item.pk %}" class="btn btn-outline-info" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if perms.products.change_product %}
|
||||
<a href="{% url 'products:product-update' item.pk %}" class="btn btn-outline-primary" title="Изменить">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.delete_product %}
|
||||
<a href="{% url 'products:product-delete' item.pk %}" class="btn btn-outline-danger" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{% url 'products:productkit-detail' item.pk %}" class="btn btn-outline-info" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if perms.products.change_productkit %}
|
||||
<a href="{% url 'products:productkit-update' item.pk %}" class="btn btn-outline-primary" title="Изменить">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.delete_productkit %}
|
||||
<a href="{% url 'products:productkit-delete' item.pk %}" class="btn btn-outline-danger" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Первая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Предыдущая</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">Страница {{ page_obj.number }} из {{ page_obj.paginator.num_pages }}</span>
|
||||
</li>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Следующая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Последняя</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<h4><i class="bi bi-info-circle"></i> Товары не найдены</h4>
|
||||
<p>В данный момент нет товаров или комплектов, соответствующих выбранным фильтрам.</p>
|
||||
<div class="mt-3">
|
||||
{% if perms.products.add_product %}
|
||||
<a href="{% url 'products:product-create' %}" class="btn btn-primary me-2">
|
||||
<i class="bi bi-plus-circle"></i> Создать товар
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.add_productkit %}
|
||||
<a href="{% url 'products:productkit-create' %}" class="btn btn-outline-primary">
|
||||
<i class="bi bi-plus-circle"></i> Создать комплект
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,136 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load quality_tags %}
|
||||
|
||||
{% block title %}Список товаров{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Список товаров</h2>
|
||||
|
||||
<!-- Панель фильтрации -->
|
||||
{% include 'components/filter_panel.html' with title="Товары" filters=filters action_buttons=action_buttons %}
|
||||
|
||||
{% if products %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Артикул</th>
|
||||
<th>Категория</th>
|
||||
<th>Цена продажи</th>
|
||||
<th>В наличии</th>
|
||||
<th>Статус</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for product in products %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if product.photos.all %}
|
||||
{% with photo=product.photos.first %}
|
||||
<!-- Миниатюра с индикатором качества -->
|
||||
<div class="photo-list-item">
|
||||
<img src="{{ photo.get_thumbnail_url }}" alt="{{ product.name }}" class="img-thumbnail rounded">
|
||||
<span class="quality-icon" title="{{ photo.get_quality_level_display }}">{{ photo|quality_icon_only }}</span>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<span class="text-muted">Нет фото</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'products:product-detail' product.pk %}">{{ product.name }}</a>
|
||||
</td>
|
||||
<td>{{ product.sku }}</td>
|
||||
<td>
|
||||
{% if product.categories.all %}
|
||||
{% for category in product.categories.all %}
|
||||
{{ category.name }}{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if product.sale_price %}
|
||||
<span class="text-decoration-line-through text-muted small">{{ product.price }} руб.</span>
|
||||
<br>
|
||||
<strong class="text-danger">{{ product.sale_price }} руб.</strong>
|
||||
<span class="badge bg-danger ms-1">Акция</span>
|
||||
{% else %}
|
||||
<strong>{{ product.price }} руб.</strong>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if product.in_stock %}
|
||||
<span class="badge bg-success"><i class="bi bi-check-circle"></i> В наличии</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger"><i class="bi bi-x-circle"></i> Нет</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if product.status == 'active' %}
|
||||
<span class="badge bg-success">Активный</span>
|
||||
{% elif product.status == 'archived' %}
|
||||
<span class="badge bg-warning text-dark">Архивный</span>
|
||||
{% elif product.status == 'discontinued' %}
|
||||
<span class="badge bg-danger">Снят</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ product.status }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if perms.products.change_product %}
|
||||
<a href="{% url 'products:product-update' product.pk %}" class="btn btn-sm btn-outline-primary">Изменить</a>
|
||||
{% endif %}
|
||||
{% if perms.products.delete_product %}
|
||||
<a href="{% url 'products:product-delete' product.pk %}" class="btn btn-sm btn-outline-danger">Удалить</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1">Первая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Предыдущая</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">Страница {{ page_obj.number }} из {{ page_obj.paginator.num_pages }}</span>
|
||||
</li>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}">Следующая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Последняя</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<p>Товары не найдены.</p>
|
||||
{% if perms.products.add_product %}
|
||||
<a href="{% url 'products:product-create' %}" class="btn btn-primary">Создать первый товар</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,141 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Список комплектов (букетов){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Список комплектов (букетов)</h2>
|
||||
|
||||
<!-- Панель фильтрации -->
|
||||
{% include 'components/filter_panel.html' with title="Комплекты" filters=filters action_buttons=action_buttons %}
|
||||
|
||||
{% if kits %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Артикул</th>
|
||||
<th>Категория</th>
|
||||
<th>Цена продажи</th>
|
||||
<th>Компонентов</th>
|
||||
<th>Статус</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for kit in kits %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if kit.photos.all %}
|
||||
{% with photo=kit.photos.first %}
|
||||
<!-- Миниатюра 200x200 для списков -->
|
||||
<img src="{{ photo.get_thumbnail_url }}" alt="{{ kit.name }}" style="width: 60px; height: 60px; object-fit: cover;" class="img-thumbnail rounded">
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<span class="text-muted">Нет фото</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'products:productkit-detail' kit.pk %}">{{ kit.name }}</a>
|
||||
</td>
|
||||
<td>{{ kit.sku }}</td>
|
||||
<td>
|
||||
{% if kit.categories.all %}
|
||||
{% for category in kit.categories.all %}
|
||||
{{ category.name }}{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if kit.sale_price %}
|
||||
<span class="text-decoration-line-through text-muted small">{{ kit.price|floatformat:2 }} руб.</span>
|
||||
<br>
|
||||
<strong class="text-danger">{{ kit.sale_price|floatformat:2 }} руб.</strong>
|
||||
<span class="badge bg-danger ms-1">Акция</span>
|
||||
{% else %}
|
||||
<strong>{{ kit.price|floatformat:2 }} руб.</strong>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ kit.get_total_components_count }} шт</span>
|
||||
{% if kit.get_components_with_variants_count > 0 %}
|
||||
<span class="badge bg-primary" title="С вариантами">
|
||||
<i class="bi bi-shuffle"></i> {{ kit.get_components_with_variants_count }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if kit.status == 'active' %}
|
||||
<span class="badge bg-success">Активный</span>
|
||||
{% elif kit.status == 'archived' %}
|
||||
<span class="badge bg-warning text-dark">Архивный</span>
|
||||
{% elif kit.status == 'discontinued' %}
|
||||
<span class="badge bg-danger">Снят</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ kit.status }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<a href="{% url 'products:productkit-detail' kit.pk %}" class="btn btn-outline-info" title="Просмотреть">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<a href="{% url 'products:productkit-update' kit.pk %}" class="btn btn-outline-primary" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<a href="{% url 'products:productkit-delete' kit.pk %}" class="btn btn-outline-danger" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Первая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Предыдущая</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">Страница {{ page_obj.number }} из {{ page_obj.paginator.num_pages }}</span>
|
||||
</li>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Следующая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Последняя</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<h4><i class="bi bi-info-circle"></i> Комплекты не найдены</h4>
|
||||
<p>В данный момент нет комплектов, соответствующих выбранным фильтрам.</p>
|
||||
{% if perms.products.add_productkit %}
|
||||
<a href="{% url 'products:productkit-create' %}" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle"></i> Создать первый комплект
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
333
myproject/products/templates/products/products_list.html
Normal file
333
myproject/products/templates/products/products_list.html
Normal file
@@ -0,0 +1,333 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load quality_tags %}
|
||||
|
||||
{% block title %}Товары и комплекты{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<h2 class="mb-4">
|
||||
<i class="bi bi-box-seam"></i> Товары и комплекты
|
||||
</h2>
|
||||
|
||||
<!-- Панель фильтрации и действий -->
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap">
|
||||
<h5 class="card-title mb-0 me-3">
|
||||
<i class="bi bi-funnel-fill"></i> Фильтры
|
||||
</h5>
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
{% if action_buttons %}
|
||||
{% for button in action_buttons %}
|
||||
<a href="{{ button.url }}" class="btn {{ button.class|default:'btn-primary' }} btn-sm me-2 mb-2 mb-md-0">
|
||||
{% if button.icon %}<i class="bi bi-{{ button.icon }}"></i>{% endif %}
|
||||
{{ button.text }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-3">
|
||||
|
||||
<form method="get" id="filterForm">
|
||||
<div class="row g-3">
|
||||
<!-- Поиск -->
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="search" class="form-label"><i class="bi bi-search"></i> Поиск</label>
|
||||
<input type="text" class="form-control" id="search" name="search"
|
||||
placeholder="Название, артикул, описание..."
|
||||
value="{{ filters.current.search|default:'' }}">
|
||||
</div>
|
||||
|
||||
<!-- Тип -->
|
||||
<div class="col-12 col-md-2">
|
||||
<label for="type" class="form-label"><i class="bi bi-box"></i> Тип</label>
|
||||
<select class="form-select" id="type" name="type">
|
||||
<option value="all" {% if filters.current.type == 'all' %}selected{% endif %}>Все</option>
|
||||
<option value="products" {% if filters.current.type == 'products' %}selected{% endif %}>Только товары</option>
|
||||
<option value="kits" {% if filters.current.type == 'kits' %}selected{% endif %}>Только комплекты</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Категория -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="category" class="form-label"><i class="bi bi-bookmark"></i> Категория</label>
|
||||
<select class="form-select" id="category" name="category">
|
||||
<option value="">Все категории</option>
|
||||
{% for category in filters.categories %}
|
||||
<option value="{{ category.id }}" {% if filters.current.category == category.id|stringformat:"s" %}selected{% endif %}>
|
||||
{{ category.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Статус -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="status" class="form-label"><i class="bi bi-toggle-on"></i> Статус</label>
|
||||
<select class="form-select" id="status" name="status">
|
||||
<option value="">Все статусы</option>
|
||||
{% for status_value, status_name in item_statuses %}
|
||||
<option value="{{ status_value }}" {% if filters.current.status == status_value %}selected{% endif %}>
|
||||
{{ status_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mt-2">
|
||||
<!-- В наличии (только для товаров) -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="in_stock" class="form-label"><i class="bi bi-check-circle"></i> В наличии</label>
|
||||
<select class="form-select" id="in_stock" name="in_stock">
|
||||
<option value="">Все</option>
|
||||
<option value="1" {% if filters.current.in_stock == '1' %}selected{% endif %}>Да</option>
|
||||
<option value="0" {% if filters.current.in_stock == '0' %}selected{% endif %}>Нет</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Теги -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="tags" class="form-label"><i class="bi bi-tags"></i> Теги</label>
|
||||
<select class="form-select" id="tags" name="tags" multiple size="1">
|
||||
{% for tag in filters.tags %}
|
||||
<option value="{{ tag.id }}" {% if tag.id in filters.current.tags %}selected{% endif %}>
|
||||
{{ tag.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if filters.current.tags %}
|
||||
<small class="text-muted">Выбрано: {{ filters.current.tags|length }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label d-none d-md-block"> </label>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-check-circle"></i> Применить
|
||||
</button>
|
||||
<a href="{% url 'products:products-list' %}" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-x-circle"></i> Сбросить
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if items %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th style="width: 80px;">Фото</th>
|
||||
<th>Название</th>
|
||||
<th style="width: 120px;">Артикул</th>
|
||||
<th style="width: 80px;">Тип</th>
|
||||
<th>Категория</th>
|
||||
<th style="width: 130px;">Цена</th>
|
||||
<th style="width: 100px;">В наличии</th>
|
||||
<th style="width: 100px;">Статус</th>
|
||||
<th style="width: 150px;">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if item.photos.all %}
|
||||
{% with photo=item.photos.first %}
|
||||
<div class="photo-list-item">
|
||||
<img src="{{ photo.get_thumbnail_url }}" alt="{{ item.name }}"
|
||||
class="img-thumbnail rounded" style="width: 60px; height: 60px; object-fit: cover;">
|
||||
{% if item.item_type == 'product' %}
|
||||
<span class="quality-icon" title="{{ photo.get_quality_level_display }}">
|
||||
{{ photo|quality_icon_only }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<span class="text-muted small">Нет фото</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
<a href="{% url 'products:product-detail' item.pk %}">{{ item.name }}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'products:productkit-detail' item.pk %}">{{ item.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><code class="small">{{ item.sku }}</code></td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
<span class="badge bg-success" title="Товар"><i class="bi bi-box"></i></span>
|
||||
{% else %}
|
||||
<span class="badge bg-info" title="Комплект"><i class="bi bi-box-seam"></i></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% for category in item.categories.all %}
|
||||
<span class="badge bg-secondary">{{ category.name }}</span>
|
||||
{% empty %}
|
||||
<span class="text-muted">-</span>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.sale_price %}
|
||||
<div class="text-decoration-line-through text-muted small">{{ item.price|floatformat:2 }} руб.</div>
|
||||
<strong class="text-danger">{{ item.sale_price|floatformat:2 }} руб.</strong>
|
||||
{% else %}
|
||||
<strong>{{ item.price|floatformat:2 }} руб.</strong>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
{% if item.in_stock %}
|
||||
<span class="badge bg-success"><i class="bi bi-check-circle"></i> Да</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger"><i class="bi bi-x-circle"></i> Нет</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted">-</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.status == 'active' %}
|
||||
<span class="badge bg-success">Активный</span>
|
||||
{% elif item.status == 'archived' %}
|
||||
<span class="badge bg-warning text-dark">Архивный</span>
|
||||
{% elif item.status == 'discontinued' %}
|
||||
<span class="badge bg-danger">Снят</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ item.get_status_display }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
{% if item.item_type == 'product' %}
|
||||
<a href="{% url 'products:product-detail' item.pk %}"
|
||||
class="btn btn-outline-info" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if perms.products.change_product %}
|
||||
<a href="{% url 'products:product-update' item.pk %}"
|
||||
class="btn btn-outline-primary" title="Изменить">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.delete_product %}
|
||||
<a href="{% url 'products:product-delete' item.pk %}"
|
||||
class="btn btn-outline-danger" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{% url 'products:productkit-detail' item.pk %}"
|
||||
class="btn btn-outline-info" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
{% if perms.products.change_productkit %}
|
||||
<a href="{% url 'products:productkit-update' item.pk %}"
|
||||
class="btn btn-outline-primary" title="Изменить">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.delete_productkit %}
|
||||
<a href="{% url 'products:productkit-delete' item.pk %}"
|
||||
class="btn btn-outline-danger" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">
|
||||
Первая
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">
|
||||
Предыдущая
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">Страница {{ page_obj.number }} из {{ page_obj.paginator.num_pages }}</span>
|
||||
</li>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">
|
||||
Следующая
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">
|
||||
Последняя
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<h4><i class="bi bi-info-circle"></i> Товары не найдены</h4>
|
||||
<p>В данный момент нет товаров или комплектов, соответствующих выбранным фильтрам.</p>
|
||||
<div class="mt-3">
|
||||
{% if perms.products.add_product %}
|
||||
<a href="{% url 'products:product-create' %}" class="btn btn-primary me-2">
|
||||
<i class="bi bi-plus-circle"></i> Создать товар
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.add_productkit %}
|
||||
<a href="{% url 'products:productkit-create' %}" class="btn btn-outline-primary">
|
||||
<i class="bi bi-plus-circle"></i> Создать комплект
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Стили для индикатора качества фото */
|
||||
.photo-list-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.photo-list-item .quality-icon {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
font-size: 14px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -1,189 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load quality_tags %}
|
||||
|
||||
{% block title %}Список товаров и комплектов{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<h2 class="mb-4">Товары и Комплекты</h2>
|
||||
|
||||
<!-- Панель фильтрации и действий -->
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap">
|
||||
<h5 class="card-title mb-0 me-3">
|
||||
<i class="bi bi-funnel-fill"></i> Фильтры
|
||||
</h5>
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
{% if perms.products.add_product %}
|
||||
<a href="{% url 'products:product-create' %}" class="btn btn-primary btn-sm me-2 mb-2 mb-md-0">
|
||||
<i class="bi bi-plus-circle"></i> Создать товар
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.products.add_productkit %}
|
||||
<a href="{% url 'products:productkit-create' %}" class="btn btn-outline-primary btn-sm mb-2 mb-md-0">
|
||||
<i class="bi bi-box-seam"></i> Создать комплект
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-3">
|
||||
|
||||
<form method="get" id="filterForm">
|
||||
<div class="row g-3">
|
||||
<!-- Поиск -->
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="search" class="form-label"><i class="bi bi-search"></i> Поиск</label>
|
||||
<input type="text" class="form-control" id="search" name="search" placeholder="Название, артикул, описание..." value="{{ filters.current.search|default:'' }}">
|
||||
</div>
|
||||
|
||||
<!-- Тип -->
|
||||
<div class="col-12 col-md-2">
|
||||
<label for="type" class="form-label"><i class="bi bi-box-seam"></i> Тип</label>
|
||||
<select class="form-select" id="type" name="type">
|
||||
<option value="all" {% if filters.current.type == 'all' %}selected{% endif %}>Все</option>
|
||||
<option value="products" {% if filters.current.type == 'products' %}selected{% endif %}>Только товары</option>
|
||||
<option value="kits" {% if filters.current.type == 'kits' %}selected{% endif %}>Только комплекты</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Категория -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="category" class="form-label"><i class="bi bi-bookmark"></i> Категория</label>
|
||||
<select class="form-select" id="category" name="category">
|
||||
<option value="">Все категории</option>
|
||||
{% for category in filters.categories %}
|
||||
<option value="{{ category.id }}" {% if filters.current.category == category.id|stringformat:"s" %}selected{% endif %}>{{ category.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Статус -->
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="status" class="form-label"><i class="bi bi-toggle-on"></i> Статус</label>
|
||||
<select class="form-select" id="status" name="status">
|
||||
<option value="">Все статусы</option>
|
||||
{% for status_value, status_name in item_statuses %}
|
||||
<option value="{{ status_value }}" {% if filters.current.status == status_value %}selected{% endif %}>{{ status_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3 mt-2">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-primary"><i class="bi bi-check-circle"></i> Применить</button>
|
||||
<a href="{% url 'products:product-list' %}" class="btn btn-outline-secondary"><i class="bi bi-x-circle"></i> Сброс</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if items %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Артикул</th>
|
||||
<th>Тип</th>
|
||||
<th>Категория</th>
|
||||
<th>Цена</th>
|
||||
<th>В наличии</th>
|
||||
<th>Компоненты</th>
|
||||
<th>Статус</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>
|
||||
{% with photo=item.photos.first %}
|
||||
<div class="photo-list-item">
|
||||
<img src="{{ photo.get_thumbnail_url }}" alt="{{ item.name }}" class="img-thumbnail rounded">
|
||||
{% if item.item_type == 'product' and photo %}
|
||||
<span class="quality-icon" title="{{ photo.get_quality_level_display }}">{{ photo|quality_icon_only }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ item.get_absolute_url }}">{{ item.name }}</a>
|
||||
</td>
|
||||
<td>{{ item.sku }}</td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
<span class="badge bg-success" title="Товар"><i class="bi bi-box"></i> Товар</span>
|
||||
{% else %}
|
||||
<span class="badge bg-info" title="Комплект"><i class="bi bi-box-seam"></i> Комплект</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% for category in item.categories.all %}
|
||||
<span class="badge bg-secondary">{{ category.name }}</span>
|
||||
{% empty %}
|
||||
-
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.sale_price %}
|
||||
<span class="text-decoration-line-through text-muted small">{{ item.price|floatformat:2 }} руб.</span><br>
|
||||
<strong class="text-danger">{{ item.sale_price|floatformat:2 }} руб.</strong>
|
||||
{% else %}
|
||||
<strong>{{ item.price|floatformat:2 }} руб.</strong>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.item_type == 'product' %}
|
||||
{% if item.in_stock %}
|
||||
<span class="badge bg-success"><i class="bi bi-check-circle"></i> Да</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger"><i class="bi bi-x-circle"></i> Нет</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if item.item_type == 'kit' %}
|
||||
<span class="badge bg-secondary">{{ item.get_total_components_count }} шт</span>
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge" style="background-color: {{ item.get_status_color }}">{{ item.get_status_display }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="{{ item.get_absolute_url }}" class="btn btn-outline-info" title="Просмотр"><i class="bi bi-eye"></i></a>
|
||||
{% if item.item_type == 'product' and perms.products.change_product %}
|
||||
<a href="{% url 'products:product-update' item.pk %}" class="btn btn-outline-primary" title="Изменить"><i class="bi bi-pencil"></i></a>
|
||||
{% elif item.item_type == 'kit' and perms.products.change_productkit %}
|
||||
<a href="{% url 'products:productkit-update' item.pk %}" class="btn btn-outline-primary" title="Изменить"><i class="bi bi-pencil"></i></a>
|
||||
{% endif %}
|
||||
{% if item.item_type == 'product' and perms.products.delete_product %}
|
||||
<a href="{% url 'products:product-delete' item.pk %}" class="btn btn-outline-danger" title="Удалить"><i class="bi bi-trash"></i></a>
|
||||
{% elif item.item_type == 'kit' and perms.products.delete_productkit %}
|
||||
<a href="{% url 'products:productkit-delete' item.pk %}" class="btn btn-outline-danger" title="Удалить"><i class="bi bi-trash"></i></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% include 'components/pagination.html' %}
|
||||
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<p>Товары или комплекты не найдены.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user