Skip to content

Agregar funcionalidad de edición de título de tareas - #12

Open
saulCleverit with Claude wants to merge 1 commit into
mainfrom
claude/add-edit-task-title-functionality
Open

Agregar funcionalidad de edición de título de tareas#12
saulCleverit with Claude wants to merge 1 commit into
mainfrom
claude/add-edit-task-title-functionality

Conversation

@Claude

@Claude Claude AI commented Apr 1, 2026

Copy link
Copy Markdown
  • Add edit button to each task in the frontend UI
  • Implement edit mode with inline editing for task title
  • Add validation to ensure new title is not empty
  • Update frontend JavaScript to handle edit functionality
  • Add CSS styling for edit mode and edit button
  • Test the edit functionality
  • Create pull request

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR agrega la edición inline del título de las tareas en el frontend, incorporando UI/UX (botón de editar, modo edición, estilos) y validación básica para evitar títulos vacíos.

Changes:

  • Se añadió un botón de edición por tarea y un modo de edición inline (input + acciones guardar/cancelar).
  • Se implementó la actualización del título vía PUT /api/tasks/:id desde el frontend, con validación de “no vacío”.
  • Se agregaron estilos CSS para el input de edición y botones de guardar/cancelar.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
frontend/script.js Agrega UI de edición inline y lógica para guardar/cancelar cambios del título usando PUT.
frontend/style.css Incorpora estilos para input de edición y botones de guardar/cancelar.

Comment thread frontend/script.js
Comment on lines 37 to 45
function addTaskToDOM(task) {
const li = document.createElement('li');
li.innerHTML = `
<span class="${task.completed ? 'completed' : ''}">${task.title}</span>
<span class="${task.completed ? 'completed' : ''}" data-task-id="${task.id}">${task.title}</span>
<div>
<button onclick="editTask('${task.id}')" title="Edit task">✎</button>
<button onclick="toggleComplete('${task.id}', ${!task.completed})">✓</button>
<button onclick="deleteTask('${task.id}')">✕</button>
</div>

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addTaskToDOM builds the task row via innerHTML and interpolates task.title directly. Since titles come from user input and are served back by the API, this allows HTML/script injection (XSS). Prefer constructing DOM nodes and setting the title via textContent (or escaping) instead of injecting untrusted content into innerHTML.

Copilot uses AI. Check for mistakes.
Comment thread frontend/script.js
Comment on lines +147 to +151
await fetch(`${API_URL}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: newTitle })
});

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saveEdit does not check the HTTP response status. fetch only rejects on network errors, so non-2xx responses will still call fetchTasks() and make failures hard to notice. Capture the response, check res.ok (and optionally parse/display server error details) before refreshing the list.

Suggested change
await fetch(`${API_URL}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: newTitle })
});
const res = await fetch(`${API_URL}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: newTitle })
});
if (!res.ok) {
let errorMessage = 'Error al actualizar la tarea';
try {
const data = await res.json();
if (data && (data.message || data.error)) {
errorMessage = data.message || data.error;
}
} catch (parseError) {
// Ignore JSON parse errors and use the default message
}
alert(errorMessage);
return;
}

Copilot uses AI. Check for mistakes.
Comment thread frontend/script.js
Comment on lines +119 to +120
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Enter key handler uses the keypress event, which is deprecated/inconsistent across browsers for non-printable keys. Use a keydown handler for Enter (and consider calling e.preventDefault() if needed) to make keyboard saving reliable.

Suggested change
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();

Copilot uses AI. Check for mistakes.
Comment thread frontend/script.js
}

function cancelEdit(id, originalTitle, wasCompleted) {
fetchTasks();

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cancelEdit accepts originalTitle and wasCompleted but does not use them, and always re-fetches the full task list. Either remove the unused parameters or restore the original DOM state locally to avoid an unnecessary network request on cancel.

Suggested change
fetchTasks();
// Try to restore the original DOM state locally to avoid a full refetch
const editedElement = document.querySelector(`[data-task-id="${id}"]`);
// If we cannot find the element for some reason, fall back to refetching
if (!editedElement) {
fetchTasks();
return;
}
const li = editedElement.closest('li');
if (!li) {
fetchTasks();
return;
}
// Restore the original markup, mirroring addTaskToDOM
li.innerHTML = `
<span class="${wasCompleted ? 'completed' : ''}" data-task-id="${id}">${originalTitle}</span>
<div>
<button onclick="editTask('${id}')" title="Edit task"></button>
<button onclick="toggleComplete('${id}', ${!wasCompleted})"></button>
<button onclick="deleteTask('${id}')"></button>
</div>
`;

Copilot uses AI. Check for mistakes.
Comment thread frontend/script.js
Comment on lines +42 to 44
<button onclick="editTask('${task.id}')" title="Edit task">✎</button>
<button onclick="toggleComplete('${task.id}', ${!task.completed})">✓</button>
<button onclick="deleteTask('${task.id}')">✕</button>

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new edit button is icon-only (✎) and relies on title. For accessibility/screen readers, add an explicit accessible name (e.g., aria-label="Edit task") and consider doing the same for the other icon-only action buttons for consistency.

Suggested change
<button onclick="editTask('${task.id}')" title="Edit task"></button>
<button onclick="toggleComplete('${task.id}', ${!task.completed})"></button>
<button onclick="deleteTask('${task.id}')"></button>
<button onclick="editTask('${task.id}')" title="Edit task" aria-label="Edit task"></button>
<button onclick="toggleComplete('${task.id}', ${!task.completed})" aria-label="${task.completed ? 'Mark task as incomplete' : 'Mark task as complete'}"></button>
<button onclick="deleteTask('${task.id}')" aria-label="Delete task"></button>

Copilot uses AI. Check for mistakes.
Comment thread frontend/style.css
Comment on lines +190 to +210
.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;

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The save/cancel button styles rely heavily on !important to override the base li button rules. This makes future styling harder and can cause specificity battles. Prefer increasing selector specificity (e.g., li button.save-btn, li button.cancel-btn) or scoping styles so !important isn't needed.

Suggested change
.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;
li button.save-btn {
background: #4caf50;
color: white;
border-radius: 4px;
width: auto;
padding: 0 0.75em;
font-weight: 500;
}
li button.save-btn:hover {
background: #45a049;
}
li button.cancel-btn {
background: #f44336;
color: white;
border-radius: 4px;
width: auto;
padding: 0 0.75em;
font-weight: 500;
}
li button.cancel-btn:hover {
background: #da190b;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants