Files
motor-de-encuestas/components/dashboard/donut-cuidados.tsx

82 lines
3.3 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
import { isSuppressed, type DistribucionData } from '@/lib/dashboard-types'
import { queries } from '@/lib/dashboard-queries'
import type { DashboardFilters } from '@/lib/dashboard-types'
import { WidgetShell } from './widget-shell'
const SEGMENTS = [
{ key: 'disc_propia', label: 'Discapacidad propia', color: '#43BBC8' },
{ key: 'familiar', label: 'Familiar con disc.', color: '#F8AD13' },
{ key: 'adulto_mayor', label: 'Adulto mayor', color: '#EE761A' },
{ key: 'ninguno', label: 'Sin rol de cuidado', color: '#3d506b' },
] as const
export function DonutCuidados({ surveyId, filters }: { surveyId: string; filters: DashboardFilters }) {
const [data, setData] = useState<DistribucionData | null>(null)
const [sup, setSup] = useState(false)
useEffect(() => {
setData(null); setSup(false)
queries.distribucion(surveyId, filters)
.then(d => {
if (isSuppressed(d)) setSup(true)
else setData(d as DistribucionData)
}).catch(() => {})
}, [surveyId, JSON.stringify(filters)])
const status = !data && !sup ? 'loading' : sup ? 'suppressed' : 'ok'
// SVG donut
const R = 60; const cx = 75; const cy = 75; const stroke = 22
let offset = 0
const circumference = 2 * Math.PI * R
const arcs = data ? SEGMENTS.map(s => {
const pct = (data[s.key as keyof DistribucionData] as number) ?? 0
const dash = (pct / 100) * circumference
const gap = circumference - dash
const arc = { ...s, dash, gap, offset: circumference * (1 - offset / 100) }
offset += pct
return arc
}) : []
return (
<WidgetShell title="Perfil de la población" subtitle="1.1 + 1.6 + 1.13 · discapacidad propia, cuidador familiar y de adulto mayor (no excluyentes)" status={status} n={data?.n} colSpan={3}>
{data && (
<div className="db-donut-wrapper">
<svg viewBox="0 0 150 150" className="db-donut-svg" aria-hidden="true">
{arcs.map(arc => (
<circle key={arc.key}
cx={cx} cy={cy} r={R}
fill="none"
stroke={arc.color}
strokeWidth={stroke}
strokeDasharray={`${arc.dash} ${arc.gap}`}
strokeDashoffset={arc.offset}
transform="rotate(-90, 75, 75)"
/>
))}
<text x={cx} y={cy-6} textAnchor="middle" fill="white" fontSize="14" fontWeight="bold">
{data.disc_propia + data.familiar + data.adulto_mayor > 0
? `${Math.round(data.disc_propia + data.familiar + data.adulto_mayor)}%`
: '0%'}
</text>
<text x={cx} y={cy+12} textAnchor="middle" fill="#9ca3af" fontSize="8">cuidadores</text>
</svg>
<ul className="db-donut-legend" aria-label="Leyenda del donut">
{SEGMENTS.map(s => (
<li key={s.key} className="db-legend-item">
<span className="db-legend-dot" style={{ background: s.color }} />
<span>{s.label}</span>
<span className="db-legend-val">
{(data[s.key as keyof DistribucionData] as number ?? 0)}%
</span>
</li>
))}
</ul>
</div>
)}
</WidgetShell>
)
}