Optimize order statuses list page with compact card layout
- Changed from table to card-based design for better space efficiency - Reduced padding and margins to fit 15+ statuses on screen without scrolling - Minimized font sizes and icon sizes for compact display - Added proper styling for edit and delete buttons with hover effects - Improved visual hierarchy with color indicators and badges - Maintained all functionality while improving UX 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,152 +4,226 @@
|
||||
{% block title %}Статусы заказов{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<h1>Статусы заказов</h1>
|
||||
<p class="text-muted">Управление статусами для заказов вашего магазина</p>
|
||||
<style>
|
||||
.status-card {
|
||||
border: none;
|
||||
border-left: 4px solid;
|
||||
padding: 10px 14px;
|
||||
margin-bottom: 6px;
|
||||
border-radius: 4px;
|
||||
background: #f8f9fa;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.status-card:hover {
|
||||
background: white;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.status-card-left {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.status-color {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
border: 2px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.status-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.status-name {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin: 0;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.status-meta {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-top: 2px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
font-size: 10px;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.status-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.status-actions .btn {
|
||||
padding: 5px 10px !important;
|
||||
font-size: 12px !important;
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
border: 1.5px solid;
|
||||
}
|
||||
|
||||
.status-actions .btn i {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.status-actions .btn-outline-primary {
|
||||
color: #0d6efd;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
|
||||
.status-actions .btn-outline-primary:hover {
|
||||
background-color: #0d6efd;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-actions .btn-outline-danger {
|
||||
color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.status-actions .btn-outline-danger:hover {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-actions .btn-outline-secondary:disabled {
|
||||
color: #6c757d;
|
||||
border-color: #6c757d;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.header-left h1 {
|
||||
font-size: 24px;
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.header-left p {
|
||||
margin: 2px 0 0 0;
|
||||
color: #6c757d;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header-section {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.status-card {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.status-card-left {
|
||||
width: 100%;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.status-actions {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.status-actions .btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container mt-4" style="max-width: 900px;">
|
||||
<div class="header-section">
|
||||
<div class="header-left">
|
||||
<h1>Статусы</h1>
|
||||
<p>{{ statuses|length }} статусов в системе</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<a href="{% url 'orders:status_create' %}" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> Создать новый статус
|
||||
<div>
|
||||
<a href="{% url 'orders:status_create' %}" class="btn btn-primary" style="font-weight: 600;">
|
||||
<i class="fas fa-plus"></i> Создать
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if messages %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert" style="margin-bottom: 16px;">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 50px;">№</th>
|
||||
<th style="width: 200px;">Название</th>
|
||||
<th style="width: 150px;">Код</th>
|
||||
<th style="width: 150px;">Тип</th>
|
||||
<th style="width: 100px;">Исход сделки</th>
|
||||
<th style="width: 80px;">Цвет</th>
|
||||
<th style="width: 80px;">Заказов</th>
|
||||
<th style="width: 150px;">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for status in statuses %}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="badge bg-secondary">{{ status.order }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<strong>{{ status.name }}</strong>
|
||||
{% if status.description %}
|
||||
<br>
|
||||
<small class="text-muted">{{ status.description|truncatewords:10 }}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ status.code }}</code>
|
||||
</td>
|
||||
<td>
|
||||
{% if status.is_system %}
|
||||
<span class="badge bg-info">Системный</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">Пользовательский</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if status.is_positive_end %}
|
||||
<span class="badge bg-success">✓ Успешный</span>
|
||||
{% elif status.is_negative_end %}
|
||||
<span class="badge bg-danger">✗ Отрицательный</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div style="width: 40px; height: 30px; background-color: {{ status.color }}; border-radius: 4px; border: 1px solid #ccc;" title="{{ status.color }}"></div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-light text-dark">{{ status.orders_count }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{% url 'orders:status_edit' status.pk %}" class="btn btn-sm btn-outline-primary" title="Редактировать">
|
||||
<i class="fas fa-edit"></i> Редактировать
|
||||
</a>
|
||||
{% if not status.is_system and status.orders_count == 0 %}
|
||||
<a href="{% url 'orders:status_delete' status.pk %}" class="btn btn-sm btn-outline-danger" title="Удалить">
|
||||
<i class="fas fa-trash"></i> Удалить
|
||||
</a>
|
||||
{% else %}
|
||||
<button class="btn btn-sm btn-outline-secondary" disabled title="{% if status.is_system %}Системный статус{% else %}В статусе есть заказы{% endif %}">
|
||||
<i class="fas fa-trash"></i> Удалить
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="8" class="text-center text-muted py-4">
|
||||
<i class="fas fa-inbox"></i> Статусы не найдены
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
{% for status in statuses %}
|
||||
<div class="status-card" style="border-left-color: {{ status.color }};">
|
||||
<div class="status-card-left">
|
||||
<div class="status-color" style="background-color: {{ status.color }};"></div>
|
||||
<div class="status-info">
|
||||
<p class="status-name" title="{{ status.name }}">{{ status.name }}</p>
|
||||
<div class="status-meta">
|
||||
<span class="status-badge bg-secondary">{{ status.code }}</span>
|
||||
{% if status.is_system %}
|
||||
<span class="status-badge bg-info">sys</span>
|
||||
{% endif %}
|
||||
{% if status.is_positive_end %}
|
||||
<span class="status-badge bg-success">✓</span>
|
||||
{% elif status.is_negative_end %}
|
||||
<span class="status-badge bg-danger">✗</span>
|
||||
{% endif %}
|
||||
{% if status.orders_count > 0 %}
|
||||
<span class="status-badge bg-light text-dark">{{ status.orders_count }} заказ{{ status.orders_count|pluralize:",а,ов" }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Page navigation" class="mt-3">
|
||||
<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 %}
|
||||
|
||||
{% for num in page_obj.paginator.page_range %}
|
||||
{% if page_obj.number == num %}
|
||||
<li class="page-item active">
|
||||
<span class="page-link">{{ num }}</span>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% 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 %}
|
||||
<div class="status-actions">
|
||||
<a href="{% url 'orders:status_edit' status.pk %}" class="btn btn-outline-primary" title="Редактировать">
|
||||
<i class="fas fa-edit"></i> Редактировать
|
||||
</a>
|
||||
{% if not status.is_system and status.orders_count == 0 %}
|
||||
<a href="{% url 'orders:status_delete' status.pk %}" class="btn btn-outline-danger" title="Удалить">
|
||||
<i class="fas fa-trash"></i> Удалить
|
||||
</a>
|
||||
{% else %}
|
||||
<button class="btn btn-outline-secondary" disabled title="{% if status.is_system %}Системный статус{% else %}В статусе есть заказы{% endif %}">
|
||||
<i class="fas fa-trash"></i> Удалить
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div style="text-align: center; padding: 40px 20px; color: #6c757d;">
|
||||
<i class="fas fa-inbox" style="font-size: 32px; margin-bottom: 12px; opacity: 0.5;"></i>
|
||||
<p style="font-size: 14px;">Статусы не найдены</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user