feat: version 2.17.5 -- Panel: medidor y detalle en "Proyectos atrasados"

La tarjeta muestra un medidor semicircular (atrasados/activos) con el valor al
centro; al hacer clic, el bloque inferior lista los proyectos atrasados en vez
de mis actividades. Por ahora solo esta tarjeta.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-10-20 17:02:45 -05:00
parent 9231bd2c7a
commit 4583e3c456
10 changed files with 102 additions and 9 deletions
+3 -1
View File
@@ -14,15 +14,17 @@ function memberFilterFor(currentUser) {
export const getSummary = asyncHandler(async (req, res) => {
const memberUserId = memberFilterFor(req.currentUser);
const [kpis, myActivities, byStatus] = await Promise.all([
const [kpis, myActivities, byStatus, overdueProjects] = await Promise.all([
repo.summary(memberUserId),
repo.myPendingActivities(req.currentUser.id, memberUserId),
repo.projectsByStatus(memberUserId),
repo.overdueProjectsList(memberUserId),
]);
ok(res, {
kpis,
myActivities: myActivities.map((a) => ({ ...a, dueStatus: dueStatus(a.due_date) })),
projectsByStatus: byStatus,
overdueProjects,
});
});
@@ -59,6 +59,20 @@ export async function summary(memberUserId) {
};
}
// Mismo criterio que el KPI overdueProjects de summary() -- la lista y el numero nunca difieren.
export async function overdueProjectsList(memberUserId) {
const memberClause = memberUserId ? 'AND EXISTS (SELECT 1 FROM project_members pm WHERE pm.project_id = p.id AND pm.user_id = ?)' : '';
const [rows] = await pool.query(
`SELECT p.id, p.code, p.name, p.estimated_end_date, p.progress_pct, u.name AS owner_name
FROM projects p JOIN project_statuses ps ON ps.id = p.status_id LEFT JOIN users u ON u.id = p.owner_user_id
WHERE ps.is_closed = 0 AND p.deleted_at IS NULL
AND p.estimated_end_date IS NOT NULL AND p.estimated_end_date < CURDATE() ${memberClause}
ORDER BY p.estimated_end_date`,
memberUserId ? [memberUserId] : []
);
return rows;
}
export async function myPendingActivities(userId, memberUserId) {
const memberClause = memberUserId ? 'AND EXISTS (SELECT 1 FROM project_members pm WHERE pm.project_id = p.id AND pm.user_id = ?)' : '';
const params = memberUserId ? [userId, memberUserId] : [userId];