refactor(orders): extract form cleanup to reusable module

Moved empty order items cleanup logic from order_form.html to a dedicated
order_form_cleanup.js module for better code organization.

Changes:
- Created order_form_cleanup.js with initOrderFormCleanup() function (~136 lines)
  - Automatically removes empty order item forms before submit
  - Handles both new and saved forms differently
  - Updates TOTAL_FORMS and reindexes remaining forms
  - Compatible with Django formsets

- Updated order_form.html:
  - Added order_form_cleanup.js include
  - Added initialization call for #order-form
  - Removed inline cleanup code (~111 lines)

Benefits:
- Cleaner template (111 lines removed)
- Reusable across other formset-based forms
- Easier to test and maintain
- Consistent with other extracted modules

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-23 16:10:57 +03:00
parent 98501c1c26
commit 5de1ae9bb9
2 changed files with 141 additions and 111 deletions

View File

@@ -875,119 +875,11 @@
</div>
</div>
<!-- Order Form Cleanup -->
<script src="{% static 'orders/js/order_form_cleanup.js' %}"></script>
<script>
// Автоматическая очистка полностью пустых форм товаров перед отправкой
document.addEventListener('DOMContentLoaded', function() {
const orderForm = document.getElementById('order-form');
if (!orderForm) return;
// Обработчик submit - очищаем пустые строки перед валидацией
orderForm.addEventListener('submit', function(e) {
console.log('[Form Cleanup] Начало очистки пустых форм товаров');
// Находим все формы товаров
const itemForms = Array.from(document.querySelectorAll('.order-item-form'));
console.log('[Form Cleanup] Найдено форм:', itemForms.length);
// Собираем формы для удаления
const formsToRemove = [];
itemForms.forEach((form, formIndex) => {
// Пропускаем уже удалённые формы
if (form.classList.contains('deleted')) {
console.log(`[Form Cleanup] Форма ${formIndex}: уже удалена, пропуск`);
return;
}
// Находим поля
const productField = form.querySelector('[name$="-product"]');
const kitField = form.querySelector('[name$="-product_kit"]');
const quantityField = form.querySelector('[name$="-quantity"]');
const priceField = form.querySelector('[name$="-price"]');
const idField = form.querySelector('[name$="-id"]');
// Проверяем значения (пустота = нет значения или значение пустое)
const hasProduct = productField && productField.value && productField.value.trim();
const hasKit = kitField && kitField.value && kitField.value.trim();
const hasQuantity = quantityField && quantityField.value && quantityField.value.trim();
const hasPrice = priceField && priceField.value && priceField.value.trim();
console.log(`[Form Cleanup] Форма ${formIndex}:`);
console.log(` - product: ${hasProduct || '(пусто)'}`);
console.log(` - kit: ${hasKit || '(пусто)'}`);
console.log(` - quantity: ${hasQuantity || '(пусто)'}`);
console.log(` - price: ${hasPrice || '(пусто)'}`);
// Если ВСЁ пусто — это мусорная строка, удаляем
const isCompletelyEmpty = !hasProduct && !hasKit && !hasQuantity && !hasPrice;
console.log(` - Полностью пустая? ${isCompletelyEmpty}`);
if (isCompletelyEmpty) {
// Если есть ID (сохранённая позиция) — помечаем на удаление
if (idField && idField.value) {
console.log(` - Действие: помечаем DELETE (есть ID: ${idField.value})`);
const deleteCheckbox = form.querySelector('input[name$="-DELETE"]');
if (deleteCheckbox) {
deleteCheckbox.checked = true;
}
form.classList.add('deleted');
form.style.display = 'none';
} else {
console.log(` - Действие: помечаем для удаления из formset (нет ID)`);
// Новая несохранённая форма — помечаем для удаления
formsToRemove.push(form);
}
} else {
console.log(` - Действие: оставляем (не пустая, пойдёт на валидацию)`);
}
});
// Удаляем помеченные формы и пересчитываем индексы
if (formsToRemove.length > 0) {
console.log(`[Form Cleanup] Удаление ${formsToRemove.length} пустых форм...`);
// Удаляем формы из DOM
formsToRemove.forEach(form => form.remove());
// Обновляем TOTAL_FORMS
const totalFormsInput = document.querySelector('[name="items-TOTAL_FORMS"]');
if (totalFormsInput) {
const oldTotal = parseInt(totalFormsInput.value);
const newTotal = oldTotal - formsToRemove.length;
console.log(`[Form Cleanup] Обновление TOTAL_FORMS: ${oldTotal}${newTotal}`);
totalFormsInput.value = newTotal;
}
// Пересчитываем индексы оставшихся форм
const remainingForms = Array.from(document.querySelectorAll('.order-item-form:not(.deleted)'));
console.log(`[Form Cleanup] Пересчёт индексов для ${remainingForms.length} оставшихся форм...`);
remainingForms.forEach((form, newIndex) => {
// Находим все поля с name="items-N-..."
const fields = form.querySelectorAll('[name^="items-"]');
fields.forEach(field => {
const name = field.getAttribute('name');
// Меняем индекс: items-СТАРЫЙ-поле → items-НОВЫЙ-поле
const newName = name.replace(/^items-\d+/, `items-${newIndex}`);
if (name !== newName) {
console.log(`[Form Cleanup] Переименование: ${name}${newName}`);
field.setAttribute('name', newName);
// Обновляем ID тоже (для связи с label)
if (field.id) {
const newId = field.id.replace(/^id_items-\d+/, `id_items-${newIndex}`);
field.setAttribute('id', newId);
}
}
});
});
}
console.log('[Form Cleanup] Очистка завершена');
// Всё остальное идёт на валидацию Django как есть
});
window.initOrderFormCleanup('#order-form');
});
</script>