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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user