74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
'use client'
|
|
import { useEffect, useState } from 'react'
|
|
import {
|
|
isSuppressed,
|
|
type PuntoCiegoData,
|
|
type SuppressedPayload,
|
|
type DashboardFilters,
|
|
} from '@/lib/dashboard-types'
|
|
import { queries } from '@/lib/dashboard-queries'
|
|
import { WidgetShell } from './widget-shell'
|
|
|
|
const MAX_BAR_HEIGHT = 70
|
|
|
|
export function PuntoCiegoCard({ surveyId, filters }: { surveyId: string; filters: DashboardFilters }) {
|
|
const [data, setData] = useState<PuntoCiegoData | SuppressedPayload | null>(null)
|
|
const [error, setError] = useState(false)
|
|
|
|
useEffect(() => {
|
|
setData(null); setError(false)
|
|
queries.mePuntoCiego(surveyId, filters)
|
|
.then((d) => setData(d as PuntoCiegoData | SuppressedPayload))
|
|
.catch(() => setError(true))
|
|
}, [surveyId, JSON.stringify(filters)])
|
|
|
|
const status = error ? 'error' : data === null ? 'loading' : isSuppressed(data) ? 'suppressed' : 'ok'
|
|
const ok = status === 'ok' ? (data as PuntoCiegoData) : null
|
|
|
|
const cargaHeight = ok ? Math.max(6, (ok.carga_real_pct / 100) * MAX_BAR_HEIGHT) : 0
|
|
const apoyoHeight =
|
|
ok && ok.apoyo_percibido_pct !== null ? Math.max(6, (ok.apoyo_percibido_pct / 100) * MAX_BAR_HEIGHT) : 0
|
|
|
|
return (
|
|
<WidgetShell
|
|
title="Punto ciego organizacional"
|
|
subtitle="9.1 vs. prevalencia real (4.1) — brecha entre carga y percepción"
|
|
status={status}
|
|
n={ok?.n}
|
|
colSpan={4}
|
|
>
|
|
{ok && (
|
|
<>
|
|
<div className="db-gap-viz">
|
|
<div className="db-gap-col">
|
|
<div className="db-gap-val" style={{ color: 'var(--color-re-teal)' }}>
|
|
{ok.carga_real_pct}%
|
|
</div>
|
|
<div className="db-gap-bar" style={{ height: cargaHeight, background: 'var(--color-re-teal)' }} />
|
|
<div className="db-gap-lab">carga real</div>
|
|
</div>
|
|
<div className="db-gap-col">
|
|
{ok.apoyo_percibido_pct !== null ? (
|
|
<>
|
|
<div className="db-gap-val" style={{ color: '#f06b6b' }}>
|
|
{ok.apoyo_percibido_pct}%
|
|
</div>
|
|
<div className="db-gap-bar" style={{ height: apoyoHeight, background: '#f06b6b' }} />
|
|
</>
|
|
) : (
|
|
<div className="db-gap-val" style={{ color: '#6b7280' }}>
|
|
n<5
|
|
</div>
|
|
)}
|
|
<div className="db-gap-lab">se siente apoyado</div>
|
|
</div>
|
|
</div>
|
|
{ok.brecha_pp !== null && (
|
|
<p className="db-gap-brecha">Brecha: {ok.brecha_pp} puntos porcentuales</p>
|
|
)}
|
|
</>
|
|
)}
|
|
</WidgetShell>
|
|
)
|
|
}
|