Feat: Implementar API de resultados y widget de prueba dinámico con selector

API (Backend):
Se crea el endpoint GET /api/resultados/municipio/{id} para servir los resultados detallados de un municipio específico.
Se añade el endpoint GET /api/catalogos/municipios para poblar selectores en el frontend.
Se incluye un endpoint simulado GET /api/resultados/provincia/{id} para facilitar el desarrollo futuro del frontend.
Worker (Servicio de Ingesta):
La lógica de sondeo se ha hecho dinámica. Ahora consulta todos los municipios presentes en la base de datos en lugar de uno solo.
El servicio falso (FakeElectoralApiService) se ha mejorado para generar datos aleatorios para cualquier municipio solicitado.
Frontend (React):
Se crea el componente <MunicipioSelector /> que se carga con datos desde la nueva API de catálogos.
Se integra el selector en la página principal, permitiendo al usuario elegir un municipio.
El componente <MunicipioWidget /> ahora recibe el ID del municipio como una prop y muestra los datos del municipio seleccionado, actualizándose en tiempo real.
Configuración:
Se ajusta la política de CORS en la API para permitir peticiones desde el servidor de desarrollo de Vite (localhost:5173), solucionando errores de conexión en el entorno local.
This commit is contained in:
2025-08-14 15:27:45 -03:00
parent b90baadeed
commit 1d58023113
70 changed files with 5563 additions and 89 deletions

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/AgrupacionDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class AgrupacionDto
{
[JsonPropertyName("idAgrupacion")]
public string IdAgrupacion { get; set; } = null!;
[JsonPropertyName("idAgrupacionTelegrama")]
public string IdAgrupacionTelegrama { get; set; } = null!;
[JsonPropertyName("nombreAgrupacion")]
public string NombreAgrupacion { get; set; } = null!;
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/AmbitoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class AmbitoDto
{
[JsonPropertyName("nivelld")]
public int NivelId { get; set; }
[JsonPropertyName("nombre")]
public string Nombre { get; set; } = null!;
[JsonPropertyName("codigoAmbitos")]
public CodigoAmbitoDto CodigoAmbitos { get; set; } = null!;
}

View File

@@ -0,0 +1,9 @@
// src/Elecciones.Core/DTOs/ApiResponses/AgrupacionResultadoDto.cs
namespace Elecciones.Core.DTOs.ApiResponses;
public class AgrupacionResultadoDto
{
public string Nombre { get; set; } = null!;
public long Votos { get; set; }
public decimal Porcentaje { get; set; }
}

View File

@@ -0,0 +1,14 @@
// src/Elecciones.Core/DTOs/ApiResponses/MunicipioResultadosDto.cs
namespace Elecciones.Core.DTOs.ApiResponses;
public class MunicipioResultadosDto
{
public string MunicipioNombre { get; set; } = null!;
public DateTime UltimaActualizacion { get; set; }
public decimal PorcentajeEscrutado { get; set; }
public decimal PorcentajeParticipacion { get; set; }
public List<AgrupacionResultadoDto> Resultados { get; set; } = [];
public VotosAdicionalesDto VotosAdicionales { get; set; } = null!;
}

View File

@@ -0,0 +1,7 @@
namespace Elecciones.Core.DTOs.ApiResponses;
public class MunicipioSimpleDto
{
public string Id { get; set; } = null!;
public string Nombre { get; set; } = null!;
}

View File

@@ -0,0 +1,11 @@
namespace Elecciones.Core.DTOs.ApiResponses;
public class ResumenProvincialDto
{
public string ProvinciaNombre { get; set; } = null!;
public DateTime UltimaActualizacion { get; set; }
public decimal PorcentajeEscrutado { get; set; }
public decimal PorcentajeParticipacion { get; set; }
public List<AgrupacionResultadoDto> Resultados { get; set; } = [];
public VotosAdicionalesDto VotosAdicionales { get; set; } = null!;
}

View File

@@ -0,0 +1,9 @@
// src/Elecciones.Core/DTOs/ApiResponses/VotosAdicionalesDto.cs
namespace Elecciones.Core.DTOs.ApiResponses;
public class VotosAdicionalesDto
{
public long EnBlanco { get; set; }
public long Nulos { get; set; }
public long Recurridos { get; set; }
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/CatalogoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class CatalogoDto
{
[JsonPropertyName("version")]
public int Version { get; set; }
[JsonPropertyName("categoriald")]
public int CategoriaId { get; set; }
[JsonPropertyName("ambitos")]
public List<AmbitoDto> Ambitos { get; set; } = [];
[JsonPropertyName("niveles")]
public List<NivelDto> Niveles { get; set; } = [];
}

View File

@@ -0,0 +1,20 @@
// src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class CodigoAmbitoDto
{
[JsonPropertyName("distritold")]
public string DistritoId { get; set; } = null!;
// Hacemos que los demás IDs acepten nulos para ser más flexibles
[JsonPropertyName("seccionProvincialld")]
public string? SeccionProvincialId { get; set; }
[JsonPropertyName("seccionld")]
public string? SeccionId { get; set; }
[JsonPropertyName("municipiold")]
public string? MunicipioId { get; set; }
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/EstadoRecuentoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class EstadoRecuentoDto
{
[JsonPropertyName("mesasEsperadas")]
public int MesasEsperadas { get; set; }
[JsonPropertyName("mesasTotalizadas")]
public int MesasTotalizadas { get; set; }
[JsonPropertyName("cantidadElectores")]
public int CantidadElectores { get; set; }
[JsonPropertyName("participacionPorcentaje")]
public decimal ParticipacionPorcentaje { get; set; }
}

View File

@@ -0,0 +1,13 @@
// src/Elecciones.Core/DTOs/NivelDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class NivelDto
{
[JsonPropertyName("nivelld")]
public int NivelId { get; set; }
[JsonPropertyName("nombre")]
public string Nombre { get; set; } = null!;
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/ResultadosDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class ResultadosDto
{
[JsonPropertyName("fechaTotalizacion")]
public string FechaTotalizacion { get; set; } = null!;
[JsonPropertyName("estadoRecuento")]
public EstadoRecuentoDto EstadoRecuento { get; set; } = null!;
[JsonPropertyName("valoresTotalizadosPositivos")]
public List<VotosPositivosDto> ValoresTotalizadosPositivos { get; set; } = [];
[JsonPropertyName("valoresTotalizadosOtros")]
public VotosOtrosDto? ValoresTotalizadosOtros { get; set; }
}

View File

@@ -0,0 +1,13 @@
// src/Elecciones.Core/DTOs/TokenData.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class TokenData
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; } = null!;
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/TokenResponse.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class TokenResponse
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; } = null!;
[JsonPropertyName("data")]
public TokenData? Data { get; set; }
[JsonPropertyName("error")]
public string? Error { get; set; }
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/VotosOtrosDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class VotosOtrosDto
{
[JsonPropertyName("votosNulos")]
public long VotosNulos { get; set; }
[JsonPropertyName("votosEnBlanco")]
public long VotosEnBlanco { get; set; }
[JsonPropertyName("votosRecurridosComandoImpugnados")]
public long VotosRecurridos { get; set; }
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/VotosPositivosDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class VotosPositivosDto
{
[JsonPropertyName("idAgrupacion")]
public string IdAgrupacion { get; set; } = null!;
[JsonPropertyName("nombreAgrupacion")]
public string NombreAgrupacion { get; set; } = null!;
[JsonPropertyName("votos")]
public long Votos { get; set; }
}