Fix bancas widget
This commit is contained in:
@@ -1,73 +1,68 @@
|
||||
// src/components/ConfiguracionGeneral.tsx
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { getAgrupaciones, getConfiguracion, updateConfiguracion } from '../services/apiService';
|
||||
import type { AgrupacionPolitica } from '../types';
|
||||
import './AgrupacionesManager.css'; // Reutilizamos los estilos para mantener la consistencia
|
||||
import './AgrupacionesManager.css';
|
||||
|
||||
export const ConfiguracionGeneral = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
// Estado específico para la configuración de la presidencia del Senado
|
||||
|
||||
const [presidenciaSenadoId, setPresidenciaSenadoId] = useState<string>('');
|
||||
const [usarDatosOficiales, setUsarDatosOficiales] = useState(false);
|
||||
// Renombramos el estado para mayor claridad
|
||||
const [modoOficialActivo, setModoOficialActivo] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const loadInitialData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Hacemos ambas llamadas a la API en paralelo para más eficiencia
|
||||
const [agrupacionesData, configData] = await Promise.all([
|
||||
getAgrupaciones(),
|
||||
getConfiguracion()
|
||||
]);
|
||||
|
||||
const [agrupacionesData, configData] = await Promise.all([getAgrupaciones(), getConfiguracion()]);
|
||||
setAgrupaciones(agrupacionesData);
|
||||
|
||||
// Asignamos el valor guardado, si existe
|
||||
if (configData && configData.PresidenciaSenadores) {
|
||||
setPresidenciaSenadoId(configData.PresidenciaSenadores);
|
||||
}
|
||||
setUsarDatosOficiales(configData.UsarDatosDeBancadasOficiales === 'true');
|
||||
setPresidenciaSenadoId(configData.PresidenciaSenadores || '');
|
||||
setModoOficialActivo(configData.UsarDatosDeBancadasOficiales === 'true');
|
||||
} catch (err) {
|
||||
console.error("Error al cargar datos de configuración:", err);
|
||||
setError("No se pudieron cargar los datos necesarios para la configuración.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
} finally { setLoading(false); }
|
||||
};
|
||||
loadInitialData();
|
||||
}, []);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
await updateConfiguracion({ "PresidenciaSenadores": presidenciaSenadoId, "UsarDatosDeBancadasOficiales": usarDatosOficiales.toString() });
|
||||
alert('Configuración guardada con éxito.');
|
||||
} catch (err) {
|
||||
console.error("Error al guardar la configuración:", err);
|
||||
alert('Error al guardar la configuración.');
|
||||
await updateConfiguracion({
|
||||
"PresidenciaSenadores": presidenciaSenadoId,
|
||||
"UsarDatosDeBancadasOficiales": modoOficialActivo.toString()
|
||||
});
|
||||
await queryClient.invalidateQueries({ queryKey: ['composicionCongreso'] });
|
||||
await queryClient.invalidateQueries({ queryKey: ['bancadasDetalle'] });
|
||||
alert('Configuración guardada.');
|
||||
} catch {
|
||||
alert('Error al guardar.');
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) return <div className="admin-module"><p>Cargando configuración...</p></div>;
|
||||
if (loading) return <div className="admin-module"><p>Cargando...</p></div>;
|
||||
if (error) return <div className="admin-module"><p style={{ color: 'red' }}>{error}</p></div>;
|
||||
|
||||
return (
|
||||
<div className="admin-module">
|
||||
<h3>Configuración General de Cámaras</h3>
|
||||
<h3>Configuración General de Visualización</h3>
|
||||
<div className="form-group">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={usarDatosOficiales}
|
||||
onChange={e => setUsarDatosOficiales(e.target.checked)}
|
||||
checked={modoOficialActivo}
|
||||
onChange={e => setModoOficialActivo(e.target.checked)}
|
||||
/>
|
||||
Activar Modo "Resultados Oficiales"
|
||||
**Activar Modo "Resultados Oficiales"**
|
||||
</label>
|
||||
<p style={{ fontSize: '0.8rem', color: '#666', margin: '0.5rem 0 0 0' }}>
|
||||
Si está activo, el widget del Congreso mostrará la composición gestionada manualmente en esta página. Si está inactivo, mostrará la proyección en tiempo real de las elecciones.
|
||||
<p style={{ fontSize: '0.8rem', color: '#666' }}>
|
||||
Si está activo, el sitio público mostrará la composición de bancas y los ocupantes definidos manualmente en este panel. Si está inactivo, mostrará la proyección en tiempo real de la elección.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ marginTop: '1rem', paddingBottom: '1rem', borderBottom: '1px solid #eee' }}>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// src/components/LoginPage.tsx
|
||||
import { useState } from 'react';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
export const LoginPage = () => {
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const queryClient = useQueryClient();
|
||||
const { login } = useAuth();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
@@ -14,6 +16,9 @@ export const LoginPage = () => {
|
||||
const success = await login({ username, password });
|
||||
if (!success) {
|
||||
setError('Usuario o contraseña incorrectos.');
|
||||
} else {
|
||||
// Si el login es exitoso, invalidamos todo para empezar de cero
|
||||
await queryClient.invalidateQueries();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ export interface ComposicionData {
|
||||
export interface OcupanteBanca {
|
||||
id: number;
|
||||
nombreOcupante: string;
|
||||
fotoUrl: string;
|
||||
periodo: string;
|
||||
fotoUrl: string | null;
|
||||
periodo: string | null;
|
||||
}
|
||||
|
||||
interface PartidoData {
|
||||
@@ -35,7 +35,6 @@ interface PartidoData {
|
||||
nombre: string;
|
||||
nombreCorto: string | null;
|
||||
bancasTotales: number;
|
||||
bancasEnJuego: number;
|
||||
color: string | null;
|
||||
ocupantes: OcupanteBanca[];
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ export const CongresoWidget = () => {
|
||||
const { data: composicionData, isLoading: isLoadingComposicion, error: errorComposicion } = useQuery<ComposicionData>({
|
||||
queryKey: ['composicionCongreso'],
|
||||
queryFn: getComposicionCongreso,
|
||||
// Vuelve a buscar los datos cada 20 segundos
|
||||
refetchInterval: 20000,
|
||||
});
|
||||
|
||||
const { data: bancadasDetalle = [] } = useQuery<BancadaDetalle[]>({
|
||||
@@ -29,28 +31,41 @@ export const CongresoWidget = () => {
|
||||
|
||||
// --- LÓGICA DE SEATFILLDATA ---
|
||||
const seatFillData = useMemo(() => {
|
||||
if (!datosCamaraActual || !bancadasDetalle.length) return [];
|
||||
if (!datosCamaraActual) return [];
|
||||
|
||||
const camaraId = camaraActiva === 'diputados' ? 0 : 1;
|
||||
const bancadasDeCamara = bancadasDetalle.filter(b => b.camara === camaraId);
|
||||
// --- LÓGICA DEL INTERRUPTOR ---
|
||||
// Verificamos si la respuesta de la API contiene datos de ocupantes.
|
||||
// Si bancadasDetalle tiene elementos, significa que el modo "Oficial" está activo en el backend.
|
||||
const modoOficialActivo = bancadasDetalle.length > 0;
|
||||
|
||||
// Creamos un mapa de AgrupacionId -> Color para un acceso rápido
|
||||
const colorMap = new Map<string, string>();
|
||||
datosCamaraActual.partidos.forEach(p => {
|
||||
if (p.id && p.color) {
|
||||
colorMap.set(p.id, p.color);
|
||||
}
|
||||
});
|
||||
if (modoOficialActivo) {
|
||||
// --- MODO OFICIAL: Construir desde las bancas físicas ---
|
||||
const camaraId = camaraActiva === 'diputados' ? 0 : 1;
|
||||
const bancadasDeCamara = bancadasDetalle.filter(b => b.camara === camaraId);
|
||||
|
||||
// 1. Aseguramos que la lista de bancas esté en orden físico (por su ID).
|
||||
const bancadasOrdenadas = bancadasDeCamara.sort((a, b) => a.id - b.id);
|
||||
const colorMap = new Map<string, string>();
|
||||
datosCamaraActual.partidos.forEach(p => {
|
||||
if (p.id && p.color) {
|
||||
colorMap.set(p.id, p.color);
|
||||
}
|
||||
});
|
||||
|
||||
// 2. Mapeamos cada banca física a un objeto SeatFillData.
|
||||
// El índice del array corresponderá al asiento visual.
|
||||
return bancadasOrdenadas.map(bancada => ({
|
||||
color: bancada.agrupacionPoliticaId ? colorMap.get(bancada.agrupacionPoliticaId) || DEFAULT_COLOR : DEFAULT_COLOR,
|
||||
ocupante: bancada.ocupante
|
||||
}));
|
||||
const bancadasOrdenadas = bancadasDeCamara.sort((a, b) => a.id - b.id);
|
||||
|
||||
return bancadasOrdenadas.map(bancada => ({
|
||||
color: bancada.agrupacionPoliticaId ? colorMap.get(bancada.agrupacionPoliticaId) || DEFAULT_COLOR : DEFAULT_COLOR,
|
||||
ocupante: bancada.ocupante
|
||||
}));
|
||||
|
||||
} else {
|
||||
// --- MODO PROYECCIÓN: Construir desde los totales de los partidos ---
|
||||
// Esta es la lógica original que teníamos para el modo proyección.
|
||||
return datosCamaraActual.partidos.flatMap(party => {
|
||||
const seatColor = party.color || DEFAULT_COLOR;
|
||||
// En modo proyección, no hay ocupantes individuales.
|
||||
return Array(party.bancasTotales).fill({ color: seatColor, ocupante: null });
|
||||
});
|
||||
}
|
||||
|
||||
}, [datosCamaraActual, bancadasDetalle, camaraActiva]);
|
||||
|
||||
|
||||
@@ -127,43 +127,44 @@ export const ParliamentLayout: React.FC<ParliamentLayoutProps> = ({
|
||||
|
||||
// Si hay un presidente y su partido tiene bancas, le quitamos una para asignarla.
|
||||
if (presidenteBancada && presidenteBancada.color) {
|
||||
// Encontramos el índice del último asiento que pertenece al partido del presidente.
|
||||
const lastSeatIndex = finalSeatData.map(s => s.color).lastIndexOf(presidenteBancada.color);
|
||||
|
||||
if (lastSeatIndex !== -1) {
|
||||
// Eliminamos ese asiento de la lista de asientos electorales.
|
||||
finalSeatData.splice(lastSeatIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const renderedElements = seatElements.map((child, index) => {
|
||||
// El asiento presidencial sigue siendo un caso especial
|
||||
if (index === PRESIDENTE_SEAT_INDEX) {
|
||||
// --- CASO ESPECIAL: ASIENTO PRESIDENCIAL ---
|
||||
if (index === PRESIDENTE_SEAT_INDEX) {
|
||||
return React.cloneElement(child, {
|
||||
fill: presidenteBancada?.color || '#A9A9A9',
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
// Le damos un tooltip genérico al presidente
|
||||
'data-tooltip-id': 'seat-tooltip',
|
||||
'data-tooltip-html': `<div class="seat-tooltip"><p>Presidencia de la Cámara</p></div>`
|
||||
});
|
||||
}
|
||||
|
||||
// --- LÓGICA NORMAL PARA EL RESTO DE ASIENTOS ---
|
||||
// Usamos la copia modificada 'finalSeatData'. Como este array es más corto,
|
||||
// el último asiento electoral no encontrará datos y quedará gris, lo cual es correcto.
|
||||
const seat = finalSeatData[index];
|
||||
|
||||
if (!seat) {
|
||||
return React.cloneElement(child, { fill: '#E0E0E0', stroke: '#ffffff', strokeWidth: 1.5 });
|
||||
}
|
||||
|
||||
return React.cloneElement(child, {
|
||||
fill: presidenteBancada?.color || '#A9A9A9',
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
fill: seat.color,
|
||||
stroke: '#ffffff',
|
||||
strokeWidth: 1.5,
|
||||
'data-tooltip-id': seat.ocupante ? 'seat-tooltip' : undefined,
|
||||
'data-tooltip-html': seat.ocupante
|
||||
? `<div class="seat-tooltip"><img src="${seat.ocupante.fotoUrl || '/default-avatar.png'}" alt="${seat.ocupante.nombreOcupante}" /><p>${seat.ocupante.nombreOcupante}</p></div>`
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// La lógica ahora es simple: el asiento en el índice X del SVG
|
||||
// corresponde al asiento en el índice X de los datos.
|
||||
const seat = seatData[index];
|
||||
|
||||
if (!seat) {
|
||||
return React.cloneElement(child, { fill: '#E0E0E0', stroke: '#ffffff', strokeWidth: 1.5 });
|
||||
}
|
||||
|
||||
return React.cloneElement(child, {
|
||||
fill: seat.color,
|
||||
stroke: '#ffffff',
|
||||
strokeWidth: 1.5,
|
||||
'data-tooltip-id': seat.ocupante ? 'seat-tooltip' : undefined,
|
||||
'data-tooltip-html': seat.ocupante
|
||||
? `<div class="seat-tooltip"><img src="${seat.ocupante.fotoUrl || '/default-avatar.png'}" alt="${seat.ocupante.nombreOcupante}" /><p>${seat.ocupante.nombreOcupante}</p></div>`
|
||||
: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<svg viewBox="0 0 550 375" width={size} height={size * (375 / 550)} style={{ display: 'block', margin: 'auto' }}>
|
||||
|
||||
@@ -81,28 +81,29 @@ export const SenateLayout: React.FC<SenateLayoutProps> = ({
|
||||
|
||||
// Si hay un presidente y su partido tiene bancas, le quitamos una para asignarla.
|
||||
if (presidenteBancada && presidenteBancada.color) {
|
||||
// Encontramos el índice del último asiento que pertenece al partido del presidente.
|
||||
const lastSeatIndex = finalSeatData.map(s => s.color).lastIndexOf(presidenteBancada.color);
|
||||
|
||||
if (lastSeatIndex !== -1) {
|
||||
// Eliminamos ese asiento de la lista de asientos electorales.
|
||||
finalSeatData.splice(lastSeatIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const renderedElements = seatElements.map((child, index) => {
|
||||
// El asiento presidencial sigue siendo un caso especial
|
||||
// --- CASO ESPECIAL: ASIENTO PRESIDENCIAL ---
|
||||
if (index === PRESIDENTE_SEAT_INDEX) {
|
||||
return React.cloneElement(child, {
|
||||
fill: presidenteBancada?.color || '#A9A9A9',
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
// Le damos un tooltip genérico al presidente
|
||||
'data-tooltip-id': 'seat-tooltip',
|
||||
'data-tooltip-html': `<div class="seat-tooltip"><p>Presidencia de la Cámara</p></div>`
|
||||
});
|
||||
}
|
||||
|
||||
// La lógica ahora es simple: el asiento en el índice X del SVG
|
||||
// corresponde al asiento en el índice X de los datos.
|
||||
const seat = seatData[index];
|
||||
// --- LÓGICA NORMAL PARA EL RESTO DE ASIENTOS ---
|
||||
// Usamos la copia modificada 'finalSeatData'. Como este array es más corto,
|
||||
// el último asiento electoral no encontrará datos y quedará gris, lo cual es correcto.
|
||||
const seat = finalSeatData[index];
|
||||
|
||||
if (!seat) {
|
||||
return React.cloneElement(child, { fill: '#E0E0E0', stroke: '#ffffff', strokeWidth: 1.5 });
|
||||
|
||||
@@ -295,57 +295,33 @@ public class ResultadosController : ControllerBase
|
||||
.AsNoTracking()
|
||||
.ToDictionaryAsync(c => c.Clave, c => c.Valor);
|
||||
|
||||
// Aquí está el interruptor
|
||||
config.TryGetValue("UsarDatosDeBancadasOficiales", out var usarDatosOficialesValue);
|
||||
bool usarDatosOficiales = usarDatosOficialesValue == "true";
|
||||
|
||||
if (usarDatosOficiales)
|
||||
{
|
||||
// Si el interruptor está en 'true', llama a este método
|
||||
return await GetComposicionDesdeBancadasOficiales(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si está en 'false' o no existe, llama a este otro
|
||||
return await GetComposicionDesdeProyecciones(config);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IActionResult> GetComposicionDesdeBancadasOficiales(Dictionary<string, string> config)
|
||||
{
|
||||
config.TryGetValue("MostrarOcupantes", out var mostrarOcupantesValue);
|
||||
bool mostrarOcupantes = mostrarOcupantesValue == "true";
|
||||
|
||||
// Se declara la variable explícitamente como IQueryable<Bancada>
|
||||
IQueryable<Bancada> bancadasQuery = _dbContext.Bancadas.AsNoTracking()
|
||||
.Include(b => b.AgrupacionPolitica);
|
||||
|
||||
if (mostrarOcupantes)
|
||||
{
|
||||
// Ahora sí podemos añadir otro .Include() sin problemas de tipo
|
||||
bancadasQuery = bancadasQuery.Include(b => b.Ocupante);
|
||||
}
|
||||
|
||||
var bancadas = await bancadasQuery.ToListAsync();
|
||||
|
||||
// --- CAMBIO 2: Eliminar la carga manual de Ocupantes ---
|
||||
// Ya no necesitamos 'ocupantesLookup'. Se puede borrar todo este bloque:
|
||||
/*
|
||||
var ocupantesLookup = new Dictionary<int, OcupanteBanca>();
|
||||
if (mostrarOcupantes)
|
||||
{
|
||||
ocupantesLookup = (await _dbContext.OcupantesBancas.AsNoTracking()
|
||||
.ToListAsync())
|
||||
.ToDictionary(o => o.BancadaId);
|
||||
}
|
||||
*/
|
||||
var bancadas = await _dbContext.Bancadas.AsNoTracking()
|
||||
.Include(b => b.AgrupacionPolitica)
|
||||
.Include(b => b.Ocupante)
|
||||
.ToListAsync();
|
||||
|
||||
var bancasPorAgrupacion = bancadas
|
||||
.Where(b => b.AgrupacionPoliticaId != null)
|
||||
.GroupBy(b => new { b.AgrupacionPoliticaId, b.Camara })
|
||||
.Select(g => new
|
||||
{
|
||||
Agrupacion = g.First().AgrupacionPolitica,
|
||||
g.Key.Camara,
|
||||
BancasTotales = g.Count()
|
||||
})
|
||||
.Where(b => b.AgrupacionPolitica != null)
|
||||
.GroupBy(b => b.AgrupacionPolitica)
|
||||
.Select(g => new { Agrupacion = g.Key!, Camara = g.First().Camara, BancasTotales = g.Count() })
|
||||
.ToList();
|
||||
|
||||
var presidenteDiputados = bancasPorAgrupacion
|
||||
@@ -356,25 +332,14 @@ public class ResultadosController : ControllerBase
|
||||
config.TryGetValue("PresidenciaSenadores", out var idPartidoPresidenteSenadores);
|
||||
var presidenteSenadores = await _dbContext.AgrupacionesPoliticas.FindAsync(idPartidoPresidenteSenadores);
|
||||
|
||||
object MapearPartidos(Core.Enums.TipoCamara camara)
|
||||
object MapearPartidosOficial(Core.Enums.TipoCamara camara)
|
||||
{
|
||||
// 1. Filtramos las bancadas que nos interesan (por cámara y que tengan partido).
|
||||
var bancadasDeCamara = bancadas
|
||||
.Where(b => b.Camara == camara && b.AgrupacionPolitica != null);
|
||||
var partidosDeCamara = bancasPorAgrupacion.Where(b => b.Camara == camara);
|
||||
|
||||
// 2. --- ¡EL CAMBIO CLAVE ESTÁ AQUÍ! ---
|
||||
// Agrupamos por el ID de la Agrupación, no por el objeto.
|
||||
// Esto garantiza que todas las bancadas del mismo partido terminen en el MISMO grupo.
|
||||
var partidosDeCamara = bancadasDeCamara
|
||||
.GroupBy(b => b.AgrupacionPolitica!.Id)
|
||||
.Select(g => new
|
||||
{
|
||||
// La Agrupacion la podemos tomar del primer elemento del grupo,
|
||||
// ya que todas las bancadas del grupo pertenecen al mismo partido.
|
||||
Agrupacion = g.First().AgrupacionPolitica!,
|
||||
// g ahora contiene la lista COMPLETA de bancadas para esta agrupación.
|
||||
BancasDelPartido = g.ToList()
|
||||
});
|
||||
|
||||
// 3. Ordenamos, como antes, pero ahora sobre una lista de grupos correcta.
|
||||
var partidosOrdenados = (camara == Core.Enums.TipoCamara.Diputados)
|
||||
@@ -382,28 +347,19 @@ public class ResultadosController : ControllerBase
|
||||
: partidosDeCamara.OrderBy(p => p.Agrupacion.OrdenSenadores ?? 999);
|
||||
|
||||
// 4. Mapeamos al resultado final.
|
||||
return partidosOrdenados
|
||||
.ThenByDescending(p => p.BancasDelPartido.Count)
|
||||
.Select(p =>
|
||||
{
|
||||
// Ahora 'p.BancasDelPartido' contiene TODAS las bancadas del partido (en tu caso, las 2).
|
||||
// Cuando hagamos el .Select() aquí, recorrerá ambas y encontrará a los ocupantes.
|
||||
var ocupantesDelPartido = p.BancasDelPartido
|
||||
.Select(b => b.Ocupante)
|
||||
.Where(o => o != null)
|
||||
.ToList();
|
||||
|
||||
return new
|
||||
{
|
||||
p.Agrupacion.Id,
|
||||
p.Agrupacion.Nombre,
|
||||
p.Agrupacion.NombreCorto,
|
||||
p.Agrupacion.Color,
|
||||
BancasTotales = p.BancasDelPartido.Count,
|
||||
// ¡Esta lista ahora debería contener a tus 2 ocupantes!
|
||||
Ocupantes = mostrarOcupantes ? ocupantesDelPartido : new List<OcupanteBanca?>()
|
||||
};
|
||||
}).ToList();
|
||||
return partidosDeCamara.Select(p => new
|
||||
{
|
||||
p.Agrupacion.Id,
|
||||
p.Agrupacion.Nombre,
|
||||
p.Agrupacion.NombreCorto,
|
||||
p.Agrupacion.Color,
|
||||
p.BancasTotales,
|
||||
// Adjuntamos la lista de ocupantes para este partido
|
||||
Ocupantes = bancadas
|
||||
.Where(b => b.AgrupacionPoliticaId == p.Agrupacion.Id && b.Camara == p.Camara && b.Ocupante != null)
|
||||
.Select(b => b.Ocupante)
|
||||
.ToList()
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
// El resto del método permanece igual...
|
||||
@@ -412,7 +368,7 @@ public class ResultadosController : ControllerBase
|
||||
CamaraNombre = "Cámara de Diputados",
|
||||
TotalBancas = 92,
|
||||
BancasEnJuego = 0,
|
||||
Partidos = MapearPartidos(Core.Enums.TipoCamara.Diputados),
|
||||
Partidos = MapearPartidosOficial(Core.Enums.TipoCamara.Diputados),
|
||||
PresidenteBancada = presidenteDiputados != null ? new { presidenteDiputados.Color } : null
|
||||
};
|
||||
|
||||
@@ -421,7 +377,7 @@ public class ResultadosController : ControllerBase
|
||||
CamaraNombre = "Cámara de Senadores",
|
||||
TotalBancas = 46,
|
||||
BancasEnJuego = 0,
|
||||
Partidos = MapearPartidos(Core.Enums.TipoCamara.Senadores),
|
||||
Partidos = MapearPartidosOficial(Core.Enums.TipoCamara.Senadores),
|
||||
PresidenteBancada = presidenteSenadores != null ? new { presidenteSenadores.Color } : null
|
||||
};
|
||||
|
||||
@@ -466,15 +422,16 @@ public class ResultadosController : ControllerBase
|
||||
.ThenByDescending(b => b.Bancas.BancasTotales);
|
||||
|
||||
return partidosDeCamara
|
||||
.Select(b => new
|
||||
{
|
||||
b.Agrupacion.Id,
|
||||
b.Agrupacion.Nombre,
|
||||
b.Agrupacion.NombreCorto,
|
||||
b.Agrupacion.Color,
|
||||
b.Bancas.BancasTotales
|
||||
})
|
||||
.ToList();
|
||||
.Select(b => new
|
||||
{
|
||||
b.Agrupacion.Id,
|
||||
b.Agrupacion.Nombre,
|
||||
b.Agrupacion.NombreCorto,
|
||||
b.Agrupacion.Color,
|
||||
b.Bancas.BancasTotales,
|
||||
Ocupantes = new List<object>() // <-- Siempre vacío en modo proyección
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
var diputados = new
|
||||
@@ -502,24 +459,20 @@ public class ResultadosController : ControllerBase
|
||||
public async Task<IActionResult> GetBancadasConOcupantes()
|
||||
{
|
||||
var config = await _dbContext.Configuraciones.AsNoTracking().ToDictionaryAsync(c => c.Clave, c => c.Valor);
|
||||
config.TryGetValue("MostrarOcupantes", out var mostrarOcupantesValue);
|
||||
if (mostrarOcupantesValue != "true")
|
||||
|
||||
config.TryGetValue("UsarDatosDeBancadasOficiales", out var usarDatosOficialesValue);
|
||||
if (usarDatosOficialesValue != "true")
|
||||
{
|
||||
// Si la opción está desactivada, devolvemos un array vacío.
|
||||
// Si el modo oficial no está activo, SIEMPRE devolvemos un array vacío.
|
||||
return Ok(new List<object>());
|
||||
}
|
||||
|
||||
// Si el modo oficial SÍ está activo, devolvemos los detalles.
|
||||
var bancadasConOcupantes = await _dbContext.Bancadas
|
||||
.AsNoTracking()
|
||||
.Include(b => b.Ocupante)
|
||||
.Where(b => b.Ocupante != null) // Solo las que tienen un ocupante asignado
|
||||
.Select(b => new
|
||||
{
|
||||
b.Id,
|
||||
b.Camara,
|
||||
b.AgrupacionPoliticaId,
|
||||
Ocupante = b.Ocupante
|
||||
})
|
||||
.Select(b => new { b.Id, b.Camara, b.AgrupacionPoliticaId, Ocupante = b.Ocupante })
|
||||
.OrderBy(b => b.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(bancadasConOcupantes);
|
||||
|
||||
@@ -14,7 +14,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1ed9a49a5373209c105168d721df4c77b6c1f329")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","GeIeP3tog3JZwKJCFe6prPm1MG/MSEFptilJTMpLZdk=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","DfeTw\u002BIdhmMK9IhKuwlSfgckGaIOiGMaYzhCKVkysII="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","XNJwPCDHDCECwfNSMw\u002B6U9bmP9Oc1zMcX0NwP0k5bF8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","T1/vt/jpzUAMkv7\u002BVei1e0uBlnnKJZz40wzx6s2b4L0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","GeIeP3tog3JZwKJCFe6prPm1MG/MSEFptilJTMpLZdk=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","DfeTw\u002BIdhmMK9IhKuwlSfgckGaIOiGMaYzhCKVkysII="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","XNJwPCDHDCECwfNSMw\u002B6U9bmP9Oc1zMcX0NwP0k5bF8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","T1/vt/jpzUAMkv7\u002BVei1e0uBlnnKJZz40wzx6s2b4L0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1ed9a49a5373209c105168d721df4c77b6c1f329")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1ed9a49a5373209c105168d721df4c77b6c1f329")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1ed9a49a5373209c105168d721df4c77b6c1f329")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
Reference in New Issue
Block a user