From c94f21b01e268b0ed1aa2f86e9aaa6012dfa724c Mon Sep 17 00:00:00 2001 From: Vladimir Tomashevskiy Date: Sun, 8 Feb 2026 18:23:59 +0000 Subject: [PATCH] Implement proper AJAX handling for subtasks - Fix DOM manipulation to handle empty subtasks list - Create subtasks list dynamically if it doesn't exist - Update UI elements without page reload - Handle all edge cases for add/delete/toggle operations --- app/Modules/Tasks/Views/tasks/show.twig | 97 ++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 9 deletions(-) diff --git a/app/Modules/Tasks/Views/tasks/show.twig b/app/Modules/Tasks/Views/tasks/show.twig index d2a16aa..c7fbd8d 100644 --- a/app/Modules/Tasks/Views/tasks/show.twig +++ b/app/Modules/Tasks/Views/tasks/show.twig @@ -246,8 +246,50 @@ function addSubtask(event, taskId) { .then(response => response.json()) .then(data => { if (data.success) { - // Обновляем страницу вместо манипуляций с DOM - location.reload(); + // Находим контейнер для подзадач + let list = document.getElementById('subtasks-list'); + + // Если списка ещё нет (был пустой), создаём его + if (!list) { + const cardBody = form.closest('.card-body'); + const emptyMessage = cardBody.querySelector('p.text-muted.text-center'); + + // Создаём новый список подзадач + const newList = document.createElement('ul'); + newList.className = 'list-group list-group-flush mb-3'; + newList.id = 'subtasks-list'; + + // Вставляем перед формой + cardBody.insertBefore(newList, form); + + // Удаляем сообщение "Подзадач пока нет" + if (emptyMessage) { + emptyMessage.remove(); + } + + list = newList; + } + + // Создаём новую подзадачу + const newItem = document.createElement('li'); + newItem.className = 'list-group-item d-flex align-items-center gap-2'; + newItem.setAttribute('data-subtask-id', data.subtask_id); + newItem.innerHTML = ` + + ${title} + + `; + + // Добавляем в список + list.appendChild(newItem); + + // Очищаем поле ввода + input.value = ''; + + // Обновляем счётчик + updateSubtasksCount(); } else { alert(data.error || 'Ошибка при создании подзадачи'); } @@ -259,9 +301,15 @@ function addSubtask(event, taskId) { } function updateSubtasksCount() { - const count = document.querySelectorAll('#subtasks-list li').length; - const completed = document.querySelectorAll('#subtasks-list li input:checked').length; - const badge = document.querySelector('#subtasks-list ~ .badge'); + const list = document.getElementById('subtasks-list'); + if (!list) return; + + const items = list.querySelectorAll('li'); + const count = items.length; + const completed = list.querySelectorAll('li input:checked').length; + + // Обновляем счётчик на заголовке карточки + const badge = document.querySelector('.card-header h5 .badge'); if (badge) { badge.textContent = `${completed}/${count}`; } @@ -281,8 +329,20 @@ function toggleSubtask(taskId, subtaskId) { if (!data.success) { alert(data.error || 'Ошибка'); } else { - // Обновляем страницу для обновления UI - location.reload(); + // Находим чекбокс и обновляем состояние + const checkbox = document.querySelector(`[data-subtask-id="${subtaskId}"] .subtask-checkbox`); + const span = checkbox.nextElementSibling; + + if (checkbox.checked) { + checkbox.checked = false; + span.classList.remove('text-muted', 'text-decoration-line-through'); + } else { + checkbox.checked = true; + span.classList.add('text-muted', 'text-decoration-line-through'); + } + + // Обновляем счётчик + updateSubtasksCount(); } }) .catch(error => { @@ -306,8 +366,27 @@ function deleteSubtask(taskId, subtaskId) { if (!data.success) { alert(data.error || 'Ошибка'); } else { - // Обновляем страницу для обновления UI - location.reload(); + // Удаляем из DOM + const item = document.querySelector(`li[data-subtask-id="${subtaskId}"]`); + if (item) { + item.remove(); + + // Если список пуст, показываем сообщение + const list = document.getElementById('subtasks-list'); + if (list && list.children.length === 0) { + list.remove(); + + // Добавляем сообщение "Подзадач пока нет" + const cardBody = item.closest('.card-body'); + const message = document.createElement('p'); + message.className = 'text-muted text-center mb-3'; + message.textContent = 'Подзадач пока нет'; + cardBody.appendChild(message); + } + + // Обновляем счётчик + updateSubtasksCount(); + } } }) .catch(error => {