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
This commit is contained in:
parent
bf609257c3
commit
c94f21b01e
|
|
@ -246,8 +246,50 @@ function addSubtask(event, taskId) {
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
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 = `
|
||||||
|
<input type="checkbox" class="form-check-input subtask-checkbox" onchange="toggleSubtask(${taskId}, ${data.subtask_id})">
|
||||||
|
<span class="flex-grow-1">${title}</span>
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm" onclick="deleteSubtask(${taskId}, ${data.subtask_id})" title="Удалить">
|
||||||
|
<i class="fa-solid fa-times"></i>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Добавляем в список
|
||||||
|
list.appendChild(newItem);
|
||||||
|
|
||||||
|
// Очищаем поле ввода
|
||||||
|
input.value = '';
|
||||||
|
|
||||||
|
// Обновляем счётчик
|
||||||
|
updateSubtasksCount();
|
||||||
} else {
|
} else {
|
||||||
alert(data.error || 'Ошибка при создании подзадачи');
|
alert(data.error || 'Ошибка при создании подзадачи');
|
||||||
}
|
}
|
||||||
|
|
@ -259,9 +301,15 @@ function addSubtask(event, taskId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSubtasksCount() {
|
function updateSubtasksCount() {
|
||||||
const count = document.querySelectorAll('#subtasks-list li').length;
|
const list = document.getElementById('subtasks-list');
|
||||||
const completed = document.querySelectorAll('#subtasks-list li input:checked').length;
|
if (!list) return;
|
||||||
const badge = document.querySelector('#subtasks-list ~ .badge');
|
|
||||||
|
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) {
|
if (badge) {
|
||||||
badge.textContent = `${completed}/${count}`;
|
badge.textContent = `${completed}/${count}`;
|
||||||
}
|
}
|
||||||
|
|
@ -281,8 +329,20 @@ function toggleSubtask(taskId, subtaskId) {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
alert(data.error || 'Ошибка');
|
alert(data.error || 'Ошибка');
|
||||||
} else {
|
} 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 => {
|
.catch(error => {
|
||||||
|
|
@ -306,8 +366,27 @@ function deleteSubtask(taskId, subtaskId) {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
alert(data.error || 'Ошибка');
|
alert(data.error || 'Ошибка');
|
||||||
} else {
|
} else {
|
||||||
// Обновляем страницу для обновления UI
|
// Удаляем из DOM
|
||||||
location.reload();
|
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 => {
|
.catch(error => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue