104 lines
2.8 KiB
React
104 lines
2.8 KiB
React
import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from 'recharts'
|
|
import { useChartTheme } from '../../hooks/useChartTheme'
|
|
|
|
const COLORES = {
|
|
Urbana: '#252C61',
|
|
Rural: '#E8881A',
|
|
'Sin datos': '#94A3B8',
|
|
}
|
|
|
|
const RADIAN = Math.PI / 180
|
|
|
|
function normalizarZona(valor) {
|
|
const texto = String(valor ?? '').trim().toLowerCase()
|
|
|
|
if (!texto) return 'Sin datos'
|
|
if (texto.includes('urb')) return 'Urbana'
|
|
if (texto.includes('rur')) return 'Rural'
|
|
return 'Sin datos'
|
|
}
|
|
|
|
export default function ZonaOcurrencia({ siniestros }) {
|
|
const { tooltipBg, tooltipBorder, tooltipLabel, tickColor } = useChartTheme()
|
|
|
|
const conteo = { Urbana: 0, Rural: 0, 'Sin datos': 0 }
|
|
|
|
siniestros.forEach((s) => {
|
|
const zona = normalizarZona(s.zona_ocurrencia)
|
|
conteo[zona] += 1
|
|
})
|
|
|
|
const data = Object.entries(conteo)
|
|
.map(([name, value]) => ({ name, value }))
|
|
.filter((item) => item.value > 0)
|
|
|
|
const total = data.reduce((acc, d) => acc + d.value, 0)
|
|
|
|
const renderLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent }) => {
|
|
if (percent < 0.04) return null
|
|
|
|
const r = innerRadius + (outerRadius - innerRadius) * 0.5
|
|
const x = cx + r * Math.cos(-midAngle * RADIAN)
|
|
const y = cy + r * Math.sin(-midAngle * RADIAN)
|
|
|
|
return (
|
|
<text
|
|
x={x}
|
|
y={y}
|
|
fill="white"
|
|
textAnchor="middle"
|
|
dominantBaseline="central"
|
|
style={{ fontSize: '13px', fontWeight: 700 }}
|
|
>
|
|
{`${(percent * 100).toFixed(1)}%`}
|
|
</text>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="rounded-[28px] border border-opsv-border bg-opsv-surface p-6 shadow-sm">
|
|
|
|
<ResponsiveContainer width="100%" height={260}>
|
|
<PieChart>
|
|
<Pie
|
|
data={data}
|
|
cx="50%"
|
|
cy="50%"
|
|
outerRadius={100}
|
|
innerRadius={45}
|
|
dataKey="value"
|
|
labelLine={false}
|
|
label={renderLabel}
|
|
>
|
|
{data.map((entry, i) => (
|
|
<Cell key={i} fill={COLORES[entry.name] || '#8E44AD'} />
|
|
))}
|
|
</Pie>
|
|
|
|
<Tooltip
|
|
contentStyle={{
|
|
background: tooltipBg,
|
|
border: `1px solid ${tooltipBorder}`,
|
|
borderRadius: 16,
|
|
boxShadow: '0 10px 30px rgba(0,0,0,0.08)',
|
|
}}
|
|
labelStyle={{ color: tooltipLabel, fontWeight: 700 }}
|
|
itemStyle={{ color: tickColor }}
|
|
formatter={(val, name) => [
|
|
`${val} (${total ? ((val / total) * 100).toFixed(1) : 0}%)`,
|
|
name,
|
|
]}
|
|
/>
|
|
|
|
<Legend
|
|
iconType="circle"
|
|
iconSize={10}
|
|
formatter={(value) => (
|
|
<span style={{ fontSize: 12, color: tickColor }}>{value}</span>
|
|
)}
|
|
/>
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
)
|
|
} |