// document-fields.js - Скрипт для управления полями документа в задачах (function() { 'use strict'; // Конфигурация const CONFIG = { modalId: 'documentFieldsModal', modalStyles: ` `, buttonStyles: ` ` }; // Текущий пользователь let currentUser = null; // Получение текущего пользователя async function getCurrentUser() { try { const response = await fetch('/api/user'); const data = await response.json(); if (data.user) { currentUser = data.user; console.log('✅ DocumentFields: текущий пользователь', currentUser); } return currentUser; } catch (error) { console.error('❌ DocumentFields: ошибка получения пользователя', error); return null; } } // Создание модального окна function createModal() { // Добавляем стили if (!document.getElementById('document-fields-styles')) { const styleElement = document.createElement('div'); styleElement.id = 'document-fields-styles'; styleElement.innerHTML = CONFIG.modalStyles + CONFIG.buttonStyles; document.head.appendChild(styleElement); } // Проверяем, существует ли уже модальное окно if (document.getElementById(CONFIG.modalId)) { return; } const modalHTML = `

📄 Реквизиты документа

`; document.body.insertAdjacentHTML('beforeend', modalHTML); } // Открытие модального окна async function openModal(taskId) { const modal = document.getElementById(CONFIG.modalId); if (!modal) { createModal(); } const modalElement = document.getElementById(CONFIG.modalId); const form = document.getElementById('documentFieldsForm'); const loading = document.getElementById('documentFieldsLoading'); const errorDiv = document.getElementById('documentFieldsError'); const messageDiv = document.getElementById('documentFieldsMessage'); // Скрываем предыдущие сообщения errorDiv.style.display = 'none'; messageDiv.style.display = 'none'; // Показываем загрузку form.style.display = 'none'; loading.style.display = 'block'; // Активируем модальное окно modalElement.classList.add('active'); // Устанавливаем ID задачи document.getElementById('documentTaskId').textContent = taskId; // Устанавливаем автора (логин текущего пользователя) const authorInput = document.getElementById('documentAuthor'); if (currentUser) { authorInput.value = currentUser.login || ''; } try { // Загружаем текущие значения const response = await fetch(`/api/tasks/${taskId}/document-fields`); if (!response.ok) { throw new Error('Ошибка загрузки данных'); } const result = await response.json(); if (result.success) { document.getElementById('documentNumber').value = result.data.document_n || ''; document.getElementById('documentDate').value = result.data.document_d || ''; // Автор из БД может отличаться от текущего пользователя if (result.data.document_a && !authorInput.value) { authorInput.value = result.data.document_a; } } } catch (error) { console.error('❌ Ошибка загрузки полей документа:', error); showError('Ошибка загрузки данных: ' + error.message); } finally { // Скрываем загрузку, показываем форму loading.style.display = 'none'; form.style.display = 'block'; } } // Закрытие модального окна function closeModal() { const modal = document.getElementById(CONFIG.modalId); if (modal) { modal.classList.remove('active'); } } // Показать ошибку function showError(message) { const errorDiv = document.getElementById('documentFieldsError'); errorDiv.textContent = message; errorDiv.style.display = 'block'; setTimeout(() => { errorDiv.style.display = 'none'; }, 5000); } // Показать успех function showSuccess(message) { const messageDiv = document.getElementById('documentFieldsMessage'); messageDiv.textContent = message; messageDiv.style.display = 'block'; setTimeout(() => { messageDiv.style.display = 'none'; closeModal(); }, 2000); } // Валидация даты function validateDate(dateStr) { if (!dateStr) return true; // Пустая дата допустима // Проверка формата ДД.ММ.ГГГГ const datePattern = /^(\d{2})\.(\d{2})\.(\d{4})$/; if (!datePattern.test(dateStr)) { return 'Неверный формат даты. Используйте ДД.ММ.ГГГГ'; } const [, day, month, year] = dateStr.match(datePattern); const date = new Date(year, month - 1, day); if (date.getDate() != day || date.getMonth() + 1 != month || date.getFullYear() != year) { return 'Некорректная дата'; } return true; } // Сохранение полей async function saveFields() { const taskId = document.getElementById('documentTaskId').textContent; const document_n = document.getElementById('documentNumber').value.trim(); let document_d = document.getElementById('documentDate').value.trim(); const document_a = document.getElementById('documentAuthor').value.trim() || currentUser?.login; // Валидация даты if (document_d) { const dateValidation = validateDate(document_d); if (dateValidation !== true) { showError(dateValidation); return; } } // Показываем загрузку const saveBtn = document.querySelector('.document-fields-btn.save'); const originalText = saveBtn.textContent; saveBtn.textContent = 'Сохранение...'; saveBtn.disabled = true; try { const response = await fetch(`/api/tasks/${taskId}/document-fields`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ document_n: document_n || null, document_d: document_d || null, document_a: document_a || null }) }); const result = await response.json(); if (response.ok && result.success) { showSuccess('✅ Поля документа сохранены'); // Обновляем отображение в карточке задачи, если есть updateTaskCardDisplay(taskId, result.data); } else { showError(result.error || 'Ошибка сохранения'); } } catch (error) { console.error('❌ Ошибка сохранения:', error); showError('Ошибка сети: ' + error.message); } finally { saveBtn.textContent = originalText; saveBtn.disabled = false; } } // Обновление отображения в карточке задачи function updateTaskCardDisplay(taskId, data) { const taskCards = document.querySelectorAll(`[data-task-id="${taskId}"]`); taskCards.forEach(card => { // Ищем или создаем контейнер для полей документа let docContainer = card.querySelector('.document-fields-display'); if (!docContainer) { docContainer = document.createElement('div'); docContainer.className = 'document-fields-display'; // Вставляем после заголовка или в подходящее место const header = card.querySelector('.task-header'); if (header) { header.after(docContainer); } else { card.prepend(docContainer); } } // Формируем HTML для отображения let displayHTML = '
'; if (data.document_n) { displayHTML += `№: ${data.document_n}`; } if (data.document_d) { displayHTML += `Дата: ${data.document_d}`; } if (data.document_a) { displayHTML += `Автор: ${data.document_a}`; } if (!data.document_n && !data.document_d) { displayHTML += 'Нет данных документа'; } displayHTML += '
'; docContainer.innerHTML = displayHTML; }); } // Добавление кнопки в карточки задач function addDocumentFieldsButtons() { if (!currentUser) return; document.querySelectorAll('[data-task-id]').forEach(card => { // Проверяем, есть ли уже кнопка if (card.querySelector('.document-fields-btn-icon')) return; const taskId = card.dataset.taskId; // Ищем контейнер action-buttons const actionsContainer = card.querySelector('.action-buttons, .task-actions'); if (actionsContainer) { const btn = document.createElement('button'); btn.className = 'document-fields-btn-icon document'; btn.innerHTML = '📄 Реквизиты'; btn.onclick = (e) => { e.stopPropagation(); window.documentFields.openModal(taskId); }; btn.title = 'Редактировать реквизиты документа'; actionsContainer.appendChild(btn); } }); } // Наблюдатель за изменениями DOM function observeDOM() { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { window.documentFields.addButtons(); } }); }); observer.observe(document.body, { childList: true, subtree: true }); } // Инициализация async function init() { console.log('🔄 DocumentFields module initializing...'); // Получаем текущего пользователя await getCurrentUser(); // Создаем модальное окно createModal(); // Добавляем кнопки на существующие карточки setTimeout(() => { window.documentFields.addButtons(); }, 1000); // Запускаем наблюдение за DOM observeDOM(); console.log('✅ DocumentFields module loaded'); } // Экспортируем функции в глобальную область window.documentFields = { openModal, closeModal, saveFields, addButtons: addDocumentFieldsButtons, init }; // Запускаем инициализацию после загрузки DOM if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();