From d15a58cb29a32d48382aaf971079d0d13928f69e Mon Sep 17 00:00:00 2001 From: Milton Gonzalez Date: Wed, 21 Oct 2026 07:42:38 -0500 Subject: [PATCH] feat: version 2.17.6 -- Panel: "Proyectos atrasados" en porcentaje con "N de M" Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 5 +++++ VERSION | 2 +- backend/package.json | 2 +- frontend/package.json | 2 +- frontend/src/components/KpiCard.jsx | 7 +++++-- frontend/src/i18n/messages.js | 2 ++ frontend/src/pages/Dashboard/DashboardPage.jsx | 6 ++++-- frontend/src/styles/app.css | 4 +++- 8 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5253d..b9b5ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog - project.linkedcorp.net +## [2.17.6] - 2026-10-21 +### Changed +- Panel → "Proyectos atrasados": el centro del medidor muestra el porcentaje (atrasados sobre + activos) y debajo "N de M", para que se entienda de cuántos. + ## [2.17.5] - 2026-10-20 ### Added - Panel: la tarjeta "Proyectos atrasados" muestra un medidor (atrasados sobre activos) con el diff --git a/VERSION b/VERSION index 00db226..728789a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.5 +2.17.6 diff --git a/backend/package.json b/backend/package.json index 704b910..4e8becc 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "project-linkedcorp-backend", - "version": "2.17.5", + "version": "2.17.6", "private": true, "type": "module", "main": "src/server.js", diff --git a/frontend/package.json b/frontend/package.json index b92ce3e..9482ea0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "project-linkedcorp-frontend", "private": true, - "version": "2.17.5", + "version": "2.17.6", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/KpiCard.jsx b/frontend/src/components/KpiCard.jsx index 2d2eab6..59fa20d 100644 --- a/frontend/src/components/KpiCard.jsx +++ b/frontend/src/components/KpiCard.jsx @@ -1,12 +1,13 @@ // Medidor semicircular (tipo odometro): arco de fondo + arco relleno segun ratio (0..1), con el // valor del KPI al centro. Sin libreria -- un SVG con stroke-dasharray sobre el semicirculo. -function Gauge({ ratio, color, value }) { +function Gauge({ ratio, color, value, caption }) { const r = 40; const length = Math.PI * r; const clamped = Math.max(0, Math.min(1, ratio || 0)); const arc = `M ${50 - r} 50 A ${r} ${r} 0 0 1 ${50 + r} 50`; return (
+
{value}
+
+ {caption &&
{caption}
}
); } @@ -30,7 +33,7 @@ export function KpiCard({ label, value, gauge, onClick, selected }) { tabIndex={clickable ? 0 : undefined} onKeyDown={clickable ? (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick(); } } : undefined} > - {gauge ? :
{value}
} + {gauge ? :
{value}
}
{label}
); diff --git a/frontend/src/i18n/messages.js b/frontend/src/i18n/messages.js index a515854..d8e2752 100644 --- a/frontend/src/i18n/messages.js +++ b/frontend/src/i18n/messages.js @@ -156,6 +156,7 @@ export const messages = { dashboard_average_progress: 'Avance promedio', dashboard_my_activities: 'Mis actividades pendientes', dashboard_my_overdue_projects: 'Mis proyectos atrasados', + common_of: 'de', dashboard_back_to_my_activities: 'Ver mis actividades', dashboard_projects_by_status: 'Proyectos por estado', @@ -643,6 +644,7 @@ export const messages = { dashboard_average_progress: 'Average progress', dashboard_my_activities: 'My pending activities', dashboard_my_overdue_projects: 'My overdue projects', + common_of: 'of', dashboard_back_to_my_activities: 'Show my activities', dashboard_projects_by_status: 'Projects by status', diff --git a/frontend/src/pages/Dashboard/DashboardPage.jsx b/frontend/src/pages/Dashboard/DashboardPage.jsx index 316d0b3..792d353 100644 --- a/frontend/src/pages/Dashboard/DashboardPage.jsx +++ b/frontend/src/pages/Dashboard/DashboardPage.jsx @@ -17,6 +17,8 @@ export default function DashboardPage() { if (!data) return
{t('common_loading')}
; const { kpis, myActivities, projectsByStatus, overdueProjects } = data; const activeTotal = Number(kpis.activeProjects) || 0; + const overdueRatio = activeTotal ? Number(kpis.overdueProjects) / activeTotal : 0; + const overduePct = Math.round(overdueRatio * 100); return (
@@ -26,8 +28,8 @@ export default function DashboardPage() { toggleDetail('overdue')} selected={detail === 'overdue'} /> diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index c64c6d2..e7e38f7 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -244,9 +244,11 @@ table.list-table { width: 100%; border-collapse: collapse; font-size: .8rem; } .kpi-card-clickable { cursor: pointer; transition: border-color .15s ease; } .kpi-card-clickable:hover { border-color: rgb(var(--accent) / .5); } .kpi-card.selected { border-color: rgb(var(--accent)); box-shadow: 0 0 0 1px rgb(var(--accent)); } -.kpi-gauge { position: relative; width: 120px; max-width: 100%; } +.kpi-gauge { width: 120px; max-width: 100%; } +.kpi-gauge-dial { position: relative; } .kpi-gauge svg { display: block; width: 100%; } .kpi-gauge-value { position: absolute; left: 0; right: 0; bottom: 0; text-align: center; font-size: 1.4rem; font-weight: 700; line-height: 1; } +.kpi-gauge-caption { text-align: center; font-size: .68rem; color: rgb(var(--muted)); margin-top: 2px; } .panel-card { background: rgb(var(--surface)); border: 1px solid rgb(var(--line)); border-radius: var(--r-lg); padding: 16px; margin-bottom: 16px; } .panel-card h3 { margin: 0 0 12px; font-size: .95rem; } .company-logo-preview {