Feature s77: Gestor transversal de comentarios, badge cyan y deep-links de tareas
Resumen
PR#57 (2026-05-20, @Esquembri) agrupa 5 mejoras del menú Tareas encadenadas, todas bajo la referencia interna s77. El objetivo central es hacer el módulo de tareas más navegable: los comentarios son visibles desde las tarjetas, existe una vista dedicada para gestionarlos, y los deep-links desde el widget del escritorio funcionan de forma fiable.
Mejoras incluidas
1. Fix race condition: deep-link widget → modal tarea
Problema: al hacer click en una tarjeta del widget KanbanMini (que navega a /tasks?task=N), el modal no se abría. El useEffect que sincronizaba modalTask → URL borraba el parámetro ?task=N antes de que el effect lector pudiera ejecutarse (las tasks todavía estaban loading=true al montar).
Solución (TaskManager.tsx):
// Guard añadido en el useEffect de sincronización modalTask → URL
if (loading && modalTask === null) return;
Además, loading se añadió como dependencia del efecto ([modalTask, loading]) para que se re-evalúe cuando la carga termine.
2. Badge “comentarios” en tarjetas (tinte cyan)
functions/api/tasks/index.ts: subquery añadida al SELECT principal:(SELECT COUNT(*) FROM task_comments WHERE task_id = tasks.id) AS comment_countsrc/lib/types.tsyTaskModal.tsx: campocomment_count?: numberañadido a la interfazTask.TaskKanban.tsxyKanbanMini.tsx: chiptask-link-badge task-link-badge-commentmostrado cuandocomment_count > 0.- CSS (
globals.css): clase.task-link-badge-commentcon tinte cyan (var(--accent-2)al 14%) para distinguirlo visualmente de los badges de emails/eventos Zoho.
.task-link-badge-comment {
background: color-mix(in srgb, var(--accent-2) 14%, transparent);
color: var(--accent-2);
}
3. Gestor transversal de comentarios
Nueva vista en /tasks?view=comments que muestra todos los comentarios del workspace con filtros avanzados.
Componente: src/components/tasks/TaskCommentsView.tsx (333 LOC).
Filtros disponibles en la filter bar:
| Filtro | Tipo | API param |
|---|---|---|
| Buscar en cuerpo | text input | q |
| Autor | select (TEAM_FILTER) | author |
| Destinatario | select (TEAM_FILTER) | target_user |
| Título de tarea | text input | task_title |
| Desde | date input | start_date |
| Hasta | date input | end_date |
Paginación: PAGE_SIZE = 50, botón “Cargar más” (offset acumulativo). El total visible se muestra como N/total comentarios.
Cards clickables: cada article.task-comment-card abre el TaskModal de la tarea origen mediante onOpenTask(associatedTask). Si la tarea ya no está en memoria, navega directamente a /tasks?task=<id>.
Integración en TaskManager:
- Nueva opción en el type
View:'board' | 'list' | 'calendar' | 'comments'. - Tab
{ key: 'comments', label: 'Comentarios' }en la barra de pestañas. - URL persistida:
?view=commentsmediantereplaceState. Al montar, se lee el param?view=para restaurar la vista activa.
4. Botón “Nueva” del widget abre modal de creación
DesktopA.tsx: el botón “Nueva” del widget Tareas cambia de href="/tasks" a href="/tasks?task=new". TaskManager ya leía ese parámetro para abrir el modal en modo CREAR. Texto actualizado a + Nueva.
5. Enlace nota → modal tarea
TaskModal.createAndLinkNote: al crear una nota desde el modal de edición de una tarea existente (cuando task?.id existe), se inyecta al inicio del contenido de la nota:
[Nota asociada a tarea #N](/tasks?task=N)
En la vista preview del cuaderno (modo markdown), el link es clickable y navega a /tasks?task=N, abriendo el modal de edición de esa tarea.
Archivos modificados
| Archivo | Tipo de cambio |
|---|---|
functions/api/tasks/comments.ts | Nuevo — endpoint CF Pages Function |
functions/api/tasks/index.ts | Modificado — añade subquery comment_count |
src/components/tasks/TaskCommentsView.tsx | Nuevo — componente React (333 LOC) |
src/components/tasks/TaskKanban.tsx | Modificado — chip badge comentarios |
src/components/tasks/TaskManager.tsx | Modificado — tab comments, view URL, fix race condition |
src/components/tasks/TaskModal.tsx | Modificado — comment_count en interfaz + inject link nota |
src/components/variants/desktop/DesktopA.tsx | Modificado — botón ?task=new |
src/components/widgets/KanbanMini.tsx | Modificado — chip badge comentarios |
src/lib/types.ts | Modificado — campo comment_count en Task |
src/styles/globals.css | Modificado — .task-link-badge-comment, .task-comment-card |
Estilos CSS introducidos
/* Badge comentarios (tinte cyan) */
.task-link-badge-comment { … }
/* Card gestor transversal — clickable */
.task-comment-card { … }
.task-comment-card:hover { … }
Decisiones de diseño destacadas
- Race condition guard: la solución es mínima y localizada; se prefirió un guard de una línea sobre refactorizar el flujo de efectos completo.
- Separación de endpoint: se creó
functions/api/tasks/comments.tsseparado del index principal para mantener cohesión y facilitar caching/permisos futuros por ruta. - Pattern
{ results, total }: reutiliza el shape de/api/activitypara minimizar código nuevo en el frontend de paginación. target_user_idsLIKE con comillas: previene falsos positivos en nombres cortos (e.g. “Ed” en “Edu”) sin necesitar JSON functions de SQLite.
Véase también
- [[entity—tasks—endpoint—api-tasks-comments]]
- [[entity—tasks—endpoint—api-tasks-index]]