350 lines
12 KiB
TypeScript
350 lines
12 KiB
TypeScript
// src/apiService.ts
|
|
import axios from 'axios';
|
|
import type {
|
|
ApiResponseRankingMunicipio, ApiResponseRankingSeccion,
|
|
ApiResponseTablaDetallada, ProyeccionBancas, MunicipioSimple,
|
|
TelegramaData, CatalogoItem, CategoriaResumen, ResultadoTicker,
|
|
ApiResponseResultadosPorSeccion, PanelElectoralDto, ResumenProvincia,
|
|
CategoriaResumenHome, ResultadoFila, ResultadoSeccion
|
|
} from './types/types';
|
|
|
|
/**
|
|
* URL base para las llamadas a la API.
|
|
* - En desarrollo, apunta directamente al backend de .NET.
|
|
* - En producción, apunta al endpoint público de la API.
|
|
*/
|
|
export const API_BASE_URL = import.meta.env.DEV
|
|
? 'http://localhost:5217/api'
|
|
: 'https://elecciones2025.eldia.com/api';
|
|
|
|
/**
|
|
* URL base para los activos estáticos (imágenes, etc.) de la carpeta `public`.
|
|
* - En desarrollo, es una ruta relativa a la raíz (servida por Vite).
|
|
* - En producción, es la URL absoluta del dominio donde se alojan los widgets.
|
|
*/
|
|
export const assetBaseUrl = import.meta.env.DEV
|
|
? ''
|
|
: 'https://elecciones2025.eldia.com';
|
|
|
|
const apiClient = axios.create({
|
|
baseURL: API_BASE_URL,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
});
|
|
|
|
interface PartidoData {
|
|
id: string;
|
|
nombre: string;
|
|
nombreCorto: string | null;
|
|
bancasTotales: number;
|
|
color: string | null;
|
|
}
|
|
|
|
interface CamaraData {
|
|
camaraNombre: string;
|
|
totalBancas: number;
|
|
bancasEnJuego: number;
|
|
partidos: PartidoData[];
|
|
presidenteBancada: { color: string | null } | null;
|
|
}
|
|
|
|
export interface ComposicionData {
|
|
diputados: CamaraData;
|
|
senadores: CamaraData;
|
|
}
|
|
|
|
export interface OcupanteBanca {
|
|
id: number;
|
|
nombreOcupante: string;
|
|
fotoUrl: string | null;
|
|
periodo: string | null;
|
|
}
|
|
|
|
interface PartidoData {
|
|
id: string;
|
|
nombre: string;
|
|
nombreCorto: string | null;
|
|
bancasTotales: number;
|
|
color: string | null;
|
|
ocupantes: OcupanteBanca[];
|
|
}
|
|
|
|
export interface BancadaDetalle {
|
|
id: number; // Este es el ID de la Bancada
|
|
camara: number; // 0 o 1
|
|
numeroBanca: number;
|
|
agrupacionPoliticaId: string | null;
|
|
ocupante: OcupanteBanca | null;
|
|
}
|
|
|
|
export interface ConfiguracionPublica {
|
|
TickerResultadosCantidad?: string;
|
|
ConcejalesResultadosCantidad?: string;
|
|
}
|
|
|
|
export interface ResultadoDetalleSeccion {
|
|
id: string; // ID de la agrupación para la key
|
|
nombre: string;
|
|
votos: number;
|
|
porcentaje: number;
|
|
color: string | null;
|
|
}
|
|
|
|
export interface PartidoComposicionNacional {
|
|
id: string;
|
|
nombre: string;
|
|
nombreCorto: string | null;
|
|
color: string | null;
|
|
bancasFijos: number;
|
|
bancasGanadas: number;
|
|
bancasTotales: number;
|
|
ordenDiputadosNacionales: number | null;
|
|
ordenSenadoresNacionales: number | null;
|
|
}
|
|
|
|
export interface CamaraComposicionNacional {
|
|
camaraNombre: string;
|
|
totalBancas: number;
|
|
bancasEnJuego: number;
|
|
partidos: PartidoComposicionNacional[];
|
|
presidenteBancada: { color: string | null; tipoBanca: 'ganada' | 'previa' | null } | null;
|
|
ultimaActualizacion: string;
|
|
}
|
|
|
|
export interface ComposicionNacionalData {
|
|
diputados: CamaraComposicionNacional;
|
|
senadores: CamaraComposicionNacional;
|
|
}
|
|
|
|
export interface ResumenParams {
|
|
focoDistritoId?: string;
|
|
focoCategoriaId?: number;
|
|
cantidadResultados?: number;
|
|
}
|
|
|
|
export const getResumenProvincial = async (eleccionId: number): Promise<CategoriaResumen[]> => {
|
|
const response = await apiClient.get(`/elecciones/${eleccionId}/provincia/02`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getBancasPorSeccion = async (eleccionId: number, seccionId: string, camara: 'diputados' | 'senadores'): Promise<ProyeccionBancas> => {
|
|
const { data } = await apiClient.get(`/elecciones/${eleccionId}/bancas-por-seccion/${seccionId}/${camara}`);
|
|
return data;
|
|
};
|
|
|
|
/**
|
|
* Obtiene la lista de Secciones Electorales desde la API.
|
|
*/
|
|
export const getSeccionesElectorales = async (categoriaId?: number): Promise<MunicipioSimple[]> => {
|
|
let url = '/catalogos/secciones-electorales';
|
|
// Si se proporciona una categoría, la añadimos a la URL
|
|
if (categoriaId) {
|
|
url += `?categoriaId=${categoriaId}`;
|
|
}
|
|
const response = await apiClient.get(url);
|
|
return response.data;
|
|
};
|
|
|
|
/**
|
|
* Obtiene los datos completos de un telegrama por su ID de mesa.
|
|
*/
|
|
export const getTelegramaPorId = async (mesaId: string): Promise<TelegramaData> => {
|
|
const response = await apiClient.get(`/telegramas/${mesaId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getSecciones = async (): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get('/catalogos/secciones');
|
|
return response.data;
|
|
};
|
|
|
|
export const getMunicipiosPorSeccion = async (seccionId: string): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get(`/catalogos/municipios/${seccionId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getCircuitosPorMunicipio = async (municipioId: string): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get(`/catalogos/circuitos/${municipioId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getEstablecimientosPorCircuito = async (circuitoId: string): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get(`/catalogos/establecimientos/${circuitoId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getMesasPorEstablecimiento = async (establecimientoId: string): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get(`/catalogos/mesas/${establecimientoId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getComposicionCongreso = async (eleccionId: number): Promise<ComposicionData> => {
|
|
const response = await apiClient.get(`/elecciones/${eleccionId}/composicion-congreso`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getBancadasDetalle = async (eleccionId: number): Promise<BancadaDetalle[]> => {
|
|
const response = await apiClient.get(`/elecciones/${eleccionId}/bancadas-detalle`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getConfiguracionPublica = async (): Promise<ConfiguracionPublica> => {
|
|
const response = await apiClient.get('/resultados/configuracion-publica');
|
|
return response.data;
|
|
};
|
|
|
|
export const getResultadosPorSeccion = async (eleccionId: number, seccionId: string, categoriaId: number): Promise<ApiResponseResultadosPorSeccion> => {
|
|
const response = await apiClient.get(`/elecciones/${eleccionId}/seccion-resultados/${seccionId}?categoriaId=${categoriaId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getDetalleSeccion = async (eleccionId: number, seccionId: string, categoriaId: number): Promise<ResultadoDetalleSeccion[]> => {
|
|
const response = await apiClient.get(`/elecciones/${eleccionId}/seccion/${seccionId}?categoriaId=${categoriaId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getResultadosPorMunicipio = async (eleccionId: number, municipioId: string, categoriaId: number): Promise<ResultadoTicker[]> => {
|
|
const response = await apiClient.get(`/elecciones/${eleccionId}/partido/${municipioId}?categoriaId=${categoriaId}`);
|
|
return response.data.resultados;
|
|
};
|
|
|
|
export const getMunicipios = async (categoriaId?: number): Promise<MunicipioSimple[]> => {
|
|
let url = '/catalogos/municipios';
|
|
if (categoriaId) {
|
|
url += `?categoriaId=${categoriaId}`;
|
|
}
|
|
const response = await apiClient.get(url);
|
|
|
|
// --- CORRECCIÓN ---
|
|
// La API devuelve un array de objetos con las propiedades { id, nombre }.
|
|
// Ya no es necesario mapear. Simplemente devolvemos los datos como vienen.
|
|
return response.data;
|
|
};
|
|
|
|
export const getSeccionesElectoralesConCargos = async (): Promise<MunicipioSimple[]> => {
|
|
// Hacemos la petición al nuevo endpoint del backend
|
|
const { data } = await apiClient.get<MunicipioSimple[]>('/resultados/secciones-electorales-con-cargos');
|
|
return data;
|
|
};
|
|
|
|
export const getResultadosTablaDetallada = async (seccionId: string): Promise<ApiResponseTablaDetallada> => {
|
|
const { data } = await apiClient.get(`/resultados/tabla-ranking-seccion/${seccionId}`);
|
|
return data;
|
|
};
|
|
|
|
export const getRankingResultadosPorSeccion = async (seccionId: string): Promise<ApiResponseRankingSeccion> => {
|
|
const { data } = await apiClient.get(`/resultados/ranking-por-seccion/${seccionId}`);
|
|
return data;
|
|
};
|
|
|
|
export const getRankingMunicipiosPorSeccion = async (seccionId: string): Promise<ApiResponseRankingMunicipio> => {
|
|
const { data } = await apiClient.get(`/resultados/ranking-municipios-por-seccion/${seccionId}`);
|
|
return data;
|
|
};
|
|
|
|
export const getEstablecimientosPorMunicipio = async (municipioId: string): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get(`/catalogos/establecimientos-por-municipio/${municipioId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getPanelElectoral = async (
|
|
eleccionId: number,
|
|
ambitoId: string | null,
|
|
categoriaId: number,
|
|
nivel: 'pais' | 'provincia' | 'municipio'
|
|
): Promise<PanelElectoralDto> => {
|
|
|
|
let url: string;
|
|
|
|
// Construimos la URL con el prefijo correcto.
|
|
if (nivel === 'pais' || !ambitoId) {
|
|
url = `/elecciones/${eleccionId}/panel`;
|
|
} else if (nivel === 'provincia') {
|
|
url = `/elecciones/${eleccionId}/panel/distrito:${ambitoId}`;
|
|
} else { // nivel === 'municipio'
|
|
url = `/elecciones/${eleccionId}/panel/municipio:${ambitoId}`;
|
|
}
|
|
|
|
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.`);
|
|
return {
|
|
ambitoNombre: 'Sin Datos',
|
|
mapaData: [],
|
|
resultadosPanel: [],
|
|
estadoRecuento: { participacionPorcentaje: 0, mesasTotalizadasPorcentaje: 0 },
|
|
sinDatos: true,
|
|
};
|
|
}
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
export const getComposicionNacional = async (eleccionId: number): Promise<ComposicionNacionalData> => {
|
|
const { data } = await apiClient.get(`/elecciones/${eleccionId}/composicion-nacional`);
|
|
return data;
|
|
};
|
|
|
|
// 11. Endpoint para el widget de tarjetas nacionales
|
|
export const getResumenPorProvincia = async (eleccionId: number, params: ResumenParams = {}): Promise<ResumenProvincia[]> => {
|
|
// Usamos URLSearchParams para construir la query string de forma segura y limpia
|
|
const queryParams = new URLSearchParams();
|
|
|
|
if (params.focoDistritoId) {
|
|
queryParams.append('focoDistritoId', params.focoDistritoId);
|
|
}
|
|
if (params.focoCategoriaId) {
|
|
queryParams.append('focoCategoriaId', params.focoCategoriaId.toString());
|
|
}
|
|
if (params.cantidadResultados) {
|
|
queryParams.append('cantidadResultados', params.cantidadResultados.toString());
|
|
}
|
|
|
|
const queryString = queryParams.toString();
|
|
|
|
// Añadimos la query string a la URL solo si tiene contenido
|
|
const url = `/elecciones/${eleccionId}/resumen-por-provincia${queryString ? `?${queryString}` : ''}`;
|
|
|
|
const { data } = await apiClient.get(url);
|
|
return data;
|
|
};
|
|
|
|
export const getMunicipiosPorDistrito = async (distritoId: string): Promise<CatalogoItem[]> => {
|
|
const response = await apiClient.get(`/catalogos/municipios-por-distrito/${distritoId}`);
|
|
return response.data;
|
|
};
|
|
|
|
export const getHomeResumen = async (eleccionId: number, distritoId: string, categoriaId: number): Promise<CategoriaResumenHome> => {
|
|
const queryParams = new URLSearchParams({
|
|
eleccionId: eleccionId.toString(),
|
|
distritoId: distritoId,
|
|
categoriaId: categoriaId.toString(),
|
|
});
|
|
const url = `/elecciones/home-resumen?${queryParams.toString()}`;
|
|
const { data } = await apiClient.get(url);
|
|
return data;
|
|
};
|
|
|
|
export const getHomeResumenNacional = async (eleccionId: number, categoriaId: number): Promise<CategoriaResumenHome> => {
|
|
const queryParams = new URLSearchParams({
|
|
eleccionId: eleccionId.toString(),
|
|
categoriaId: categoriaId.toString(),
|
|
});
|
|
const url = `/elecciones/home-resumen-nacional?${queryParams.toString()}`;
|
|
const { data } = await apiClient.get(url);
|
|
return data;
|
|
};
|
|
|
|
export const getTablaConurbano = async (eleccionId: number): Promise<ResultadoFila[]> => {
|
|
const { data } = await apiClient.get(`/elecciones/${eleccionId}/tabla-conurbano`);
|
|
return data;
|
|
};
|
|
|
|
export const getTablaSecciones = async (eleccionId: number): Promise<ResultadoSeccion[]> => {
|
|
const { data } = await apiClient.get(`/elecciones/${eleccionId}/tabla-secciones`);
|
|
return data;
|
|
}; |