import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { LineChart, BarChart3, PieChart } from "lucide-react"; import { LineChart as RechartsLineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, BarChart, Bar, PieChart as RechartsPieChart, Pie, Cell, } from "recharts"; import React from "react"; // Colors for charts const CHART_COLORS = [ "#8884d8", "#83a6ed", "#8dd1e1", "#82ca9d", "#a4de6c", "#d0ed57", "#ffc658", "#ff8042", "#ff6361", "#bc5090" ]; type TradeChartsProps = { visualizationData: { recordsByYear: { year: number; count: number }[]; topImporters: { country: string; count: number }[]; topExporters: { country: string; count: number }[]; termsTraded: { term: string; count: number }[]; tradePurposes: { purpose: string; count: number; description: string }[]; tradeSources: { source: string; count: number; description: string }[]; termQuantitiesByYear: { year: number; [term: string]: number }[]; topTerms: string[]; }; PURPOSE_DESCRIPTIONS: Record; SOURCE_DESCRIPTIONS: Record; }; export function TradeCharts({ visualizationData, PURPOSE_DESCRIPTIONS, SOURCE_DESCRIPTIONS }: TradeChartsProps) { // Process terms data to combine small segments const processedTermsData = React.useMemo(() => { const threshold = 0.02; // 2% threshold let otherCount = 0; // Sort by count in descending order const sortedTerms = [...visualizationData.termsTraded].sort((a, b) => b.count - a.count); // Calculate total for percentage const total = sortedTerms.reduce((sum, item) => sum + item.count, 0); // Filter and combine small segments const significantTerms = sortedTerms.filter(item => { const percentage = item.count / total; if (percentage < threshold) { otherCount += item.count; return false; } return true; }); // Add "Other" category if there are small segments if (otherCount > 0) { significantTerms.push({ term: 'Other', count: otherCount }); } return significantTerms; }, [visualizationData.termsTraded]); // Custom tooltip for pie chart const renderCustomizedLabel = ({ cx, cy, midAngle, outerRadius, percent, payload }: any) => { const RADIAN = Math.PI / 180; const radius = outerRadius * 1.15; // Increased radius for better spacing const x = cx + radius * Math.cos(-midAngle * RADIAN); const y = cy + radius * Math.sin(-midAngle * RADIAN); return ( cx ? 'start' : 'end'} dominantBaseline="central" fontSize={12} fontWeight="500" > {`${payload.term} (${(percent * 100).toFixed(0)}%)`} ); }; return (

Trade Visualizations

{/* Records Over Time */}
Records Over Time
Number of trade records by year
{/* Top Importers and Exporters */}
{/* Top Importers */}
Top Importers
Countries importing the most specimens
{/* Top Exporters */}
Top Exporters
Countries exporting the most specimens
{/* Terms Traded */}
Terms Traded
Distribution of specimen types in trade
{processedTermsData.map((_, index) => ( ))} [`${value} records`, props.payload.term]} />
{/* Trade Purposes and Sources */}
{/* Trade Purposes */}
Trade Purposes
Reasons for trade
`${value} - ${PURPOSE_DESCRIPTIONS[value] || 'Unknown'}`} width={150} /> [ `${value} records`, `${props.payload.purpose} - ${props.payload.description}` ]} />
{/* Trade Sources */}
Trade Sources
Origin of traded specimens
`${value} - ${SOURCE_DESCRIPTIONS[value] || 'Unknown'}`} width={150} /> [ `${value} records`, `${props.payload.source} - ${props.payload.description}` ]} />
{/* Quantity of Top Terms Over Time */}
Quantity of Top Terms Over Time
Trends in quantities of the most traded terms
{visualizationData.topTerms.map((term, index) => ( ))}
); }