Feat Tabla Resumen Nacional

This commit is contained in:
2025-10-23 14:01:20 -03:00
parent 248171146d
commit e98e152f0e
15 changed files with 260 additions and 7 deletions

View File

@@ -8,6 +8,7 @@ import './DevAppStyle.css'
import { HomeCarouselNacionalWidget } from './nacionales/HomeCarouselNacionalWidget';
import { TablaConurbanoWidget } from './nacionales/TablaConurbanoWidget';
import { TablaSeccionesWidget } from './nacionales/TablaSeccionesWidget';
import { ResumenNacionalWidget } from './nacionales/ResumenNacionalWidget';
// --- NUEVO COMPONENTE REUTILIZABLE PARA CONTENIDO COLAPSABLE ---
const CollapsibleWidgetWrapper = ({ children }: { children: React.ReactNode }) => {
@@ -174,6 +175,11 @@ export const DevAppLegislativas = () => {
<h2>Widget: Tabla de Resultados por Sección Electoral</h2>
<TablaSeccionesWidget />
</div>
<div style={sectionStyle}>
<h2>Resumen Nacional de Resultados por Provincia</h2>
<ResumenNacionalWidget />
</div>
</div>
</div>
);

View File

@@ -0,0 +1,81 @@
/* src/components/widgets/ResumenNacionalWidget.module.css */
.widgetContainer {
font-family: sans-serif;
border: 1px solid #ccc;
border-radius: 8px;
padding: 1.5rem;
max-width: 1000px;
margin: 2rem auto;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 1rem;
margin-bottom: 1rem;
border-bottom: 1px solid #eee;
}
.header h3 {
margin: 0;
font-size: 1.5rem;
}
.categoriaSelector {
min-width: 280px;
}
.listaProvincias {
list-style: none;
padding: 0;
margin: 0;
}
.provinciaItem {
padding: 1rem 0;
border-bottom: 1px solid #eee;
}
.provinciaItem:last-child {
border-bottom: none;
}
.provinciaHeader {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 0.5rem;
}
.provinciaNombre {
font-weight: bold;
font-size: 1.1rem;
text-transform: uppercase;
}
.provinciaEscrutado {
font-size: 0.8rem;
color: #555;
font-weight: 500;
}
.resultadosLista {
list-style: none;
padding: 0;
margin: 0;
}
.resultadoItem {
display: flex;
justify-content: space-between;
padding: 0.25rem 0;
}
.partidoNombre {
color: #333;
}
.partidoPorcentaje {
font-weight: bold;
}

View File

@@ -0,0 +1,61 @@
// src/components/widgets/ResumenNacionalWidget.tsx
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import Select from 'react-select';
import { getResumenNacionalPorProvincia } from '../../../apiService';
import styles from './ResumenNacionalWidget.module.css';
const ELECCION_ID = 2; // Exclusivo para elecciones nacionales
const CATEGORIAS_NACIONALES = [
{ value: 3, label: 'Diputados Nacionales' },
{ value: 2, label: 'Senadores Nacionales' },
];
export const ResumenNacionalWidget = () => {
const [categoria, setCategoria] = useState(CATEGORIAS_NACIONALES[0]);
const { data, isLoading, error } = useQuery({
queryKey: ['resumenNacional', ELECCION_ID, categoria.value],
queryFn: () => getResumenNacionalPorProvincia(ELECCION_ID, categoria.value),
refetchInterval: 60000,
});
const formatPercent = (num: number) => `${num.toFixed(2)}%`;
return (
<div className={styles.widgetContainer}>
<div className={styles.header}>
<h3>{categoria.label}</h3>
<Select
className={styles.categoriaSelector}
options={CATEGORIAS_NACIONALES}
value={categoria}
onChange={(opt) => setCategoria(opt!)}
isSearchable={false}
/>
</div>
{isLoading && <p>Cargando resumen nacional...</p>}
{error && <p style={{ color: 'red' }}>Error al cargar los datos.</p>}
{data && (
<ul className={styles.listaProvincias}>
{data.map((provincia) => (
<li key={provincia.provinciaId} className={styles.provinciaItem}>
<div className={styles.provinciaHeader}>
<span className={styles.provinciaNombre}>{provincia.provinciaNombre}</span>
<span className={styles.provinciaEscrutado}>ESCR. {formatPercent(provincia.porcentajeEscrutado)}</span>
</div>
<ul className={styles.resultadosLista}>
{provincia.resultados.map((partido, index) => (
<li key={index} className={styles.resultadoItem}>
<span className={styles.partidoNombre}>{partido.nombre}</span>
<span className={styles.partidoPorcentaje}>{formatPercent(partido.porcentaje)}</span>
</li>
))}
</ul>
</li>
))}
</ul>
)}
</div>
);
};