// src/services/apiService.ts import axios from 'axios'; import { triggerLogout } from '../context/authUtils'; import type { CandidatoOverride, AgrupacionPolitica, UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria, MunicipioSimple, BancaPrevia, ProvinciaSimple } from '../types'; /** * URL base para las llamadas a la API. */ const API_URL_BASE = import.meta.env.DEV ? 'http://localhost:5217/api' : 'https://elecciones2025.eldia.com/api'; /** * URL completa para el endpoint de autenticación. */ export const AUTH_API_URL = `${API_URL_BASE}/auth`; /** * URL completa para los endpoints de administración. */ 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, }); // Cliente de API para endpoints públicos (no envía token) const apiClient = axios.create({ baseURL: API_URL_BASE, headers: { 'Content-Type': 'application/json' }, }); // --- INTERCEPTORES (Solo para el cliente de admin) --- adminApiClient.interceptors.request.use( (config) => { const token = localStorage.getItem('admin-jwt-token'); if (token) { config.headers['Authorization'] = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); adminApiClient.interceptors.response.use( (response) => response, (error) => { if (axios.isAxiosError(error) && error.response?.status === 401) { console.log("Token expirado o inválido. Deslogueando..."); triggerLogout(); } return Promise.reject(error); } ); // --- 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 export interface LoginCredentials { username: string; password: string; } export const loginUser = async (credentials: LoginCredentials): Promise => { try { const response = await axios.post(`${AUTH_API_URL}/login`, credentials); return response.data.token; } catch (error) { console.error("Error during login request:", error); throw error; } }; // 2. Agrupaciones export const getAgrupaciones = async (): Promise => { const response = await adminApiClient.get('/agrupaciones'); return response.data; }; export const updateAgrupacion = async (id: string, data: UpdateAgrupacionData): Promise => { await adminApiClient.put(`/agrupaciones/${id}`, data); }; // 3. Ordenamiento de Agrupaciones export const updateOrden = async (camara: 'diputados' | 'senadores' | 'diputados-nacionales' | 'senadores-nacionales', ids: string[]): Promise => { await adminApiClient.put(`/agrupaciones/orden-${camara}`, ids); }; // 4. Gestión de Bancas export const getBancadas = async (camara: 'diputados' | 'senadores', eleccionId: number): Promise => { const camaraId = (camara === 'diputados') ? 0 : 1; const response = await adminApiClient.get(`/bancadas/${camaraId}?eleccionId=${eleccionId}`); return response.data; }; export interface UpdateBancadaData { agrupacionPoliticaId: string | null; nombreOcupante: string | null; fotoUrl: string | null; periodo: string | null; } export const updateBancada = async (bancadaId: number, data: UpdateBancadaData): Promise => { await adminApiClient.put(`/bancadas/${bancadaId}`, data); }; // 5. Configuración General export type ConfiguracionResponse = Record; export const getConfiguracion = async (): Promise => { const response = await adminApiClient.get('/configuracion'); return response.data; }; export const updateConfiguracion = async (data: Record): Promise => { await adminApiClient.put('/configuracion', data); }; // 6. Logos y Candidatos export const getLogos = async (eleccionId: number): Promise => { const response = await adminApiClient.get(`/logos?eleccionId=${eleccionId}`); return response.data; }; export const updateLogos = async (data: LogoAgrupacionCategoria[]): Promise => { await adminApiClient.put('/logos', data); }; export const getCandidatos = async (eleccionId: number): Promise => { const response = await adminApiClient.get(`/candidatos?eleccionId=${eleccionId}`); return response.data; }; export const updateCandidatos = async (data: CandidatoOverride[]): Promise => { await adminApiClient.put('/candidatos', data); }; // 7. Catálogos export const getMunicipiosForAdmin = async (): Promise => { const response = await adminApiClient.get('/catalogos/municipios'); return response.data; }; // 8. Logging export interface UpdateLoggingLevelData { level: string; } export const updateLoggingLevel = async (data: UpdateLoggingLevelData): Promise => { await adminApiClient.put(`/logging-level`, data); }; // 9. Bancas Previas export const getBancasPrevias = async (eleccionId: number): Promise => { const response = await adminApiClient.get(`/bancas-previas/${eleccionId}`); return response.data; }; export const updateBancasPrevias = async (eleccionId: number, data: BancaPrevia[]): Promise => { await adminApiClient.put(`/bancas-previas/${eleccionId}`, data); }; // 10. Obtener Composición Nacional (Endpoint Público) export const getComposicionNacional = async (eleccionId: number): Promise => { // 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 => { const response = await adminApiClient.get('/catalogos/provincias'); return response.data; }; export interface CreateAgrupacionData { nombre: string; nombreCorto: string | null; color: string | null; } // Servicio para crear una nueva agrupación export const createAgrupacion = async (data: CreateAgrupacionData): Promise => { const response = await adminApiClient.post('/agrupaciones', data); return response.data; };