Реализовано управление активностью тегов товаров и комплектов
## Что сделано: ### 1. Фильтрация тегов по активности - ProductForm и ProductKitForm показывают только активные теги в селектах - ProductListView, ProductKitListView передают только активные теги в контекст фильтров ### 2. Отображение тегов на страницах товаров/комплектов - product_detail.html отображает только активные теги - productkit_detail.html отображает только активные теги ### 3. Логика отображения в деталях тега - Для активного тега: показываются только активные товары/комплекты - Для неактивного тега: показываются ВСЕ товары/комплекты (для возможности ручной очистки) ### 4. API endpoint для переключения статуса - Новый endpoint toggle_tag_status_api в api_views.py - POST /products/api/tags/<id>/toggle/ - Переключает is_active и возвращает новый статус ### 5. AJAX toggle switch в таблице тегов - Заменены бейджи на toggle switch в tag_list.html - Переключатель в 1.3x больше (масштабирование через CSS) - Мгновенное обновление без перезагрузки страницы - Показывает сообщение об успехе/ошибке ### 6. Связь в БД остаётся неизменной - При деактивации тег остаётся привязан к товарам в БД - Просто скрывается в интерфейсе - При реактивации вновь становится видимым 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -154,7 +154,9 @@
|
||||
<td>
|
||||
{% if product.tags.all %}
|
||||
{% for tag in product.tags.all %}
|
||||
<span class="badge bg-secondary">{{ tag.name }}</span>
|
||||
{% if tag.is_active %}
|
||||
<span class="badge bg-secondary">{{ tag.name }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
-
|
||||
|
||||
@@ -104,7 +104,9 @@
|
||||
<h6>Теги:</h6>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
{% for tag in kit.tags.all %}
|
||||
{% if tag.is_active %}
|
||||
<span class="badge bg-secondary">{{ tag.name }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -87,11 +87,13 @@
|
||||
<span class="badge bg-info">{{ tag.kits_count }}</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if tag.is_active %}
|
||||
<span class="badge bg-success">Активен</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">Неактивен</span>
|
||||
{% endif %}
|
||||
<div class="form-check form-switch" style="transform: scale(1.3); transform-origin: left;">
|
||||
<input class="form-check-input tag-status-switch"
|
||||
type="checkbox"
|
||||
id="tag-status-{{ tag.pk }}"
|
||||
data-tag-id="{{ tag.pk }}"
|
||||
{% if tag.is_active %}checked{% endif %}>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
@@ -241,6 +243,45 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Обработчик переключения статуса тега
|
||||
document.querySelectorAll('.tag-status-switch').forEach(toggle => {
|
||||
toggle.addEventListener('click', async function(e) {
|
||||
e.preventDefault(); // Предотвращаем стандартное поведение checkbox
|
||||
|
||||
const tagId = this.dataset.tagId;
|
||||
const toggleSwitch = this;
|
||||
const wasChecked = toggleSwitch.checked; // Сохраняем ТЕКУЩЕЕ состояние
|
||||
|
||||
try {
|
||||
// Отправляем AJAX запрос
|
||||
const apiUrl = `/products/api/tags/${tagId}/toggle/`;
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': '{{ csrf_token }}'
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
// Устанавливаем переключатель в НОВОЕ состояние согласно ответу сервера
|
||||
toggleSwitch.checked = data.is_active;
|
||||
|
||||
// Показываем сообщение об успехе
|
||||
showMessage(data.message, 'success');
|
||||
} else {
|
||||
// Переключатель остаётся в исходном состоянии (мы его не меняли)
|
||||
showMessage(data.error || 'Ошибка при обновлении тега', 'danger');
|
||||
}
|
||||
} catch (error) {
|
||||
// При ошибке сети - переключатель остаётся как был
|
||||
showMessage('Ошибка сети: ' + error.message, 'danger');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user