From 0c99420f1732be579528b7c5d12b14c6060888a9 Mon Sep 17 00:00:00 2001 From: Jordan Ramos Date: Tue, 19 May 2026 14:59:08 -0600 Subject: [PATCH] Fix CCP Metrics crash when donut chart has zero non-compliant devices Recharts PieChart throws internally when all data segments are zero. Guard against this by rendering a friendly message instead of passing all-zero data to the chart component. Affects users whose vertical data has no non-compliant items. --- frontend/src/components/pages/CCPMetricsPage.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/pages/CCPMetricsPage.js b/frontend/src/components/pages/CCPMetricsPage.js index e2ca56f..3c73b24 100644 --- a/frontend/src/components/pages/CCPMetricsPage.js +++ b/frontend/src/components/pages/CCPMetricsPage.js @@ -160,12 +160,19 @@ function MetricBreakdownPanel({ metrics }) { // Donut Chart // --------------------------------------------------------------------------- function DonutChart({ donut }) { - if (!donut) return null; + if (!donut || !donut.blocked || !donut.in_progress) return null; + const total = donut.blocked.count + donut.in_progress.count; + if (total === 0) { + return ( +
+ No non-compliant devices +
+ ); + } const data = [ { name: 'Blocked', count: donut.blocked.count, color: '#EF4444' }, { name: 'In-Progress', count: donut.in_progress.count, color: '#F59E0B' }, ]; - const total = donut.blocked.count + donut.in_progress.count; return (
@@ -410,7 +417,7 @@ function VerticalDetailView({ vertical, onBack, onSelectMetric }) { const [loading, setLoading] = useState(true); const [expandedMetrics, setExpandedMetrics] = useState(new Set()); const [teamFilter, setTeamFilter] = useState(''); // '' = all teams (rollup view) - // ⚠️ CONVENTION: Missing error state — .catch() silently swallows errors without displaying them to the user. Add an error state and render an error message (see main CCPMetricsPage pattern). + // ⚠️ CONVENTION: Missing error state — .catch() silently swallows fetch errors without displaying them to the user. Add an error state and render an error message (see main CCPMetricsPage pattern). useEffect(() => { setLoading(true); @@ -774,7 +781,7 @@ function MetricSubTeamView({ vertical, metricId, metricData, onBack, onSelectTea function MetricDeviceList({ vertical, metricId, team, onBack }) { const [devices, setDevices] = useState(null); const [loading, setLoading] = useState(true); - // ⚠️ CONVENTION: Missing error state — .catch() below silently swallows errors without displaying them to the user. Add an error state and render an error message. + // ⚠️ CONVENTION: Missing error state — .catch() below silently swallows fetch errors without displaying them to the user. Add an error state and render an error message. useEffect(() => { setLoading(true);