// Modal logic for editing a todo cell in a popup // Create and show a modal with the Add/Edit Todo form, focusing the relevant field function showEditTodoModal(rowIdx, key) { console.log('[Modal] Opening modal for rowIdx:', rowIdx, 'key:', key); console.log('[Modal] Initial window.todos:', window.todos ? window.todos.length : 'null/undefined'); console.log('[Modal] Initial todos:', todos ? todos.length : 'null/undefined'); // Ensure todos are loaded from localStorage if arrays are empty if (!window.todos || window.todos.length === 0 || !todos || todos.length === 0) { console.log('[Modal] Loading todos from localStorage at modal open'); const storedTodos = localStorage.getItem('todos-v1'); if (storedTodos) { try { window.todos = JSON.parse(storedTodos); todos = window.todos; // Update local reference as well console.log('[Modal] Successfully loaded todos from localStorage:', window.todos.length); } catch (e) { console.error('[Modal] Error parsing todos from localStorage:', e); } } else { console.error('[Modal] No todos found in localStorage under key "todos-v1"'); } } // If called with an index, get the ID from that todo let todoId = null; if (typeof rowIdx === 'number' || !isNaN(Number(rowIdx))) { // First look it up by index if number is within range const numericIdx = Number(rowIdx); if (window.todos && numericIdx >= 0 && numericIdx < window.todos.length) { todoId = window.todos[numericIdx].id; console.log('[Modal] Found todo ID by index in window.todos:', todoId); } // If index doesn't work, use the number directly as ID else { todoId = numericIdx; console.log('[Modal] Using rowIdx directly as todoId:', todoId); } } else if (rowIdx && typeof rowIdx === 'object' && rowIdx.id) { // Handle case where entire todo object is passed todoId = rowIdx.id; console.log('[Modal] Using object.id as todoId:', todoId); } else if (rowIdx) { // Any other non-null value, try to use directly todoId = rowIdx; console.log('[Modal] Using rowIdx as todoId:', todoId); } // Remove any existing modal document.querySelectorAll('.modal').forEach(m => m.remove()); // Always find the todo by ID let todo = null; if (todoId !== null) { console.log('[Modal] Looking for todo with ID:', todoId, 'Type:', typeof todoId); // Debug all todos in the array to see what IDs we have if (window.todos && window.todos.length > 0) { window.todos.forEach((t, idx) => { if (t) console.log(`[Modal] Todo ${idx}: ID=${t.id} (${typeof t.id})`); }); } // More flexible ID comparison logic const findTodoById = (arr, id) => { if (!arr || !Array.isArray(arr)) return null; return arr.find(t => { if (!t) return false; const idStr = String(id).trim(); const tIdStr = String(t.id).trim(); const idNum = Number(id); const tIdNum = Number(t.id); return t.id === id || // Direct comparison tIdStr === idStr || // String comparison (!isNaN(idNum) && !isNaN(tIdNum) && idNum === tIdNum); // Number comparison }); }; todo = findTodoById(window.todos, todoId); if (todo) console.log('[Modal] Found todo by ID in window.todos:', todo); if (!todo && todos !== window.todos) { todo = findTodoById(todos, todoId); if (todo) console.log('[Modal] Found todo by ID in local todos:', todo); } } if (!todo && todoId !== null) { console.error('[Modal] Todo not found for ID:', todoId); alert('Error: Could not find the todo to edit. Please refresh the page and try again.'); return; } // Build modal overlay (same structure as password modal) let modal = document.createElement('div'); modal.className = 'modal'; modal.style.zIndex = 2000; modal.innerHTML = `
`; // Insert modal into the DOM before attaching event listeners document.body.appendChild(modal); document.body.style.overflow = 'hidden'; // Close modal on overlay click or close/cancel button function closeModal() { modal.remove(); document.body.style.overflow = ''; } modal.onclick = (e) => { if (e.target === modal) closeModal(); }; modal.querySelector('#modal-close-btn').onclick = closeModal; // Save changes const modalForm = modal.querySelector('#modal-todo-form'); modalForm.onsubmit = function(evt) { console.log('[Modal] Save button clicked'); evt.preventDefault(); // Get form data and create an updated todo object const formData = new FormData(this); const updated = {}; for (let [k, v] of formData.entries()) { if (k !== 'id') updated[k] = v; // Never overwrite the ID } // Type conversions updated.urgent = parseInt(updated.urgent) || 1; updated.importance = parseInt(updated.importance) || 1; updated.prio = updated.urgent * updated.importance; updated.timeEstimation = parseInt(updated.timeEstimation) || 0; updated.actualTime = parseInt(updated.actualTime) || 0; // Get the original ID from the todo we found at modal open time let todoId = todo.id; console.log('[Modal] Updating todo with ID:', todoId); // Create a new complete todo object with the updates const updatedTodo = { ...todo, ...updated, id: todoId }; // DIRECT APPROACH: Simply replace the entire todos array try { // Get the todos directly from localStorage let allTodos = []; try { const stored = localStorage.getItem('todos-v1'); if (stored) { allTodos = JSON.parse(stored); console.log('[Modal] Successfully loaded', allTodos.length, 'todos from localStorage'); } } catch (err) { console.error('[Modal] Error loading todos from localStorage:', err); } // If we couldn't load from localStorage, use window.todos if (!allTodos || !allTodos.length) { allTodos = Array.isArray(window.todos) ? [...window.todos] : []; console.log('[Modal] Using window.todos instead, length:', allTodos.length); } // Find the todo by ID let found = false; for (let i = 0; i < allTodos.length; i++) { if (allTodos[i] && String(allTodos[i].id) === String(todoId)) { // Replace the todo with our updated version allTodos[i] = updatedTodo; found = true; console.log('[Modal] Updated todo at index', i); break; } } if (!found) { console.warn('[Modal] Todo with ID', todoId, 'not found in array, adding it'); allTodos.push(updatedTodo); } // Save the updated todos back to localStorage localStorage.setItem('todos-v1', JSON.stringify(allTodos)); console.log('[Modal] Saved todos to localStorage'); // Update both global and local todos arrays window.todos = allTodos; todos = allTodos; // Update the UI if (typeof renderTodos === 'function') { renderTodos(); console.log('[Modal] UI updated with new todos'); } // Close the modal closeModal(); return; } catch (err) { console.error('[Modal] Error saving todo:', err); const errMsg = modal.querySelector('#modal-error-msg'); if (errMsg) { errMsg.textContent = 'Error saving todo: ' + err.message; errMsg.style.display = 'block'; } } closeModal(); }; // Debug: log if handler is attached console.log('[Modal] onsubmit handler attached to modal-todo-form'); // Insert and focus correct field document.body.appendChild(modal); document.body.style.overflow = 'hidden'; setTimeout(() => { let focusId = 'modal-' + key.replace(/([A-Z])/g, '-$1').toLowerCase(); let focusElem = modal.querySelector('#' + focusId); if (focusElem) focusElem.focus(); }, 80); } // Immediately attach to window for use in app.js window.showEditTodoModal = showEditTodoModal; // Also attach on DOMContentLoaded for safety document.addEventListener('DOMContentLoaded', () => { window.showEditTodoModal = showEditTodoModal; console.log('[Modal] showEditTodoModal attached to window object'); });