82 lines
3.3 KiB
TypeScript
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>
|
|
)
|
|
}
|