- Вместо текста 'X / Y' теперь кликабельные цифры страниц - Показывается до 10 страниц (±5 от текущей) - Текущая страница выделена (active) - Умная логика: если на странице 15, показывает 10-20 - Все параметры фильтров сохраняются при клике на номер страницы
208 lines
12 KiB
HTML
208 lines
12 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Клиенты{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid">
|
||
<div class="row">
|
||
<div class="col-12">
|
||
|
||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||
<div>
|
||
<h1>Клиенты</h1>
|
||
<p class="text-muted mb-0">
|
||
Всего клиентов: <strong>{{ total_customers }}</strong>
|
||
</p>
|
||
</div>
|
||
<div class="btn-group" role="group">
|
||
<a href="{% url 'customers:customer-import' %}" class="btn btn-outline-success">
|
||
<i class="bi bi-upload"></i> Импорт
|
||
</a>
|
||
<a href="{% url 'customers:customer-export' %}" class="btn btn-outline-info">
|
||
<i class="bi bi-download"></i> Экспорт
|
||
</a>
|
||
<a href="{% url 'customers:customer-create' %}" class="btn btn-primary">
|
||
<i class="bi bi-plus-circle"></i> Добавить клиента
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Поиск и фильтры -->
|
||
<div class="card mb-3">
|
||
<div class="card-body">
|
||
<form method="get" class="row g-3">
|
||
<!-- Поиск -->
|
||
<div class="col-md-6">
|
||
<input type="text" class="form-control" name="q" value="{{ query }}"
|
||
placeholder="Поиск по имени, email или телефону..."
|
||
autofocus>
|
||
</div>
|
||
|
||
<!-- Фильтры -->
|
||
<div class="col-md-6">
|
||
<div class="d-flex gap-3 align-items-center">
|
||
<div class="form-check">
|
||
{{ filter.form.has_notes }}
|
||
<label class="form-check-label" for="{{ filter.form.has_notes.id_for_label }}">
|
||
Есть заметки
|
||
</label>
|
||
</div>
|
||
<div class="form-check">
|
||
{{ filter.form.no_phone }}
|
||
<label class="form-check-label" for="{{ filter.form.no_phone.id_for_label }}">
|
||
Нет телефона
|
||
</label>
|
||
</div>
|
||
<div class="form-check">
|
||
{{ filter.form.no_email }}
|
||
<label class="form-check-label" for="{{ filter.form.no_email.id_for_label }}">
|
||
Нет email
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Кнопки -->
|
||
<div class="col-12">
|
||
<div class="btn-group" role="group">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="bi bi-search"></i> Поиск / Фильтр
|
||
</button>
|
||
{% if query or filter.form.has_notes.value or filter.form.no_phone.value or filter.form.no_email.value %}
|
||
<a href="{% url 'customers:customer-list' %}" class="btn btn-outline-secondary">
|
||
<i class="bi bi-x-circle"></i> Очистить
|
||
</a>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Таблица клиентов -->
|
||
<div class="card">
|
||
<div class="card-body">
|
||
{% if page_obj %}
|
||
<div class="table-responsive">
|
||
<table class="table table-hover align-middle">
|
||
<thead>
|
||
<tr>
|
||
<th>Имя</th>
|
||
<th>Email</th>
|
||
<th>Телефон</th>
|
||
<th>Заметки</th>
|
||
<th class="text-end">Действия</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for customer in page_obj %}
|
||
<tr
|
||
style="cursor:pointer"
|
||
onclick="window.location='{% url 'customers:customer-detail' customer.pk %}'"
|
||
>
|
||
<td class="fw-semibold">{{ customer.full_name }}</td>
|
||
<td>{{ customer.email|default:'—' }}</td>
|
||
<td>{{ customer.phone|default:'—' }}</td>
|
||
<td>
|
||
{% if customer.notes %}
|
||
<div style="max-width: 300px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"
|
||
title="{{ customer.notes }}">
|
||
{{ customer.notes|truncatewords:10 }}
|
||
</div>
|
||
{% else %}
|
||
—
|
||
{% endif %}
|
||
</td>
|
||
|
||
<td class="text-end" onclick="event.stopPropagation();">
|
||
<a href="{% url 'customers:customer-detail' customer.pk %}"
|
||
class="btn btn-sm btn-outline-primary" title="Просмотр">
|
||
<i class="bi bi-eye"></i>
|
||
</a>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Pagination -->
|
||
{% if page_obj.has_other_pages %}
|
||
{# Сохраняем все GET-параметры кроме page #}
|
||
{% with params=request.GET.copy %}
|
||
{% if params.page %}{{ params.pop|slice:":0" }}{% endif %}
|
||
<nav aria-label="Page navigation" class="mt-3">
|
||
<ul class="pagination pagination-sm justify-content-center mb-0">
|
||
{% if page_obj.has_previous %}
|
||
<li class="page-item">
|
||
<a class="page-link" href="?page=1&{{ params.urlencode }}" title="Первая страница">
|
||
««
|
||
</a>
|
||
</li>
|
||
<li class="page-item">
|
||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&{{ params.urlencode }}" title="Предыдущая">
|
||
«
|
||
</a>
|
||
</li>
|
||
{% else %}
|
||
<li class="page-item disabled">
|
||
<span class="page-link">««</span>
|
||
</li>
|
||
<li class="page-item disabled">
|
||
<span class="page-link">«</span>
|
||
</li>
|
||
{% endif %}
|
||
|
||
{# Цифры страниц: показываем до 10 страниц #}
|
||
{% with start_page=page_obj.number|add:"-5" end_page=page_obj.number|add:"5" %}
|
||
{% for num in page_obj.paginator.page_range %}
|
||
{% if num >= start_page|default:1 and num <= end_page and num <= page_obj.paginator.num_pages %}
|
||
{% if num == page_obj.number %}
|
||
<li class="page-item active">
|
||
<span class="page-link">{{ num }}</span>
|
||
</li>
|
||
{% else %}
|
||
<li class="page-item">
|
||
<a class="page-link" href="?page={{ num }}&{{ params.urlencode }}">{{ num }}</a>
|
||
</li>
|
||
{% endif %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% endwith %}
|
||
|
||
{% if page_obj.has_next %}
|
||
<li class="page-item">
|
||
<a class="page-link" href="?page={{ page_obj.next_page_number }}&{{ params.urlencode }}" title="Следующая">
|
||
»
|
||
</a>
|
||
</li>
|
||
<li class="page-item">
|
||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}&{{ params.urlencode }}" title="Последняя страница">
|
||
»»
|
||
</a>
|
||
</li>
|
||
{% else %}
|
||
<li class="page-item disabled">
|
||
<span class="page-link">»</span>
|
||
</li>
|
||
<li class="page-item disabled">
|
||
<span class="page-link">»»</span>
|
||
</li>
|
||
{% endif %}
|
||
</ul>
|
||
</nav>
|
||
{% endwith %}
|
||
{% endif %}
|
||
|
||
{% else %}
|
||
<p>Клиенты не найдены.</p>
|
||
{% endif %}
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|