Feat Widgets Cards y Optimización de Consultas

This commit is contained in:
2025-09-28 19:04:09 -03:00
parent 67634ae947
commit 3b0eee25e6
71 changed files with 5415 additions and 442 deletions

View File

@@ -1,11 +1,12 @@
// src/services/apiService.ts
import axios from 'axios';
import { triggerLogout } from '../context/authUtils';
import type { CandidatoOverride, AgrupacionPolitica, UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria, MunicipioSimple } from '../types';
import type { CandidatoOverride, AgrupacionPolitica,
UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria,
MunicipioSimple, BancaPrevia, ProvinciaSimple } from '../types';
/**
* URL base para las llamadas a la API.
* Se usa para construir las URLs más específicas.
*/
const API_URL_BASE = import.meta.env.DEV
? 'http://localhost:5217/api'
@@ -21,13 +22,19 @@ export const AUTH_API_URL = `${API_URL_BASE}/auth`;
*/
export const ADMIN_API_URL = `${API_URL_BASE}/admin`;
// Cliente de API para endpoints de administración (requiere token)
const adminApiClient = axios.create({
baseURL: ADMIN_API_URL,
});
// --- INTERCEPTORES ---
// Cliente de API para endpoints públicos (no envía token)
const apiClient = axios.create({
baseURL: API_URL_BASE,
headers: { 'Content-Type': 'application/json' },
});
// Interceptor de Peticiones: Añade el token JWT a cada llamada
// --- INTERCEPTORES (Solo para el cliente de admin) ---
adminApiClient.interceptors.request.use(
(config) => {
const token = localStorage.getItem('admin-jwt-token');
@@ -39,7 +46,6 @@ adminApiClient.interceptors.request.use(
(error) => Promise.reject(error)
);
// Interceptor de Respuestas: Maneja la expiración del token (error 401)
adminApiClient.interceptors.response.use(
(response) => response,
(error) => {
@@ -51,6 +57,32 @@ adminApiClient.interceptors.response.use(
}
);
// --- INTERFACES PARA COMPOSICIÓN NACIONAL (NECESARIAS PARA EL NUEVO MÉTODO) ---
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;
}
export interface ComposicionNacionalData {
diputados: CamaraComposicionNacional;
senadores: CamaraComposicionNacional;
}
// --- SERVICIOS DE API ---
// 1. Autenticación
@@ -66,7 +98,7 @@ export const loginUser = async (credentials: LoginCredentials): Promise<string |
}
};
// 2. Agrupaciones Políticas
// 2. Agrupaciones
export const getAgrupaciones = async (): Promise<AgrupacionPolitica[]> => {
const response = await adminApiClient.get('/agrupaciones');
return response.data;
@@ -77,14 +109,14 @@ export const updateAgrupacion = async (id: string, data: UpdateAgrupacionData):
};
// 3. Ordenamiento de Agrupaciones
export const updateOrden = async (camara: 'diputados' | 'senadores', ids: string[]): Promise<void> => {
export const updateOrden = async (camara: 'diputados' | 'senadores' | 'diputados-nacionales' | 'senadores-nacionales', ids: string[]): Promise<void> => {
await adminApiClient.put(`/agrupaciones/orden-${camara}`, ids);
};
// 4. Gestión de Bancas y Ocupantes
export const getBancadas = async (camara: 'diputados' | 'senadores'): Promise<Bancada[]> => {
const camaraId = camara === 'diputados' ? 0 : 1;
const response = await adminApiClient.get(`/bancadas/${camaraId}`);
// 4. Gestión de Bancas
export const getBancadas = async (camara: 'diputados' | 'senadores', eleccionId: number): Promise<Bancada[]> => {
const camaraId = (camara === 'diputados') ? 0 : 1;
const response = await adminApiClient.get(`/bancadas/${camaraId}?eleccionId=${eleccionId}`);
return response.data;
};
@@ -111,38 +143,52 @@ export const updateConfiguracion = async (data: Record<string, string>): Promise
await adminApiClient.put('/configuracion', data);
};
export const getLogos = async (): Promise<LogoAgrupacionCategoria[]> => {
const response = await adminApiClient.get('/logos');
// 6. Logos y Candidatos
export const getLogos = async (eleccionId: number): Promise<LogoAgrupacionCategoria[]> => {
const response = await adminApiClient.get(`/logos?eleccionId=${eleccionId}`);
return response.data;
};
export const updateLogos = async (data: LogoAgrupacionCategoria[]): Promise<void> => {
await adminApiClient.put('/logos', data);
};
export const getMunicipiosForAdmin = async (): Promise<MunicipioSimple[]> => {
// Ahora usa adminApiClient, que apunta a /api/admin/
// La URL final será /api/admin/catalogos/municipios
const response = await adminApiClient.get('/catalogos/municipios');
export const getCandidatos = async (eleccionId: number): Promise<CandidatoOverride[]> => {
const response = await adminApiClient.get(`/candidatos?eleccionId=${eleccionId}`);
return response.data;
};
// 6. Overrides de Candidatos
export const getCandidatos = async (): Promise<CandidatoOverride[]> => {
const response = await adminApiClient.get('/candidatos');
return response.data;
};
export const updateCandidatos = async (data: CandidatoOverride[]): Promise<void> => {
await adminApiClient.put('/candidatos', data);
};
// 7. Gestión de Logging
export interface UpdateLoggingLevelData {
level: string;
}
// 7. Catálogos
export const getMunicipiosForAdmin = async (): Promise<MunicipioSimple[]> => {
const response = await adminApiClient.get('/catalogos/municipios');
return response.data;
};
// 8. Logging
export interface UpdateLoggingLevelData { level: string; }
export const updateLoggingLevel = async (data: UpdateLoggingLevelData): Promise<void> => {
// Este endpoint es específico, no es parte de la configuración general
await adminApiClient.put(`/logging-level`, data);
};
// 9. Bancas Previas
export const getBancasPrevias = async (eleccionId: number): Promise<BancaPrevia[]> => {
const response = await adminApiClient.get(`/bancas-previas/${eleccionId}`);
return response.data;
};
export const updateBancasPrevias = async (eleccionId: number, data: BancaPrevia[]): Promise<void> => {
await adminApiClient.put(`/bancas-previas/${eleccionId}`, data);
};
// 10. Obtener Composición Nacional (Endpoint Público)
export const getComposicionNacional = async (eleccionId: number): Promise<ComposicionNacionalData> => {
// Este es un endpoint público, por lo que usamos el cliente sin token de admin.
const response = await apiClient.get(`/elecciones/${eleccionId}/composicion-nacional`);
return response.data;
};
// Obtenemos las provincias para el selector de ámbito
export const getProvinciasForAdmin = async (): Promise<ProvinciaSimple[]> => {
const response = await adminApiClient.get('/catalogos/provincias');
return response.data;
};