// Filtros globales del dashboard (sidebar) export interface DashboardFilters { depto?: string genero?: string[] etario?: string[] modalidad?: string[] } // Estado de cada widget export type WidgetStatus = 'loading' | 'ok' | 'suppressed' | 'error' export type SuppressedPayload = { status: 'suppressed'; min_n: number; n: number } export type RpcResult = T | SuppressedPayload export function isSuppressed(r: unknown): r is SuppressedPayload { return typeof r === 'object' && r !== null && (r as Record)['status'] === 'suppressed' } // ════════════════════════════════════════════════════════════ // Mirada Empresa — shapes tal cual los devuelven las rpc_me_* // (migración 20260625000002_dashboard_mirada_empresa.sql, verificada // contra Postgres real). NO copiar del SPEC_MIRADA_EMPRESA.md a ciegas: // el SQL real difiere un poco del shape ilustrativo de la spec (ej. E6 // agrega apoyo_percibido_suppressed; E7 usa "apoyos", no "data"). // ════════════════════════════════════════════════════════════ // E1 — Prevalencia de cuidadores export interface PrevalenciaCuidadoresData { status: 'ok' n: number pct_cuidadores: number } // E2 — Riesgo de rotación export interface RiesgoRotacionData { status: 'ok' n_cuidadores: number pct_riesgo: number desglose: { algo: number; muy: number } } // E3 — Ausentismo export interface AusentismoData { status: 'ok' n: number pct_ausentismo_recurrente: number desglose: { nunca: number; pocas: number; varias: number; frecuente: number } } // E4 — Presentismo export interface PresentismoData { status: 'ok' n: number pct_presentismo: number desglose: { nunca_o_casi_nunca: number algunas_al_mes: number varias_por_semana: number casi_todos_los_dias: number } } // E6 — Punto ciego organizacional // apoyo_percibido_pct puede ser null con status='ok' si SU población (9.1) // no llega a 5, aunque el total (carga_real) sí — dos poblaciones, dos // supresiones independientes (ver comentario en la RPC). export interface PuntoCiegoData { status: 'ok' n: number carga_real_pct: number apoyo_percibido_pct: number | null apoyo_percibido_suppressed: boolean brecha_pp: number | null } // E7 — Apoyos demandados export interface ApoyoMEItem { apoyo: string; n: number; pct: number } export interface ApoyosMEData { status: 'ok' n: number apoyos: ApoyoMEItem[] } // ★ Talento en riesgo export interface TalentoRiesgoData { status: 'ok' n_cuidadores: number umbral_senales: number pct_talento_riesgo: number criterios_promedio: number } // E5 — Carrera congelada [SEC] export interface CarreraCongeladaItem { opcion: string; n: number; pct: number } export interface CarreraCongeladaData { status: 'ok' n: number pct_carrera_congelada: number top_opciones: CarreraCongeladaItem[] } // E8 — Intensidad de carga [SEC] export interface IntensidadCargaCell { dias_semana: string horas_dia: string n: number | null suppressed: boolean } export interface IntensidadCargaData { status: 'ok' n: number distribucion_intensidad: IntensidadCargaCell[] pct_guardia_permanente: number } // E9 — Segmentación por nivel y modalidad [SEC] export interface SegmentoNivelItem { nivel: string; n: number; pct: number } export interface SegmentoModalidadItem { modalidad: string; n: number; pct: number } export interface SegmentacionData { status: 'ok' n: number por_nivel: SegmentoNivelItem[] por_modalidad: SegmentoModalidadItem[] } // E10 — Disposición a red de apoyo [SEC] // Shape "suppressed" de esta RPC difiere del genérico (usa // n_grupo_apoyo/n_voluntariado, no min_n/n) — isSuppressed() solo mira // `status`, así que sigue funcionando; no leer .n de un resultado // suprimido de esta RPC en particular. export interface DisposicionRedData { status: 'ok' n_grupo_apoyo: number pct_grupo_apoyo: number | null n_voluntariado: number pct_voluntariado: number | null }