Make Non-Compliant stat clickable — reveals metric breakdown buttons

Clicking the Non-Compliant card on the CCP Metrics overview now toggles a
panel of metric buttons below it, each showing the metric ID, category,
non-compliant count, and compliance % vs target. Styled like the compliance
page's MetricHealthCard pattern.

Backend: added metric_breakdown to the /stats response — aggregated
cross-vertical metric totals (ALL: rows only, grouped by metric_id).

Also updated tech steering file to document the single-port Express
architecture and the requirement to run npm run build after frontend changes.
This commit is contained in:
Jordan Ramos
2026-05-14 15:24:10 -06:00
parent a2bc1ff564
commit 7577ab1219
3 changed files with 210 additions and 6 deletions

View File

@@ -436,6 +436,14 @@ function createVCLMultiVerticalRouter(upload) {
* forecast_burndown: Array<{ month: string, projected_remaining: number }>,
* last_upload: string|null
* }>,
* metric_breakdown: Array<{
* metric_id: string,
* category: string,
* non_compliant: number,
* compliant: number,
* total: number,
* target: number
* }>,
* last_upload_date: string|null
* }
* @response 500 { error: string }
@@ -540,6 +548,19 @@ function createVCLMultiVerticalRouter(upload) {
};
});
// Cross-vertical metric breakdown (aggregated across all verticals, ALL: rows only)
const { rows: metricBreakdown } = await pool.query(`
SELECT metric_id, category,
SUM(non_compliant)::int AS non_compliant,
SUM(compliant)::int AS compliant,
SUM(total)::int AS total,
ROUND(AVG(target::numeric), 2) AS target
FROM vcl_multi_vertical_summary
WHERE upload_id = ANY($1) AND team LIKE 'ALL:%'
GROUP BY metric_id, category
ORDER BY non_compliant DESC
`, [latestUploadIds]);
res.json({
stats: {
total_devices: aggTotal,
@@ -550,6 +571,7 @@ function createVCLMultiVerticalRouter(upload) {
},
donut,
vertical_breakdown,
metric_breakdown: metricBreakdown,
last_upload_date: uploadDates.length > 0 ? uploadDates.reduce((max, r) => r.last_upload > max ? r.last_upload : max, '') : null,
});
} catch (err) {