diff --git a/backend/templates/procurement/equipment_list.html b/backend/templates/procurement/equipment_list.html index 11d9dc24..2d744019 100644 --- a/backend/templates/procurement/equipment_list.html +++ b/backend/templates/procurement/equipment_list.html @@ -13,6 +13,15 @@ {# ===== ШАПКА СТРАНИЦЫ ===== #} {% include "includes/components/page_header.html" with icon="bi-laptop" title="Оборудование" search_id="eqSearch" search_placeholder="Поиск по названию или инв. номеру..." has_filters=True filters_target="eqFilters" filters_template="procurement/_equipment_filters.html" create_as_card=True create_modal="equipmentCreateModal" create_text="Добавить оборудование" %} + {# ===== КНОПКА УПРАВЛЕНИЯ КАТЕГОРИЯМИ ===== #} + {% if can_manage %} +
+ +
+ {% endif %} + {# ===== СЕТКА ОБОРУДОВАНИЯ ===== #}
{% if equipment_list %} @@ -467,6 +476,76 @@
+{# ===== МОДАЛКА УПРАВЛЕНИЯ КАТЕГОРИЯМИ ===== #} + + {% endblock %} {% block extra_js %} @@ -705,5 +784,125 @@ submitBtn.innerHTML = 'Сохранить изменения'; } }); + + // === УПРАВЛЕНИЕ КАТЕГОРИЯМИ === + // Загрузка списка категорий + async function loadCategories() { + const list = document.getElementById('categoriesList'); + list.innerHTML = '
'; + + try { + const resp = await fetch('/api/procurement/equipment-categories/'); + if (resp.ok) { + const categories = await resp.json(); + + if (categories.length === 0) { + list.innerHTML = '
Категорий пока нет
'; + return; + } + + let html = '
'; + categories.forEach(cat => { + html += ` +
+
+ + ${cat.name} + ${cat.description ? `
${cat.description}` : ''} +
+ +
+ `; + }); + html += '
'; + list.innerHTML = html; + } else { + list.innerHTML = '
Ошибка загрузки
'; + } + } catch (e) { + console.error(e); + list.innerHTML = '
Ошибка сети
'; + } + } + + // Загрузка при открытии модала + document.getElementById('categoryManageModal')?.addEventListener('show.bs.modal', loadCategories); + + // Создание новой категории + document.getElementById('categoryCreateForm')?.addEventListener('submit', async (e) => { + e.preventDefault(); + + const name = document.getElementById('catName').value.trim(); + const icon = document.getElementById('catIcon').value.trim(); + const description = document.getElementById('catDescription').value.trim(); + + if (!name) return; + + const submitBtn = e.target.querySelector('[type="submit"]'); + submitBtn.disabled = true; + submitBtn.innerHTML = 'Создание...'; + + try { + const resp = await fetch('/api/procurement/equipment-categories/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': document.querySelector('[name="csrfmiddlewaretoken"]').value + }, + body: JSON.stringify({ name, icon: icon || null, description: description || '' }) + }); + + if (resp.ok) { + // Очистить форму + document.getElementById('catName').value = ''; + document.getElementById('catIcon').value = ''; + document.getElementById('catDescription').value = ''; + + // Перезагрузить список + await loadCategories(); + + // Обновить выпадающие списки категорий в формах + location.reload(); + } else { + const err = await resp.json(); + alert(err.name?.[0] || err.detail || 'Ошибка создания категории'); + } + } catch (e) { + console.error(e); + alert('Ошибка сети'); + } finally { + submitBtn.disabled = false; + submitBtn.innerHTML = 'Добавить'; + } + }); + + // Удаление категории + async function deleteCategory(id, name) { + if (!confirm(`Удалить категорию "${name}"?\n\nВнимание: это возможно только если к категории не привязано оборудование.`)) { + return; + } + + try { + const resp = await fetch(`/api/procurement/equipment-categories/${id}/`, { + method: 'DELETE', + headers: { + 'X-CSRFToken': document.querySelector('[name="csrfmiddlewaretoken"]').value + } + }); + + if (resp.ok || resp.status === 204) { + await loadCategories(); + alert('Категория удалена'); + } else { + const err = await resp.json(); + alert(err.detail || 'Ошибка удаления. Возможно, к категории привязано оборудование.'); + } + } catch (e) { + console.error(e); + alert('Ошибка сети'); + } + } {% endblock %}