From 1b23da7151a8c09af656dd63663918b25cdd4e2a Mon Sep 17 00:00:00 2001 From: Milton Gonzalez Date: Wed, 16 Sep 2026 12:52:00 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20contador=20en=20las=20pesta=C3=B1as=20d?= =?UTF-8?q?e=20Tareas/Comentarios/Documentos=20de=20una=20actividad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Circulo con el numero al lado del nombre de la pestaña: Tareas muestra las pendientes (sin marcar), Comentarios y Documentos el total. Soporte agregado al componente Tabs reutilizable (tab.count), no solo al detalle de actividad. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 7 +++++++ VERSION | 2 +- backend/package.json | 2 +- frontend/package.json | 2 +- frontend/src/components/Tabs.jsx | 1 + .../src/pages/Proyectos/ActivityDetailPanel.jsx | 13 ++++++++++--- frontend/src/styles/app.css | 7 +++++++ 7 files changed, 28 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 454ffd6..674e4af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog - project.linkedcorp.net +## [1.16.0] - 2026-09-16 +### Added +- Contador en un circulo junto al nombre de la pestaña, dentro del detalle de una actividad: + "Tareas" muestra las tareas pendientes (sin marcar como hechas), "Comentarios" y "Documentos" + muestran el total. Se oculta cuando el contador es 0. Soporte agregado al componente `Tabs` + reutilizable (`tab.count`), disponible para cualquier otra pantalla que use pestañas. + ## [1.15.2] - 2026-09-16 ### Fixed - El checkbox de "hecho" de una tarea (y el renombrado en linea) dejaba de reflejarse tras diff --git a/VERSION b/VERSION index 42cf067..15b989e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.15.2 +1.16.0 diff --git a/backend/package.json b/backend/package.json index 46ee020..70750a4 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "project-linkedcorp-backend", - "version": "1.15.2", + "version": "1.16.0", "private": true, "type": "module", "main": "src/server.js", diff --git a/frontend/package.json b/frontend/package.json index 8c8b7eb..1dcacd9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "project-linkedcorp-frontend", "private": true, - "version": "1.15.2", + "version": "1.16.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/Tabs.jsx b/frontend/src/components/Tabs.jsx index 1cbb849..5c6182d 100644 --- a/frontend/src/components/Tabs.jsx +++ b/frontend/src/components/Tabs.jsx @@ -4,6 +4,7 @@ export function Tabs({ tabs, active, onChange }) { {tabs.map((tab) => ( ))} diff --git a/frontend/src/pages/Proyectos/ActivityDetailPanel.jsx b/frontend/src/pages/Proyectos/ActivityDetailPanel.jsx index f697059..796356a 100644 --- a/frontend/src/pages/Proyectos/ActivityDetailPanel.jsx +++ b/frontend/src/pages/Proyectos/ActivityDetailPanel.jsx @@ -8,6 +8,8 @@ import { listTasks, createTask, updateTask, setTaskDone, deleteTask, reorderTask import { promoteTaskToRecurring } from '../../services/recurringTasks.js'; import { listCatalog } from '../../services/catalogs.js'; import { listUsers } from '../../services/users.js'; +import { listComments } from '../../services/comments.js'; +import { listAttachments } from '../../services/attachments.js'; import { Button } from '../../components/Button.jsx'; import { Field, FieldRow } from '../../components/Field.jsx'; import { ComboBox } from '../../components/ComboBox.jsx'; @@ -41,6 +43,10 @@ export default function ActivityDetailPanel({ activity, projectId, siblingActivi }); const [tab, setTab] = useState('detail'); + // Recargadas al cambiar de pestaña (listas livianas) para que los contadores de las pestañas + // se mantengan al dia sin necesidad de que CommentsPanel/AttachmentsPanel avisen al padre. + const { data: comments } = useAsync(() => listComments('activity', activity.id), [activity.id, tab]); + const { data: attachments } = useAsync(() => listAttachments('activity', activity.id), [activity.id, tab]); const [editing, setEditing] = useState(false); const [form, setForm] = useState(() => toForm(activity)); const [newTask, setNewTask] = useState(''); @@ -53,6 +59,7 @@ export default function ActivityDetailPanel({ activity, projectId, siblingActivi useEffect(() => { setForm(toForm(activity)); setEditing(false); }, [activity]); const hasTasks = tasks && tasks.length > 0; + const pendingTasksCount = (tasks || []).filter((task) => !task.is_done).length; const priorityOptions = (priorities || []).map((p) => ({ value: p.id, label: p.name })); const statusOptions = (statuses || []).map((s) => ({ value: s.id, label: s.name })); const userOptions = (users || []).map((u) => ({ value: u.id, label: u.name })); @@ -141,10 +148,10 @@ export default function ActivityDetailPanel({ activity, projectId, siblingActivi