Files
Elecciones-2025/Elecciones-Web/frontend/src/features/legislativas/nacionales/PanelNacionalWidget.tsx

125 lines
4.8 KiB
TypeScript
Raw Normal View History

// src/features/legislativas/nacionales/PanelNacionalWidget.tsx
import { useMemo, useState, Suspense } from 'react';
2025-09-19 17:19:10 -03:00
import { useSuspenseQuery } from '@tanstack/react-query';
import { getPanelElectoral } from '../../../apiService';
import { MapaNacional } from './components/MapaNacional';
import { PanelResultados } from './components/PanelResultados';
import { Breadcrumbs } from './components/Breadcrumbs';
import './PanelNacional.css';
import Select from 'react-select';
import type { PanelElectoralDto } from '../../../types/types';
interface PanelNacionalWidgetProps {
eleccionId: number;
}
type AmbitoState = {
id: string | null;
nivel: 'pais' | 'provincia' | 'municipio';
nombre: string;
provinciaNombre?: string;
provinciaDistritoId?: string | null;
};
const CATEGORIAS_NACIONALES = [
{ value: 2, label: 'Diputados Nacionales' },
{ value: 1, label: 'Senadores Nacionales' },
];
const PanelContenido = ({ eleccionId, ambitoActual, categoriaId }: { eleccionId: number, ambitoActual: AmbitoState, categoriaId: number }) => {
const { data } = useSuspenseQuery<PanelElectoralDto>({
queryKey: ['panelElectoral', eleccionId, ambitoActual.id, categoriaId],
queryFn: () => getPanelElectoral(eleccionId, ambitoActual.id, categoriaId),
});
2025-09-19 17:19:10 -03:00
return <PanelResultados resultados={data.resultadosPanel} estadoRecuento={data.estadoRecuento} />;
};
export const PanelNacionalWidget = ({ eleccionId }: PanelNacionalWidgetProps) => {
const [ambitoActual, setAmbitoActual] = useState<AmbitoState>({ id: null, nivel: 'pais', nombre: 'Argentina', provinciaDistritoId: null });
const [categoriaId, setCategoriaId] = useState<number>(2);
const [isPanelOpen, setIsPanelOpen] = useState(true);
const handleAmbitoSelect = (nuevoAmbitoId: string, nuevoNivel: 'provincia' | 'municipio', nuevoNombre: string) => {
setAmbitoActual(prev => ({
id: nuevoAmbitoId,
nivel: nuevoNivel,
nombre: nuevoNombre,
2025-09-19 17:19:10 -03:00
provinciaNombre: nuevoNivel === 'municipio' ? prev.provinciaNombre : (nuevoNivel === 'provincia' ? nuevoNombre : undefined),
provinciaDistritoId: nuevoNivel === 'provincia' ? nuevoAmbitoId : prev.provinciaDistritoId
}));
};
const handleResetToPais = () => {
setAmbitoActual({ id: null, nivel: 'pais', nombre: 'Argentina', provinciaDistritoId: null });
};
const handleVolverAProvincia = () => {
if (ambitoActual.provinciaDistritoId && ambitoActual.provinciaNombre) {
setAmbitoActual({
id: ambitoActual.provinciaDistritoId,
nivel: 'provincia',
nombre: ambitoActual.provinciaNombre,
2025-09-19 17:19:10 -03:00
provinciaDistritoId: ambitoActual.provinciaDistritoId,
provinciaNombre: ambitoActual.provinciaNombre,
});
} else {
handleResetToPais();
}
};
const selectedCategoria = useMemo(() =>
CATEGORIAS_NACIONALES.find(c => c.value === categoriaId),
[categoriaId]
);
return (
<div className="panel-nacional-container">
<header className="panel-header">
<div className="header-top-row">
<h1>Resultados elecciones {ambitoActual.nombre}</h1>
<Select
options={CATEGORIAS_NACIONALES}
value={selectedCategoria}
onChange={(option) => option && setCategoriaId(option.value)}
className="categoria-selector"
/>
</div>
<Breadcrumbs
nivel={ambitoActual.nivel}
nombreAmbito={ambitoActual.nombre}
nombreProvincia={ambitoActual.provinciaNombre}
onReset={handleResetToPais}
onVolverProvincia={handleVolverAProvincia}
/>
</header>
<main className={`panel-main-content ${!isPanelOpen ? 'panel-collapsed' : ''}`}>
<div className="mapa-column">
2025-09-19 17:19:10 -03:00
<button className="panel-toggle-btn" onClick={() => setIsPanelOpen(!isPanelOpen)} title={isPanelOpen ? "Ocultar panel" : "Mostrar panel"}>
{isPanelOpen ? '' : ''}
</button>
<Suspense fallback={<div className="spinner" />}>
<MapaNacional
eleccionId={eleccionId}
categoriaId={categoriaId}
nivel={ambitoActual.nivel}
nombreAmbito={ambitoActual.nombre}
2025-09-19 17:19:10 -03:00
nombreProvinciaActiva={ambitoActual.provinciaNombre}
provinciaDistritoId={ambitoActual.provinciaDistritoId ?? null}
onAmbitoSelect={handleAmbitoSelect}
onVolver={ambitoActual.nivel === 'municipio' ? handleVolverAProvincia : handleResetToPais}
/>
</Suspense>
</div>
<div className="resultados-column">
<Suspense fallback={<div className="spinner" />}>
<PanelContenido
eleccionId={eleccionId}
ambitoActual={ambitoActual}
categoriaId={categoriaId}
/>
</Suspense>
</div>
</main>
</div>
);
};