diff --git a/frontend/script.js b/frontend/script.js index a519ccf..450e80f 100644 --- a/frontend/script.js +++ b/frontend/script.js @@ -37,8 +37,9 @@ async function fetchTasks() { function addTaskToDOM(task) { const li = document.createElement('li'); li.innerHTML = ` - ${task.title} + ${task.title}
+
@@ -73,4 +74,90 @@ async function deleteTask(id) { fetchTasks(); } +function editTask(id) { + const span = document.querySelector(`span[data-task-id="${id}"]`); + if (!span) return; + + const currentTitle = span.textContent; + const wasCompleted = span.classList.contains('completed'); + + // Create input field + const input = document.createElement('input'); + input.type = 'text'; + input.value = currentTitle; + input.className = 'edit-input'; + input.setAttribute('data-task-id', id); + + // Create save button + const saveBtn = document.createElement('button'); + saveBtn.textContent = '✓'; + saveBtn.className = 'save-btn'; + saveBtn.title = 'Save changes'; + saveBtn.onclick = () => saveEdit(id); + + // Create cancel button + const cancelBtn = document.createElement('button'); + cancelBtn.textContent = '✕'; + cancelBtn.className = 'cancel-btn'; + cancelBtn.title = 'Cancel editing'; + cancelBtn.onclick = () => cancelEdit(id, currentTitle, wasCompleted); + + // Replace span with input + span.replaceWith(input); + + // Replace action buttons with save/cancel buttons + const buttonDiv = input.parentElement.querySelector('div'); + buttonDiv.innerHTML = ''; + buttonDiv.appendChild(saveBtn); + buttonDiv.appendChild(cancelBtn); + + // Focus input and select text + input.focus(); + input.select(); + + // Allow Enter key to save + input.addEventListener('keypress', (e) => { + if (e.key === 'Enter') { + saveEdit(id); + } + }); + + // Allow Escape key to cancel + input.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + cancelEdit(id, currentTitle, wasCompleted); + } + }); +} + +async function saveEdit(id) { + const input = document.querySelector(`input[data-task-id="${id}"]`); + if (!input) return; + + const newTitle = input.value.trim(); + + // Validate that title is not empty + if (!newTitle) { + alert('El título de la tarea no puede estar vacío'); + input.focus(); + return; + } + + try { + await fetch(`${API_URL}/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ title: newTitle }) + }); + fetchTasks(); + } catch (error) { + alert('Error al actualizar la tarea'); + console.error(error); + } +} + +function cancelEdit(id, originalTitle, wasCompleted) { + fetchTasks(); +} + fetchTasks(); diff --git a/frontend/style.css b/frontend/style.css index d351594..be746d9 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -173,6 +173,42 @@ li button:hover { li button:active { background: var(--button-active-bg); } +.edit-input { + flex: 1; + padding: 0.5em 0.75em; + border: 2px solid var(--primary-color); + border-radius: 4px; + background: var(--input-bg); + color: var(--text-color); + font-size: 1.05em; + outline: none; + transition: box-shadow 0.2s; +} +.edit-input:focus { + box-shadow: 0 0 0 3px var(--input-focus-shadow); +} +.save-btn { + background: #4caf50 !important; + color: white !important; + border-radius: 4px !important; + width: auto !important; + padding: 0 0.75em !important; + font-weight: 500; +} +.save-btn:hover { + background: #45a049 !important; +} +.cancel-btn { + background: #f44336 !important; + color: white !important; + border-radius: 4px !important; + width: auto !important; + padding: 0 0.75em !important; + font-weight: 500; +} +.cancel-btn:hover { + background: #da190b !important; +} @media (max-width: 600px) { body { max-width: 100vw;