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.
This commit is contained in:
@@ -160,12 +160,19 @@ function MetricBreakdownPanel({ metrics }) {
|
|||||||
// Donut Chart
|
// Donut Chart
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
function DonutChart({ donut }) {
|
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 (
|
||||||
|
<div style={{ ...CARD_STYLE, flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#10B981', fontSize: '0.8rem' }}>
|
||||||
|
No non-compliant devices
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
const data = [
|
const data = [
|
||||||
{ name: 'Blocked', count: donut.blocked.count, color: '#EF4444' },
|
{ name: 'Blocked', count: donut.blocked.count, color: '#EF4444' },
|
||||||
{ name: 'In-Progress', count: donut.in_progress.count, color: '#F59E0B' },
|
{ name: 'In-Progress', count: donut.in_progress.count, color: '#F59E0B' },
|
||||||
];
|
];
|
||||||
const total = donut.blocked.count + donut.in_progress.count;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ ...CARD_STYLE, flex: 1 }}>
|
<div style={{ ...CARD_STYLE, flex: 1 }}>
|
||||||
@@ -410,7 +417,7 @@ function VerticalDetailView({ vertical, onBack, onSelectMetric }) {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [expandedMetrics, setExpandedMetrics] = useState(new Set());
|
const [expandedMetrics, setExpandedMetrics] = useState(new Set());
|
||||||
const [teamFilter, setTeamFilter] = useState(''); // '' = all teams (rollup view)
|
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(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -774,7 +781,7 @@ function MetricSubTeamView({ vertical, metricId, metricData, onBack, onSelectTea
|
|||||||
function MetricDeviceList({ vertical, metricId, team, onBack }) {
|
function MetricDeviceList({ vertical, metricId, team, onBack }) {
|
||||||
const [devices, setDevices] = useState(null);
|
const [devices, setDevices] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
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(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user