Files
Elecciones-2025/Elecciones-Web/frontend-admin/src/components/BancasManager.tsx

121 lines
4.4 KiB
TypeScript
Raw Normal View History

// src/components/BancasManager.tsx
import { useState } from 'react';
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
const camaras = ['diputados', 'senadores'] as const;
export const BancasManager = () => {
const [activeTab, setActiveTab] = useState<'diputados' | 'senadores'>('diputados');
const [modalVisible, setModalVisible] = useState(false);
const [bancadaSeleccionada, setBancadaSeleccionada] = useState<Bancada | null>(null);
const queryClient = useQueryClient();
// Obtenemos todas las agrupaciones para poblar el <select>
const { data: agrupaciones = [] } = useQuery<AgrupacionPolitica[]>({
queryKey: ['agrupaciones'],
queryFn: getAgrupaciones
});
// Obtenemos las bancas para la cámara activa (diputados o senadores)
const { data: bancadas = [], isLoading, error } = useQuery<Bancada[]>({
queryKey: ['bancadas', activeTab],
queryFn: () => getBancadas(activeTab),
});
const handleAgrupacionChange = async (bancadaId: number, nuevaAgrupacionId: string | null) => {
const bancadaActual = bancadas.find(b => b.id === bancadaId);
if (!bancadaActual) return;
// Si se desasigna el partido (vacante), también se limpia el ocupante
const payload: UpdateBancadaData = {
agrupacionPoliticaId: nuevaAgrupacionId,
nombreOcupante: nuevaAgrupacionId ? (bancadaActual.ocupante?.nombreOcupante ?? null) : null,
fotoUrl: nuevaAgrupacionId ? (bancadaActual.ocupante?.fotoUrl ?? null) : null,
periodo: nuevaAgrupacionId ? (bancadaActual.ocupante?.periodo ?? null) : null,
};
try {
await updateBancada(bancadaId, payload);
// Invalida la query para forzar una recarga de datos frescos desde el servidor
queryClient.invalidateQueries({ queryKey: ['bancadas', activeTab] });
} catch (err) {
alert("Error al guardar el cambio.");
}
};
const handleOpenModal = (bancada: Bancada) => {
setBancadaSeleccionada(bancada);
setModalVisible(true);
};
if (error) return <p style={{ color: 'red' }}>Error al cargar las bancas.</p>;
return (
<div className="admin-module">
<h2>Gestión de Ocupación de Bancas</h2>
<p>Asigne a cada banca un partido político y, opcionalmente, los datos de la persona que la ocupa.</p>
<div className="chamber-tabs">
{camaras.map(camara => (
<button
key={camara}
className={activeTab === camara ? 'active' : ''}
onClick={() => setActiveTab(camara)}
>
{camara === 'diputados' ? 'Cámara de Diputados' : 'Cámara de Senadores'}
</button>
))}
</div>
{isLoading ? <p>Cargando bancas...</p> : (
<table>
<thead>
<tr>
<th>Banca #</th>
<th>Partido Asignado</th>
<th>Ocupante Actual</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{bancadas.map((bancada, index) => (
<tr key={bancada.id}>
<td>{`${activeTab.charAt(0).toUpperCase()}-${index + 1}`}</td>
<td>
<select
value={bancada.agrupacionPoliticaId || ''}
onChange={(e) => handleAgrupacionChange(bancada.id, e.target.value || null)}
>
<option value="">-- Vacante --</option>
{agrupaciones.map(a => <option key={a.id} value={a.id}>{a.nombre}</option>)}
</select>
</td>
<td>{bancada.ocupante?.nombreOcupante || 'Sin asignar'}</td>
<td>
<button
disabled={!bancada.agrupacionPoliticaId}
onClick={() => handleOpenModal(bancada)}
>
Editar Ocupante
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
{modalVisible && bancadaSeleccionada && (
<OcupantesModal
bancada={bancadaSeleccionada}
onClose={() => setModalVisible(false)}
activeTab={activeTab}
/>
)}
</div>
);
};