From df3a951beb3a1a39ff36c75589bb9e25acab8da6 Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Sat, 8 Nov 2025 15:45:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20UI=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BE=D0=B7=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=20=D0=B2=20=D1=84=D0=BE=D1=80=D0=BC=D0=B5=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Шаблон order_form.html: - Кнопка "Создать и добавить комплект" рядом с "Добавить товар" - Модальное окно с формой создания временного комплекта: * Поле названия комплекта * Поле описания (опционально) * Динамическое добавление/удаление товаров с Select2 * Поле количества для каждого товара JavaScript функциональность: - addTempKitComponent() - добавление товара в комплект - Select2 с AJAX поиском только товаров (type='product') - Валидация (название обязательно, минимум 1 товар) - AJAX запрос к /orders/temporary-kits/create/ - Автоматическое добавление созданного комплекта в форму заказа - Закрытие модального окна после успешного создания Теперь флорист может: 1. Нажать "Создать и добавить комплект" 2. Ввести название (например "Букет для Анны") 3. Добавить товары с количествами через Select2 4. Нажать "Создать и добавить в заказ" 5. Комплект создается и автоматически добавляется в заказ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../orders/templates/orders/order_form.html | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) diff --git a/myproject/orders/templates/orders/order_form.html b/myproject/orders/templates/orders/order_form.html index cc3a02b..9d737cd 100644 --- a/myproject/orders/templates/orders/order_form.html +++ b/myproject/orders/templates/orders/order_form.html @@ -243,6 +243,9 @@ + @@ -531,6 +534,223 @@ document.addEventListener('DOMContentLoaded', function() { } }); }); + + // === ВРЕМЕННЫЕ КОМПЛЕКТЫ === + + // Модальное окно для создания временного комплекта + const tempKitModal = document.getElementById('tempKitModal'); + const tempKitForm = document.getElementById('temp-kit-form'); + const tempKitComponentsContainer = document.getElementById('temp-kit-components'); + let tempKitComponentIndex = 0; + + // Добавление компонента в временный комплект + document.getElementById('add-temp-kit-component-btn').addEventListener('click', function() { + addTempKitComponent(); + }); + + function addTempKitComponent(productId = '', productName = '', quantity = '1') { + const componentHtml = ` +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ `; + + tempKitComponentsContainer.insertAdjacentHTML('beforeend', componentHtml); + + // Инициализация Select2 для нового компонента + $(`.select2-temp-kit-product[data-component-index="${tempKitComponentIndex}"]`).select2({ + theme: 'bootstrap-5', + width: '100%', + placeholder: 'Выберите товар', + language: 'ru', + dropdownParent: $('#tempKitModal'), + ajax: { + url: '{% url "products:api-search-products-variants" %}', + dataType: 'json', + delay: 250, + data: function(params) { + return { + q: params.term, + type: 'product', // Только товары, не комплекты + page: params.page || 1 + }; + }, + processResults: function(data) { + return { + results: data.results, + pagination: { + more: data.pagination.more + } + }; + }, + cache: true + } + }); + + tempKitComponentIndex++; + } + + // Удаление компонента + tempKitComponentsContainer.addEventListener('click', function(e) { + if (e.target.closest('.remove-temp-kit-component')) { + e.target.closest('.temp-kit-component').remove(); + } + }); + + // Добавляем первый компонент при открытии модального окна + tempKitModal.addEventListener('show.bs.modal', function() { + // Очищаем форму + document.getElementById('temp-kit-name').value = ''; + document.getElementById('temp-kit-description').value = ''; + tempKitComponentsContainer.innerHTML = ''; + tempKitComponentIndex = 0; + + // Добавляем первый пустой компонент + addTempKitComponent(); + }); + + // Создание временного комплекта + document.getElementById('save-temp-kit-btn').addEventListener('click', function() { + const name = document.getElementById('temp-kit-name').value.trim(); + const description = document.getElementById('temp-kit-description').value.trim(); + + if (!name) { + alert('Пожалуйста, укажите название комплекта'); + return; + } + + // Собираем компоненты + const components = []; + document.querySelectorAll('.temp-kit-component').forEach(function(component) { + const select = component.querySelector('.select2-temp-kit-product'); + const quantity = component.querySelector('.temp-kit-quantity').value; + const productId = $(select).val(); + + if (productId && quantity > 0) { + // Убираем префикс "product_" если есть + const cleanId = productId.replace('product_', ''); + components.push({ + product_id: parseInt(cleanId), + quantity: quantity + }); + } + }); + + if (components.length === 0) { + alert('Добавьте хотя бы один товар в комплект'); + return; + } + + // Отправляем AJAX запрос + fetch('{% url "orders:temporary-kit-create" %}', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': '{{ csrf_token }}' + }, + body: JSON.stringify({ + name: name, + description: description, + order_id: {{ form.instance.pk|default:"null" }}, + components: components + }) + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + // Закрываем модальное окно + const modal = bootstrap.Modal.getInstance(tempKitModal); + modal.hide(); + + // Добавляем созданный комплект в форму заказа + addOrderItem(`kit_${data.kit_id}`, 'kit', data.kit_name, data.kit_price, 1); + + // Показываем успешное сообщение + alert(`Комплект "${data.kit_name}" создан и добавлен в заказ!`); + } else { + alert(`Ошибка: ${data.error}`); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Произошла ошибка при создании комплекта'); + }); + }); }); + + + {% endblock %}