115 lines
3.8 KiB
TypeScript
115 lines
3.8 KiB
TypeScript
"use client"
|
|
|
|
import { useMigrants } from "@/hooks/useGraph"
|
|
import { useRef } from "react"
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from "recharts"
|
|
|
|
export const ResidenceChart = () => {
|
|
const { residenceData, loading, error } = useMigrants()
|
|
const chartRef = useRef<HTMLDivElement>(null)
|
|
|
|
if (loading) {
|
|
return (
|
|
<Card className="border border-gray-800 bg-gray-900 shadow-2xl overflow-hidden">
|
|
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-[#9B2335] to-[#9B2335]/60"></div>
|
|
<CardContent className="p-6 flex items-center justify-center h-4">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#9B2335]"></div>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<Card className="border border-gray-800 bg-gray-900 shadow-2xl overflow-hidden">
|
|
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-red-500 to-red-600"></div>
|
|
<CardContent className="p-6 text-center">
|
|
<p className="text-red-400">{error}</p>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
if (!residenceData.length) {
|
|
return (
|
|
<Card className="border border-gray-800 bg-gray-900 shadow-2xl overflow-hidden">
|
|
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-gray-600 to-gray-700"></div>
|
|
<CardContent className="p-6 text-center">
|
|
<p className="text-gray-400">No data available</p>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
const COLORS = [
|
|
"#9B2335",
|
|
"#DC2626",
|
|
"#EA580C",
|
|
"#D97706",
|
|
"#CA8A04",
|
|
"#65A30D",
|
|
"#16A34A",
|
|
"#059669",
|
|
"#0891B2",
|
|
"#0284C7",
|
|
]
|
|
|
|
return (
|
|
<Card ref={chartRef} className="border border-gray-800 bg-gray-900 shadow-2xl overflow-hidden">
|
|
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-[#9B2335] to-[#9B2335]/60"></div>
|
|
<CardHeader className="border-b border-gray-800">
|
|
<CardTitle className="text-lg font-medium text-white">Italian Migration: Residence Distribution</CardTitle>
|
|
<CardDescription className="text-gray-400">
|
|
Distribution of Italian migrants across different towns or cities
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="p-6">
|
|
<ResponsiveContainer width="100%" height={400}>
|
|
<PieChart>
|
|
<Pie
|
|
data={residenceData}
|
|
dataKey="value"
|
|
nameKey="name"
|
|
cx="50%"
|
|
cy="50%"
|
|
outerRadius={130}
|
|
innerRadius={70}
|
|
paddingAngle={3}
|
|
labelLine={false}
|
|
label={({ name, value }) => `${name} (${value})`}
|
|
>
|
|
{residenceData.map((_, index) => (
|
|
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} className="rounded-full" />
|
|
))}
|
|
</Pie>
|
|
|
|
<Tooltip
|
|
contentStyle={{
|
|
backgroundColor: "#1F2937",
|
|
borderRadius: "8px",
|
|
color: "#fff",
|
|
fontSize: "0.875rem",
|
|
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
|
|
border: "1px solid #374151",
|
|
}}
|
|
formatter={(value: number, name: string) => [`${value} migrants`, name]}
|
|
/>
|
|
|
|
<Legend
|
|
verticalAlign="bottom"
|
|
iconType="circle"
|
|
align="center"
|
|
wrapperStyle={{
|
|
fontSize: "0.875rem",
|
|
color: "#9CA3AF",
|
|
marginTop: "1rem",
|
|
}}
|
|
/>
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|