'use client' import { ResponsivePie } from '@nivo/pie' import { ResponsiveBar } from '@nivo/bar' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { nivoTheme, BRAND_COLORS } from './chart-theme' interface DiversityData { total: number byCountry: { country: string; count: number; percentage: number }[] byCategory: { category: string; count: number; percentage: number }[] byOceanIssue: { issue: string; count: number; percentage: number }[] byTag: { tag: string; count: number; percentage: number }[] } interface DiversityMetricsProps { data: DiversityData } /** Convert ISO 3166-1 alpha-2 code to full country name using Intl API */ function getCountryName(code: string): string { if (code === 'Others') return 'Others' try { const displayNames = new Intl.DisplayNames(['en'], { type: 'region' }) return displayNames.of(code.toUpperCase()) || code } catch { return code } } /** Convert SCREAMING_SNAKE_CASE to Title Case */ function formatLabel(value: string): string { if (!value) return value return value .replace(/_/g, ' ') .toLowerCase() .replace(/\b\w/g, (c) => c.toUpperCase()) } export function DiversityMetricsChart({ data }: DiversityMetricsProps) { if (!data || data.total === 0) { return (

No project data available

) } // Top countries for pie chart (max 10, others grouped) const topCountries = (data.byCountry || []).slice(0, 10) const otherCountries = (data.byCountry || []).slice(10) const countryPieData = otherCountries.length > 0 ? [...topCountries, { country: 'Others', count: otherCountries.reduce((sum, c) => sum + c.count, 0), percentage: otherCountries.reduce((sum, c) => sum + c.percentage, 0), }] : topCountries const nivoPieData = countryPieData.map((c) => ({ id: c.country === 'Others' ? 'Others' : c.country.toUpperCase(), label: getCountryName(c.country), value: c.count, })) // Pre-format category and ocean issue data for display 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) => ({ issue: formatLabel(o.issue), count: o.count, })) return (
{/* Summary */}
{data.total}

Total Projects

{(data.byCountry || []).length}

Countries Represented

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

Categories

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

Unique Tags

{/* Country Distribution */} Geographic Distribution
{nivoPieData.length > 0 ? : (

No geographic data

)}
{/* Category Distribution */} Competition Categories {formattedCategories.length > 0 ? (
) : (

No category data

)}
{/* Ocean Issues */} {formattedOceanIssues.length > 0 && ( Ocean Issues Addressed
)} {/* Tags Cloud */} {(data.byTag || []).length > 0 && ( Project Tags
{(data.byTag || []).slice(0, 30).map((tag) => ( {tag.tag} ({tag.count}) ))}
)}
) }