From 23a38d42c2ae1a1a4236024cb884fb8e038f81f6 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 14 May 2025 18:25:53 +0200 Subject: [PATCH] Modal view when you edit a todo --- app.js | 56 +++++++++++++-- modal.js | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 239 insertions(+), 23 deletions(-) diff --git a/app.js b/app.js index 40aad86..4d480b2 100644 --- a/app.js +++ b/app.js @@ -1,8 +1,11 @@ // --- Basic Todo Model --- const STORAGE_KEY = 'todos-v1'; const CATEGORY_KEY = 'todo-categories'; -let todos = []; -let categories = []; +window.todos = window.todos || []; +window.categories = window.categories || []; +// For backward compatibility, assign to local variables as references +let todos = window.todos; +let categories = window.categories; function loadTodos() { todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]'); @@ -217,15 +220,53 @@ function renderTodos() { th.addEventListener('click', () => sortTodos(th.dataset.col)); }); // Add modal editing listeners - document.querySelectorAll('.todos-table td[data-editable="true"]').forEach(td => { + // Attach popup modal to ID cell only + document.querySelectorAll('.todo-id-cell').forEach(td => { + console.log('[TodoApp] Attaching click handler to ID cell:', td); td.addEventListener('click', function(e) { + const todoId = +td.dataset.id; const rowIdx = +td.dataset.row; - const key = td.dataset.key; - if (window.showEditTodoModal) { - window.showEditTodoModal(rowIdx, key); + console.log('[TodoApp] ID cell clicked. todoId:', todoId, 'rowIdx:', rowIdx); + console.log('[TodoApp] window.showEditTodoModal available:', typeof window.showEditTodoModal); + console.log('[TodoApp] window.showEditTodoModal value:', window.showEditTodoModal); + + // Find the todo by ID instead of row index + const todoIndex = todos.findIndex(t => t.id === todoId); + console.log('[TodoApp] Found todo at index:', todoIndex); + + if (todoIndex === -1) { + console.error('[TodoApp] Todo not found with ID:', todoId); + alert('Error: Todo not found. Please refresh the page.'); + return; } + + // Force set the function if needed + if (typeof showEditTodoModal === 'function' && typeof window.showEditTodoModal !== 'function') { + console.log('[TodoApp] Setting window.showEditTodoModal from local showEditTodoModal'); + window.showEditTodoModal = showEditTodoModal; + } + + if (typeof window.showEditTodoModal === 'function') { + try { + console.log('[TodoApp] Calling window.showEditTodoModal with todoIndex:', todoIndex); + window.showEditTodoModal(todoIndex, 'id'); + console.log('[TodoApp] Editing via popup modal.'); + } catch (err) { + console.warn('[TodoApp] Popup modal error:', err); + console.error(err); + } + } else { + console.error('[TodoApp] showEditTodoModal is not a function:', window.showEditTodoModal); + alert('Error: Edit modal function not available. Please refresh the page.'); + } + e.stopPropagation(); }); }); + // Add inline editing to all other editable cells + document.querySelectorAll('.todos-table td[data-editable="true"]').forEach(td => { + if (td.classList.contains('todo-id-cell')) return; // skip ID, handled above + td.addEventListener('click', handleCellEdit); + }); } function renderEditableCell(todo, key, rowIdx) { @@ -243,7 +284,8 @@ function renderEditableCell(todo, key, rowIdx) { if (key === 'coms' && value) value = `Link`; if (key === 'link' && value) value = `Link`; if (key === 'status') return `${todo.status || ''}`; - if (nonEditable.includes(key)) return `${todo[key]}`; + if (key === 'id') return `${todo[key]}`; +if (nonEditable.includes(key)) return `${todo[key]}`; return `${value}`; } diff --git a/modal.js b/modal.js index 5b0e8b0..38d668d 100644 --- a/modal.js +++ b/modal.js @@ -2,18 +2,103 @@ // Create and show a modal with the Add/Edit Todo form, focusing the relevant field function showEditTodoModal(rowIdx, key) { - // Find the todo - const todo = window.todos[rowIdx]; - if (!todo) return; + 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); + } - // Build modal overlay + // 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 = ` -