46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
'use client'
|
|
import type { WidgetStatus } from '@/lib/dashboard-types'
|
|
|
|
interface WidgetShellProps {
|
|
title: string
|
|
subtitle?: string
|
|
status: WidgetStatus
|
|
n?: number
|
|
children: React.ReactNode
|
|
colSpan?: number
|
|
}
|
|
|
|
export function WidgetShell({ title, subtitle, status, n, children, colSpan = 6 }: WidgetShellProps) {
|
|
return (
|
|
<div className={`db-widget db-col-${colSpan}`} style={{ gridColumn: `span ${colSpan}` }}>
|
|
<div className="db-widget-header">
|
|
<div className="db-widget-title-group">
|
|
<h3 className="db-widget-title">{title}</h3>
|
|
{subtitle && <p className="db-widget-subtitle">{subtitle}</p>}
|
|
</div>
|
|
{n !== undefined && status === 'ok' && (
|
|
<span className="db-widget-n">n = {n.toLocaleString('es-PY')}</span>
|
|
)}
|
|
</div>
|
|
<div className="db-widget-body">
|
|
{status === 'loading' && (
|
|
<div className="db-skeleton-block" aria-label="Cargando…" aria-busy="true" />
|
|
)}
|
|
{status === 'suppressed' && (
|
|
<div className="db-suppressed" role="status">
|
|
<span className="db-suppressed-icon">🔒</span>
|
|
<p>Datos insuficientes</p>
|
|
<p className="db-suppressed-hint">Se necesitan al menos 5 respuestas en este corte.</p>
|
|
</div>
|
|
)}
|
|
{status === 'error' && (
|
|
<div className="db-suppressed" role="alert">
|
|
<p>Error al cargar los datos.</p>
|
|
</div>
|
|
)}
|
|
{status === 'ok' && children}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|