Fix observer analytics crash: guard Nivo edge cases
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m41s
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m41s
- Disable enableSlices on ResponsiveLine with single data point (causes null reference in Nivo internal slice computation) - Add null check for slice.points[0] in timeline tooltip - Guard ResponsivePie from empty data array in diversity metrics - Add fallback for scoreDistribution.distribution on both observer and admin reports pages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -532,9 +532,9 @@ function StageAnalytics() {
|
|||||||
<Skeleton className="h-[350px]" />
|
<Skeleton className="h-[350px]" />
|
||||||
) : scoreDistribution ? (
|
) : scoreDistribution ? (
|
||||||
<ScoreDistributionChart
|
<ScoreDistributionChart
|
||||||
data={scoreDistribution.distribution}
|
data={scoreDistribution.distribution ?? []}
|
||||||
averageScore={scoreDistribution.averageScore}
|
averageScore={scoreDistribution.averageScore ?? 0}
|
||||||
totalScores={scoreDistribution.totalScores}
|
totalScores={scoreDistribution.totalScores ?? 0}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -399,9 +399,9 @@ function AnalyticsTab({ selectedValue }: { selectedValue: string }) {
|
|||||||
<Skeleton className="h-[350px]" />
|
<Skeleton className="h-[350px]" />
|
||||||
) : scoreDistribution ? (
|
) : scoreDistribution ? (
|
||||||
<ScoreDistributionChart
|
<ScoreDistributionChart
|
||||||
data={scoreDistribution.distribution}
|
data={scoreDistribution.distribution ?? []}
|
||||||
averageScore={scoreDistribution.averageScore}
|
averageScore={scoreDistribution.averageScore ?? 0}
|
||||||
totalScores={scoreDistribution.totalScores}
|
totalScores={scoreDistribution.totalScores ?? 0}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export function DiversityMetricsChart({ data }: DiversityMetricsProps) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div style={{ height: '400px' }}>
|
<div style={{ height: '400px' }}>
|
||||||
<ResponsivePie
|
{nivoPieData.length > 0 ? <ResponsivePie
|
||||||
data={nivoPieData}
|
data={nivoPieData}
|
||||||
theme={nivoTheme}
|
theme={nivoTheme}
|
||||||
colors={[...BRAND_COLORS]}
|
colors={[...BRAND_COLORS]}
|
||||||
@@ -149,7 +149,9 @@ export function DiversityMetricsChart({ data }: DiversityMetricsProps) {
|
|||||||
symbolShape: 'circle',
|
symbolShape: 'circle',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/> : (
|
||||||
|
<p className="text-muted-foreground text-center py-8">No geographic data</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -63,9 +63,10 @@ export function EvaluationTimelineChart({ data }: EvaluationTimelineProps) {
|
|||||||
pointBorderWidth={2}
|
pointBorderWidth={2}
|
||||||
pointBorderColor="#ffffff"
|
pointBorderColor="#ffffff"
|
||||||
useMesh={true}
|
useMesh={true}
|
||||||
enableSlices="x"
|
enableSlices={formattedData.length >= 2 ? 'x' : false}
|
||||||
sliceTooltip={({ slice }) => {
|
sliceTooltip={({ slice }) => {
|
||||||
const point = slice.points[0]
|
const point = slice.points[0]
|
||||||
|
if (!point) return null
|
||||||
const dataItem = formattedData.find(
|
const dataItem = formattedData.find(
|
||||||
(d) => d.dateFormatted === point.data.xFormatted
|
(d) => d.dateFormatted === point.data.xFormatted
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user