diff --git a/src/components/charts/criteria-scores.tsx b/src/components/charts/criteria-scores.tsx index 1f6c97b..588b105 100644 --- a/src/components/charts/criteria-scores.tsx +++ b/src/components/charts/criteria-scores.tsx @@ -23,6 +23,8 @@ type CriterionBarDatum = { } export function CriteriaScoresChart({ data }: CriteriaScoresProps) { + if (!data?.length) return null + const overallAverage = data.length > 0 ? data.reduce((sum, d) => sum + d.averageScore, 0) / data.length diff --git a/src/components/charts/cross-round-comparison.tsx b/src/components/charts/cross-round-comparison.tsx index a5e847b..7420cc4 100644 --- a/src/components/charts/cross-round-comparison.tsx +++ b/src/components/charts/cross-round-comparison.tsx @@ -21,6 +21,16 @@ interface CrossStageComparisonProps { export function CrossStageComparisonChart({ data, }: CrossStageComparisonProps) { + if (!data?.length) { + return ( + + +

No comparison data available

+
+
+ ) + } + const baseData = data.map((round) => ({ name: round.roundName.length > 20 diff --git a/src/components/charts/diversity-metrics.tsx b/src/components/charts/diversity-metrics.tsx index 6b441bd..e8d6316 100644 --- a/src/components/charts/diversity-metrics.tsx +++ b/src/components/charts/diversity-metrics.tsx @@ -39,7 +39,7 @@ function formatLabel(value: string): string { } export function DiversityMetricsChart({ data }: DiversityMetricsProps) { - if (data.total === 0) { + if (!data || data.total === 0) { return ( @@ -50,8 +50,8 @@ export function DiversityMetricsChart({ data }: DiversityMetricsProps) { } // Top countries for pie chart (max 10, others grouped) - const topCountries = data.byCountry.slice(0, 10) - const otherCountries = data.byCountry.slice(10) + const topCountries = (data.byCountry || []).slice(0, 10) + const otherCountries = (data.byCountry || []).slice(10) const countryPieData = otherCountries.length > 0 ? [...topCountries, { country: 'Others', @@ -67,12 +67,12 @@ export function DiversityMetricsChart({ data }: DiversityMetricsProps) { })) // Pre-format category and ocean issue data for display - const formattedCategories = data.byCategory.slice(0, 10).map((c) => ({ + const formattedCategories = (data.byCategory || []).slice(0, 10).map((c) => ({ category: formatLabel(c.category), count: c.count, })) - const formattedOceanIssues = data.byOceanIssue.slice(0, 15).map((o) => ({ + const formattedOceanIssues = (data.byOceanIssue || []).slice(0, 15).map((o) => ({ issue: formatLabel(o.issue), count: o.count, })) @@ -89,19 +89,19 @@ export function DiversityMetricsChart({ data }: DiversityMetricsProps) { -
{data.byCountry.length}
+
{(data.byCountry || []).length}

Countries Represented

-
{data.byCategory.length}
+
{(data.byCategory || []).length}

Categories

-
{data.byTag.length}
+
{(data.byTag || []).length}

Unique Tags

@@ -228,14 +228,14 @@ export function DiversityMetricsChart({ data }: DiversityMetricsProps) { )} {/* Tags Cloud */} - {data.byTag.length > 0 && ( + {(data.byTag || []).length > 0 && ( Project Tags
- {data.byTag.slice(0, 30).map((tag) => ( + {(data.byTag || []).slice(0, 30).map((tag) => ( ({ ...d, dateFormatted: new Date(d.date).toLocaleDateString('en-US', { diff --git a/src/components/charts/juror-consistency.tsx b/src/components/charts/juror-consistency.tsx index e97556a..f1ee1ca 100644 --- a/src/components/charts/juror-consistency.tsx +++ b/src/components/charts/juror-consistency.tsx @@ -91,6 +91,16 @@ function CustomNode({ } export function JurorConsistencyChart({ data }: JurorConsistencyProps) { + if (!data?.jurors?.length) { + return ( + + +

No juror consistency data available

+
+
+ ) + } + const scatterData = [ { id: 'Jurors', diff --git a/src/components/charts/juror-workload.tsx b/src/components/charts/juror-workload.tsx index b682575..81282d6 100644 --- a/src/components/charts/juror-workload.tsx +++ b/src/components/charts/juror-workload.tsx @@ -25,6 +25,8 @@ type WorkloadBarDatum = { } export function JurorWorkloadChart({ data }: JurorWorkloadProps) { + if (!data?.length) return null + const totalAssigned = data.reduce((sum, d) => sum + d.assigned, 0) const totalCompleted = data.reduce((sum, d) => sum + d.completed, 0) const overallRate = diff --git a/src/components/charts/project-rankings.tsx b/src/components/charts/project-rankings.tsx index 1b60158..df02806 100644 --- a/src/components/charts/project-rankings.tsx +++ b/src/components/charts/project-rankings.tsx @@ -30,6 +30,8 @@ export function ProjectRankingsChart({ data, limit = 20, }: ProjectRankingsProps) { + if (!data?.length) return null + const scoredData = data.filter( (d): d is ProjectRankingData & { averageScore: number } => d.averageScore !== null, diff --git a/src/components/charts/score-distribution.tsx b/src/components/charts/score-distribution.tsx index 49cd6bf..f03fcd5 100644 --- a/src/components/charts/score-distribution.tsx +++ b/src/components/charts/score-distribution.tsx @@ -15,6 +15,8 @@ export function ScoreDistributionChart({ averageScore, totalScores, }: ScoreDistributionProps) { + if (!data?.length) return null + const chartData = data.map((d) => ({ score: String(d.score), count: d.count, diff --git a/src/components/charts/status-breakdown.tsx b/src/components/charts/status-breakdown.tsx index b2bf2d3..fe0da18 100644 --- a/src/components/charts/status-breakdown.tsx +++ b/src/components/charts/status-breakdown.tsx @@ -14,6 +14,8 @@ interface StatusBreakdownProps { } export function StatusBreakdownChart({ data }: StatusBreakdownProps) { + if (!data?.length) return null + const total = data.reduce((sum, item) => sum + item.count, 0) const pieData = data.map((d) => ({ diff --git a/src/server/routers/analytics.ts b/src/server/routers/analytics.ts index 5dc7258..245b1f6 100644 --- a/src/server/routers/analytics.ts +++ b/src/server/routers/analytics.ts @@ -615,7 +615,7 @@ export const analyticsRouter = router({ // By tag const tagCounts: Record = {} projects.forEach((p) => { - p.tags.forEach((tag) => { + (p.tags || []).forEach((tag) => { tagCounts[tag] = (tagCounts[tag] || 0) + 1 }) })