diff --git a/Elecciones-Web/frontend-admin/src/components/BancasManager.tsx b/Elecciones-Web/frontend-admin/src/components/BancasManager.tsx index 9c2db97..86a85c4 100644 --- a/Elecciones-Web/frontend-admin/src/components/BancasManager.tsx +++ b/Elecciones-Web/frontend-admin/src/components/BancasManager.tsx @@ -4,7 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { getBancadas, getAgrupaciones, updateBancada, type UpdateBancadaData } from '../services/apiService'; import type { Bancada, AgrupacionPolitica } from '../types'; import { OcupantesModal } from './OcupantesModal'; -import './AgrupacionesManager.css'; // Asegúrate de que este CSS tenga los estilos de .chamber-tabs +import './AgrupacionesManager.css'; const camaras = ['diputados', 'senadores'] as const; @@ -14,13 +14,11 @@ export const BancasManager = () => { const [bancadaSeleccionada, setBancadaSeleccionada] = useState(null); const queryClient = useQueryClient(); - // Obtenemos todas las agrupaciones para poblar el { {bancada.ocupante?.nombreOcupante || 'Sin asignar'} -
- +
-
@@ -27,6 +25,7 @@ export const DashboardPage = () => {
+
diff --git a/Elecciones-Web/frontend-admin/src/types/index.ts b/Elecciones-Web/frontend-admin/src/types/index.ts index 0107a48..a875434 100644 --- a/Elecciones-Web/frontend-admin/src/types/index.ts +++ b/Elecciones-Web/frontend-admin/src/types/index.ts @@ -36,6 +36,7 @@ export interface OcupanteBanca { export interface Bancada { id: number; camara: TipoCamaraValue; + numeroBanca: number; agrupacionPoliticaId: string | null; agrupacionPolitica: AgrupacionPolitica | null; ocupante: OcupanteBanca | null; diff --git a/Elecciones-Web/frontend/public/default-avatar.png b/Elecciones-Web/frontend/public/default-avatar.png new file mode 100644 index 0000000..c9da383 Binary files /dev/null and b/Elecciones-Web/frontend/public/default-avatar.png differ diff --git a/Elecciones-Web/frontend/src/apiService.ts b/Elecciones-Web/frontend/src/apiService.ts index a393203..22241b0 100644 --- a/Elecciones-Web/frontend/src/apiService.ts +++ b/Elecciones-Web/frontend/src/apiService.ts @@ -42,6 +42,7 @@ interface PartidoData { 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; } diff --git a/Elecciones-Web/frontend/src/components/CongresoWidget.css b/Elecciones-Web/frontend/src/components/CongresoWidget.css index 96f1c4d..38e49ac 100644 --- a/Elecciones-Web/frontend/src/components/CongresoWidget.css +++ b/Elecciones-Web/frontend/src/components/CongresoWidget.css @@ -201,4 +201,9 @@ font-size: 12px; font-weight: bold; color: #333; +} + +#seat-tooltip.react-tooltip { + opacity: 1 !important; + background-color: white; /* Opcional: asegura un fondo sólido */ } \ No newline at end of file diff --git a/Elecciones-Web/frontend/src/components/CongresoWidget.tsx b/Elecciones-Web/frontend/src/components/CongresoWidget.tsx index 44cdb29..7b39bc7 100644 --- a/Elecciones-Web/frontend/src/components/CongresoWidget.tsx +++ b/Elecciones-Web/frontend/src/components/CongresoWidget.tsx @@ -29,44 +29,44 @@ export const CongresoWidget = () => { const datosCamaraActual = composicionData ? composicionData[camaraActiva] : null; + const esModoOficial = bancadasDetalle.length > 0; + // --- LÓGICA DE SEATFILLDATA --- const seatFillData = useMemo(() => { if (!datosCamaraActual) return []; - // --- 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; - - if (modoOficialActivo) { - // --- MODO OFICIAL: Construir desde las bancas físicas --- + if (esModoOficial) { + // --- MODO OFICIAL --- const camaraId = camaraActiva === 'diputados' ? 0 : 1; const bancadasDeCamara = bancadasDetalle.filter(b => b.camara === camaraId); - const colorMap = new Map(); - datosCamaraActual.partidos.forEach(p => { - if (p.id && p.color) { - colorMap.set(p.id, p.color); + datosCamaraActual.partidos.forEach(p => { if (p.id && p.color) colorMap.set(p.id, p.color); }); + + // 1. Creamos un array del tamaño correcto, lleno de 'null's + const size = camaraActiva === 'diputados' ? 92 : 46; + const finalSeatData = new Array(size).fill(null); + + // 2. Poblamos el array usando NumeroBanca como índice + bancadasDeCamara.forEach(bancada => { + // El índice del SVG es NumeroBanca - 1 + const index = bancada.numeroBanca - 1; + if (index >= 0 && index < size) { + finalSeatData[index] = { + 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 - })); + return finalSeatData; } 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. + // --- 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]); if (isLoadingComposicion) return
Cargando...
; @@ -78,11 +78,23 @@ export const CongresoWidget = () => {
{camaraActiva === 'diputados' ? ( - + ) : ( - + )}
+