Fix Mapa Error (Sección Sin Datos)
This commit is contained in:
@@ -252,12 +252,26 @@ export const getPanelElectoral = async (eleccionId: number, ambitoId: string | n
|
||||
let url = ambitoId
|
||||
? `/elecciones/${eleccionId}/panel/${ambitoId}`
|
||||
: `/elecciones/${eleccionId}/panel`;
|
||||
|
||||
// Añadimos categoriaId como un query parameter
|
||||
url += `?categoriaId=${categoriaId}`;
|
||||
|
||||
try {
|
||||
const { data } = await apiClient.get(url);
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
||||
console.warn(`API devolvió 404 para ${url}. Devolviendo un estado vacío.`);
|
||||
|
||||
// Devolvemos el objeto vacío PERO con la nueva bandera activada
|
||||
return {
|
||||
ambitoNombre: 'Sin Datos',
|
||||
mapaData: [],
|
||||
resultadosPanel: [],
|
||||
estadoRecuento: { participacionPorcentaje: 0, mesasTotalizadasPorcentaje: 0 },
|
||||
sinDatos: true,
|
||||
};
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const getComposicionNacional = async (eleccionId: number): Promise<ComposicionNacionalData> => {
|
||||
|
||||
@@ -13,9 +13,10 @@ import Select from 'react-select';
|
||||
import type { PanelElectoralDto, ResultadoTicker } from '../../../types/types';
|
||||
import { FiMap, FiList, FiChevronDown, FiChevronUp } from 'react-icons/fi';
|
||||
import { useMediaQuery } from './hooks/useMediaQuery';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
import toast, { Toaster } from 'react-hot-toast';
|
||||
import { ImageWithFallback } from '../../../components/common/ImageWithFallback';
|
||||
import { assetBaseUrl } from '../../../apiService';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
// --- COMPONENTE INTERNO PARA LA TARJETA DE RESULTADOS EN MÓVIL ---
|
||||
interface MobileResultsCardProps {
|
||||
@@ -157,10 +158,22 @@ const PanelContenido = ({ eleccionId, ambitoActual, categoriaId }: { eleccionId:
|
||||
queryKey: ['panelElectoral', eleccionId, ambitoActual.id, categoriaId],
|
||||
queryFn: () => getPanelElectoral(eleccionId, ambitoActual.id, categoriaId),
|
||||
});
|
||||
// Si la API devolvió la bandera 'sinDatos', mostramos un mensaje.
|
||||
if (data.sinDatos) {
|
||||
return (
|
||||
<div style={{ padding: '2rem', textAlign: 'center', color: '#666' }}>
|
||||
<h4>Sin Resultados Detallados</h4>
|
||||
<p>Aún no hay datos disponibles para esta selección.</p>
|
||||
<p>Por favor, intente de nuevo más tarde.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Si no, renderizamos los resultados.
|
||||
return <PanelResultados resultados={data.resultadosPanel} estadoRecuento={data.estadoRecuento} />;
|
||||
};
|
||||
|
||||
export const PanelNacionalWidget = ({ eleccionId }: PanelNacionalWidgetProps) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [ambitoActual, setAmbitoActual] = useState<AmbitoState>({ id: null, nivel: 'pais', nombre: 'Argentina', provinciaDistritoId: null });
|
||||
const [categoriaId, setCategoriaId] = useState<number>(2);
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(true);
|
||||
@@ -168,6 +181,16 @@ export const PanelNacionalWidget = ({ eleccionId }: PanelNacionalWidgetProps) =>
|
||||
const isMobile = useMediaQuery('(max-width: 800px)');
|
||||
|
||||
const handleAmbitoSelect = (nuevoAmbitoId: string, nuevoNivel: 'provincia' | 'municipio', nuevoNombre: string) => {
|
||||
if (nuevoNivel === 'municipio') {
|
||||
toast.promise(
|
||||
queryClient.invalidateQueries({ queryKey: ['panelElectoral', eleccionId, nuevoAmbitoId, categoriaId] }),
|
||||
{
|
||||
loading: `Cargando datos de ${nuevoNombre}...`,
|
||||
success: <b>Datos cargados</b>,
|
||||
error: <b>No se pudieron cargar los datos.</b>,
|
||||
}
|
||||
);
|
||||
}
|
||||
setAmbitoActual(prev => ({
|
||||
id: nuevoAmbitoId,
|
||||
nivel: nuevoNivel,
|
||||
@@ -208,14 +231,16 @@ export const PanelNacionalWidget = ({ eleccionId }: PanelNacionalWidgetProps) =>
|
||||
|
||||
return (
|
||||
<div className={styles.panelNacionalContainer}>
|
||||
<Toaster containerClassName={styles.widgetToasterContainer} />
|
||||
<Toaster
|
||||
position="bottom-center"
|
||||
containerClassName={styles.widgetToasterContainer}
|
||||
/>
|
||||
<header className={styles.panelHeader}>
|
||||
<div className={styles.headerTopRow}>
|
||||
<Select
|
||||
options={CATEGORIAS_NACIONALES}
|
||||
value={selectedCategoria}
|
||||
onChange={(option) => option && setCategoriaId(option.value)}
|
||||
// 4. Usamos un prefijo de clase simple que se asociará con las clases del módulo CSS
|
||||
classNamePrefix="categoriaSelector"
|
||||
className={styles.categoriaSelectorContainer}
|
||||
isSearchable={false}
|
||||
|
||||
@@ -195,7 +195,7 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom
|
||||
if (newZoom > initialProvincePositionRef.current.zoom) {
|
||||
toast.success('Desplazamiento Habilitado', {
|
||||
icon: '🖐️',
|
||||
style: { background: '#32e5f1ff', color: 'white' },
|
||||
style: { background: '#32e5f1ff', color: 'white', zIndex: 9999},
|
||||
duration: 1000,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ export interface PanelElectoralDto {
|
||||
mapaData: ResultadoMapaDto[];
|
||||
resultadosPanel: ResultadoTicker[];
|
||||
estadoRecuento: EstadoRecuentoTicker;
|
||||
sinDatos?: boolean;
|
||||
}
|
||||
|
||||
// --- TIPOS PARA EL WIDGET DE TARJETAS NACIONALES ---
|
||||
|
||||
Reference in New Issue
Block a user