Feat Se añade Id de Agrupaciones en Componentes
This commit is contained in:
@@ -123,7 +123,7 @@ export const AgrupacionesManager = () => {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{agrupaciones.map(agrupacion => (
|
{agrupaciones.map(agrupacion => (
|
||||||
<tr key={agrupacion.id}>
|
<tr key={agrupacion.id}>
|
||||||
<td>{agrupacion.nombre}</td>
|
<td>({agrupacion.id}) {agrupacion.nombre}</td>
|
||||||
<td><input type="text" value={editedAgrupaciones[agrupacion.id]?.nombreCorto ?? ''} onChange={(e) => handleInputChange(agrupacion.id, 'nombreCorto', e.target.value)} /></td>
|
<td><input type="text" value={editedAgrupaciones[agrupacion.id]?.nombreCorto ?? ''} onChange={(e) => handleInputChange(agrupacion.id, 'nombreCorto', e.target.value)} /></td>
|
||||||
<td><input type="color" value={sanitizeColor(editedAgrupaciones[agrupacion.id]?.color)} onChange={(e) => handleInputChange(agrupacion.id, 'color', e.target.value)} /></td>
|
<td><input type="color" value={sanitizeColor(editedAgrupaciones[agrupacion.id]?.color)} onChange={(e) => handleInputChange(agrupacion.id, 'color', e.target.value)} /></td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export const BancasNacionalesManager = () => {
|
|||||||
onChange={(e) => handleAgrupacionChange(bancada.id, e.target.value || null)}
|
onChange={(e) => handleAgrupacionChange(bancada.id, e.target.value || null)}
|
||||||
>
|
>
|
||||||
<option value="">-- Vacante --</option>
|
<option value="">-- Vacante --</option>
|
||||||
{agrupaciones.map(a => <option key={a.id} value={a.id}>{a.nombre}</option>)}
|
{agrupaciones.map(a => <option key={a.id} value={a.id}>{`(${a.id}) ${a.nombre}`}</option>)}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>{bancada.ocupante?.nombreOcupante || 'Sin asignar'}</td>
|
<td>{bancada.ocupante?.nombreOcupante || 'Sin asignar'}</td>
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export const BancasPreviasManager = () => {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{agrupaciones.map(agrupacion => (
|
{agrupaciones.map(agrupacion => (
|
||||||
<tr key={agrupacion.id}>
|
<tr key={agrupacion.id}>
|
||||||
<td>{agrupacion.nombre}</td>
|
<td>({agrupacion.id}) {agrupacion.nombre}</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export const BancasProvincialesManager = () => {
|
|||||||
onChange={(e) => handleAgrupacionChange(bancada.id, e.target.value || null)}
|
onChange={(e) => handleAgrupacionChange(bancada.id, e.target.value || null)}
|
||||||
>
|
>
|
||||||
<option value="">-- Vacante --</option>
|
<option value="">-- Vacante --</option>
|
||||||
{agrupaciones.map(a => <option key={a.id} value={a.id}>{a.nombre}</option>)}
|
{agrupaciones.map(a => <option key={a.id} value={a.id}>{`(${a.id}) ${a.nombre}`}</option>)}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>{bancada.ocupante?.nombreOcupante || 'Sin asignar'}</td>
|
<td>{bancada.ocupante?.nombreOcupante || 'Sin asignar'}</td>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { getProvinciasForAdmin, getMunicipiosForAdmin, getAgrupaciones, getCandi
|
|||||||
import type { MunicipioSimple, AgrupacionPolitica, CandidatoOverride, ProvinciaSimple } from '../types';
|
import type { MunicipioSimple, AgrupacionPolitica, CandidatoOverride, ProvinciaSimple } from '../types';
|
||||||
import { CATEGORIAS_NACIONALES_OPTIONS, CATEGORIAS_PROVINCIALES_OPTIONS } from '../constants/categorias';
|
import { CATEGORIAS_NACIONALES_OPTIONS, CATEGORIAS_PROVINCIALES_OPTIONS } from '../constants/categorias';
|
||||||
|
|
||||||
const ELECCION_OPTIONS = [
|
const ELECCION_OPTIONS = [
|
||||||
{ value: 2, label: 'Elecciones Nacionales' },
|
{ value: 2, label: 'Elecciones Nacionales' },
|
||||||
{ value: 1, label: 'Elecciones Provinciales' }
|
{ value: 1, label: 'Elecciones Provinciales' }
|
||||||
];
|
];
|
||||||
@@ -83,7 +83,14 @@ export const CandidatoOverridesManager = () => {
|
|||||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', alignItems: 'flex-end' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', alignItems: 'flex-end' }}>
|
||||||
<Select options={ELECCION_OPTIONS} value={selectedEleccion} onChange={(opt) => { setSelectedEleccion(opt!); setSelectedCategoria(null); }} />
|
<Select options={ELECCION_OPTIONS} value={selectedEleccion} onChange={(opt) => { setSelectedEleccion(opt!); setSelectedCategoria(null); }} />
|
||||||
<Select options={categoriaOptions} value={selectedCategoria} onChange={setSelectedCategoria} placeholder="Seleccione Categoría..." isDisabled={!selectedEleccion} />
|
<Select options={categoriaOptions} value={selectedCategoria} onChange={setSelectedCategoria} placeholder="Seleccione Categoría..." isDisabled={!selectedEleccion} />
|
||||||
<Select options={agrupaciones.map(a => ({ value: a.id, label: a.nombre, ...a }))} getOptionValue={opt => opt.id} getOptionLabel={opt => opt.nombre} value={selectedAgrupacion} onChange={setSelectedAgrupacion} placeholder="Seleccione Agrupación..." />
|
<Select
|
||||||
|
options={agrupaciones.map(a => ({ value: a.id, label: a.nombre, ...a }))}
|
||||||
|
getOptionValue={opt => opt.id}
|
||||||
|
getOptionLabel={opt => `(${opt.id}) ${opt.nombre}`}
|
||||||
|
value={selectedAgrupacion}
|
||||||
|
onChange={setSelectedAgrupacion}
|
||||||
|
placeholder="Seleccione Agrupación..."
|
||||||
|
/>
|
||||||
<Select options={AMBITO_LEVEL_OPTIONS} value={selectedAmbitoLevel} onChange={(opt) => { setSelectedAmbitoLevel(opt!); setSelectedProvincia(null); setSelectedMunicipio(null); }} />
|
<Select options={AMBITO_LEVEL_OPTIONS} value={selectedAmbitoLevel} onChange={(opt) => { setSelectedAmbitoLevel(opt!); setSelectedProvincia(null); setSelectedMunicipio(null); }} />
|
||||||
|
|
||||||
{selectedAmbitoLevel.value === 'provincia' || selectedAmbitoLevel.value === 'municipio' ? (
|
{selectedAmbitoLevel.value === 'provincia' || selectedAmbitoLevel.value === 'municipio' ? (
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const ConfiguracionNacional = () => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
const [presidenciaDiputadosId, setPresidenciaDiputadosId] = useState<string>('');
|
const [presidenciaDiputadosId, setPresidenciaDiputadosId] = useState<string>('');
|
||||||
const [presidenciaSenadoId, setPresidenciaSenadoId] = useState<string>('');
|
const [presidenciaSenadoId, setPresidenciaSenadoId] = useState<string>('');
|
||||||
const [modoOficialActivo, setModoOficialActivo] = useState(false);
|
const [modoOficialActivo, setModoOficialActivo] = useState(false);
|
||||||
@@ -30,7 +30,7 @@ export const ConfiguracionNacional = () => {
|
|||||||
setModoOficialActivo(configData.UsarDatosOficialesNacionales === 'true');
|
setModoOficialActivo(configData.UsarDatosOficialesNacionales === 'true');
|
||||||
setDiputadosTipoBanca(configData.PresidenciaDiputadosNacional_TipoBanca === 'previa' ? 'previa' : 'ganada');
|
setDiputadosTipoBanca(configData.PresidenciaDiputadosNacional_TipoBanca === 'previa' ? 'previa' : 'ganada');
|
||||||
setSenadoTipoBanca(configData.PresidenciaSenadoNacional_TipoBanca === 'previa' ? 'previa' : 'ganada');
|
setSenadoTipoBanca(configData.PresidenciaSenadoNacional_TipoBanca === 'previa' ? 'previa' : 'ganada');
|
||||||
} catch (err) { console.error("Error al cargar datos de configuración nacional:", err); }
|
} catch (err) { console.error("Error al cargar datos de configuración nacional:", err); }
|
||||||
finally { setLoading(false); }
|
finally { setLoading(false); }
|
||||||
};
|
};
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
@@ -56,16 +56,7 @@ export const ConfiguracionNacional = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="admin-module">
|
<div className="admin-module">
|
||||||
<h3>Configuración de Widgets Nacionales</h3>
|
<h3>Configuración de Widgets Nacionales</h3>
|
||||||
{/*<div className="form-group">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" checked={modoOficialActivo} onChange={e => setModoOficialActivo(e.target.checked)} />
|
|
||||||
**Activar Modo "Resultados Oficiales" para Widgets Nacionales**
|
|
||||||
</label>
|
|
||||||
<p style={{ fontSize: '0.8rem', color: '#666' }}>
|
|
||||||
Si está activo, los widgets nacionales usarán la composición manual de bancas. Si no, usarán la proyección en tiempo real.
|
|
||||||
</p>
|
|
||||||
</div>*/}
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', gap: '2rem', marginTop: '1rem' }}>
|
<div style={{ display: 'flex', gap: '2rem', marginTop: '1rem' }}>
|
||||||
{/* Columna Diputados */}
|
{/* Columna Diputados */}
|
||||||
<div style={{ flex: 1, borderRight: '1px solid #ccc', paddingRight: '1rem' }}>
|
<div style={{ flex: 1, borderRight: '1px solid #ccc', paddingRight: '1rem' }}>
|
||||||
@@ -77,14 +68,14 @@ export const ConfiguracionNacional = () => {
|
|||||||
</p>
|
</p>
|
||||||
<select id="presidencia-diputados-nacional" value={presidenciaDiputadosId} onChange={e => setPresidenciaDiputadosId(e.target.value)} style={{ width: '100%', padding: '8px', marginBottom: '0.5rem' }}>
|
<select id="presidencia-diputados-nacional" value={presidenciaDiputadosId} onChange={e => setPresidenciaDiputadosId(e.target.value)} style={{ width: '100%', padding: '8px', marginBottom: '0.5rem' }}>
|
||||||
<option value="">-- No Asignado --</option>
|
<option value="">-- No Asignado --</option>
|
||||||
{agrupaciones.map(a => (<option key={a.id} value={a.id}>{a.nombre}</option>))}
|
{agrupaciones.map(a => (<option key={a.id} value={a.id}>{`(${a.id}) ${a.nombre}`}</option>))}
|
||||||
</select>
|
</select>
|
||||||
{presidenciaDiputadosId && (
|
{presidenciaDiputadosId && (
|
||||||
<div>
|
<div>
|
||||||
<label><input type="radio" value="ganada" checked={diputadosTipoBanca === 'ganada'} onChange={() => setDiputadosTipoBanca('ganada')} /> Descontar de Banca Ganada</label>
|
<label><input type="radio" value="ganada" checked={diputadosTipoBanca === 'ganada'} onChange={() => setDiputadosTipoBanca('ganada')} /> Descontar de Banca Ganada</label>
|
||||||
<label style={{marginLeft: '1rem'}}><input type="radio" value="previa" checked={diputadosTipoBanca === 'previa'} onChange={() => setDiputadosTipoBanca('previa')} /> Descontar de Banca Previa</label>
|
<label style={{ marginLeft: '1rem' }}><input type="radio" value="previa" checked={diputadosTipoBanca === 'previa'} onChange={() => setDiputadosTipoBanca('previa')} /> Descontar de Banca Previa</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Columna Senadores */}
|
{/* Columna Senadores */}
|
||||||
@@ -97,11 +88,11 @@ export const ConfiguracionNacional = () => {
|
|||||||
</p>
|
</p>
|
||||||
<select id="presidencia-senado-nacional" value={presidenciaSenadoId} onChange={e => setPresidenciaSenadoId(e.target.value)} style={{ width: '100%', padding: '8px' }}>
|
<select id="presidencia-senado-nacional" value={presidenciaSenadoId} onChange={e => setPresidenciaSenadoId(e.target.value)} style={{ width: '100%', padding: '8px' }}>
|
||||||
<option value="">-- No Asignado --</option>
|
<option value="">-- No Asignado --</option>
|
||||||
{agrupaciones.map(a => (<option key={a.id} value={a.id}>{a.nombre}</option>))}
|
{agrupaciones.map(a => (<option key={a.id} value={a.id}>{`(${a.id}) ${a.nombre}`}</option>))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button onClick={handleSave} style={{ marginTop: '1.5rem' }}>
|
<button onClick={handleSave} style={{ marginTop: '1.5rem' }}>
|
||||||
Guardar Configuración
|
Guardar Configuración
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { MunicipioSimple, AgrupacionPolitica, LogoAgrupacionCategoria, Prov
|
|||||||
import { CATEGORIAS_NACIONALES_OPTIONS, CATEGORIAS_PROVINCIALES_OPTIONS } from '../constants/categorias';
|
import { CATEGORIAS_NACIONALES_OPTIONS, CATEGORIAS_PROVINCIALES_OPTIONS } from '../constants/categorias';
|
||||||
|
|
||||||
const ELECCION_OPTIONS = [
|
const ELECCION_OPTIONS = [
|
||||||
{ value: 0, label: 'General (Toda la elección)' },
|
{ value: 0, label: 'General (Todas las elecciones)' },
|
||||||
{ value: 2, label: 'Elecciones Nacionales' },
|
{ value: 2, label: 'Elecciones Nacionales' },
|
||||||
{ value: 1, label: 'Elecciones Provinciales' }
|
{ value: 1, label: 'Elecciones Provinciales' }
|
||||||
];
|
];
|
||||||
@@ -84,7 +84,14 @@ export const LogoOverridesManager = () => {
|
|||||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', alignItems: 'flex-end' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', alignItems: 'flex-end' }}>
|
||||||
<Select options={ELECCION_OPTIONS} value={selectedEleccion} onChange={(opt) => { setSelectedEleccion(opt!); setSelectedCategoria(null); }} />
|
<Select options={ELECCION_OPTIONS} value={selectedEleccion} onChange={(opt) => { setSelectedEleccion(opt!); setSelectedCategoria(null); }} />
|
||||||
<Select options={categoriaOptions} value={selectedCategoria} onChange={setSelectedCategoria} placeholder="Seleccione Categoría..." isDisabled={!selectedEleccion} />
|
<Select options={categoriaOptions} value={selectedCategoria} onChange={setSelectedCategoria} placeholder="Seleccione Categoría..." isDisabled={!selectedEleccion} />
|
||||||
<Select options={agrupaciones.map(a => ({ value: a.id, label: a.nombre, ...a }))} getOptionValue={opt => opt.id} getOptionLabel={opt => opt.nombre} value={selectedAgrupacion} onChange={setSelectedAgrupacion} placeholder="Seleccione Agrupación..." />
|
<Select
|
||||||
|
options={agrupaciones.map(a => ({ value: a.id, label: a.nombre, ...a }))}
|
||||||
|
getOptionValue={opt => opt.id}
|
||||||
|
getOptionLabel={opt => `(${opt.id}) ${opt.nombre}`}
|
||||||
|
value={selectedAgrupacion}
|
||||||
|
onChange={setSelectedAgrupacion}
|
||||||
|
placeholder="Seleccione Agrupación..."
|
||||||
|
/>
|
||||||
<Select options={AMBITO_LEVEL_OPTIONS} value={selectedAmbitoLevel} onChange={(opt) => { setSelectedAmbitoLevel(opt!); setSelectedProvincia(null); setSelectedMunicipio(null); }} />
|
<Select options={AMBITO_LEVEL_OPTIONS} value={selectedAmbitoLevel} onChange={(opt) => { setSelectedAmbitoLevel(opt!); setSelectedProvincia(null); setSelectedMunicipio(null); }} />
|
||||||
|
|
||||||
{selectedAmbitoLevel.value === 'provincia' || selectedAmbitoLevel.value === 'municipio' ? (
|
{selectedAmbitoLevel.value === 'provincia' || selectedAmbitoLevel.value === 'municipio' ? (
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ import './AgrupacionesManager.css'; // Reutilizamos los estilos
|
|||||||
const updateOrdenDiputadosApi = async (ids: string[]) => {
|
const updateOrdenDiputadosApi = async (ids: string[]) => {
|
||||||
const token = localStorage.getItem('admin-jwt-token');
|
const token = localStorage.getItem('admin-jwt-token');
|
||||||
const response = await fetch('http://localhost:5217/api/admin/agrupaciones/orden-diputados', {
|
const response = await fetch('http://localhost:5217/api/admin/agrupaciones/orden-diputados', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify(ids)
|
body: JSON.stringify(ids)
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Failed to save Diputados order");
|
throw new Error("Failed to save Diputados order");
|
||||||
@@ -38,77 +38,77 @@ const updateOrdenDiputadosApi = async (ids: string[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const OrdenDiputadosManager = () => {
|
export const OrdenDiputadosManager = () => {
|
||||||
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(PointerSensor),
|
useSensor(PointerSensor),
|
||||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchAndSortAgrupaciones = async () => {
|
const fetchAndSortAgrupaciones = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const data = await getAgrupaciones();
|
const data = await getAgrupaciones();
|
||||||
// Ordenar por el orden de Diputados. Los nulos van al final.
|
// Ordenar por el orden de Diputados. Los nulos van al final.
|
||||||
data.sort((a, b) => (a.ordenDiputados || 999) - (b.ordenDiputados || 999));
|
data.sort((a, b) => (a.ordenDiputados || 999) - (b.ordenDiputados || 999));
|
||||||
setAgrupaciones(data);
|
setAgrupaciones(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch agrupaciones for Diputados:", error);
|
console.error("Failed to fetch agrupaciones for Diputados:", error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
|
||||||
};
|
|
||||||
fetchAndSortAgrupaciones();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDragEnd = (event: DragEndEvent) => {
|
|
||||||
const { active, over } = event;
|
|
||||||
if (over && active.id !== over.id) {
|
|
||||||
setAgrupaciones((items) => {
|
|
||||||
const oldIndex = items.findIndex((item) => item.id === active.id);
|
|
||||||
const newIndex = items.findIndex((item) => item.id === over.id);
|
|
||||||
return arrayMove(items, oldIndex, newIndex);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
fetchAndSortAgrupaciones();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSaveOrder = async () => {
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
const idsOrdenados = agrupaciones.map(a => a.id);
|
const { active, over } = event;
|
||||||
try {
|
if (over && active.id !== over.id) {
|
||||||
await updateOrdenDiputadosApi(idsOrdenados);
|
setAgrupaciones((items) => {
|
||||||
alert('Orden de Diputados guardado con éxito!');
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
} catch (error) {
|
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||||
alert('Error al guardar el orden de Diputados.');
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
}
|
});
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (loading) return <p>Cargando orden de Diputados...</p>;
|
const handleSaveOrder = async () => {
|
||||||
|
const idsOrdenados = agrupaciones.map(a => a.id);
|
||||||
|
try {
|
||||||
|
await updateOrdenDiputadosApi(idsOrdenados);
|
||||||
|
alert('Orden de Diputados guardado con éxito!');
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error al guardar el orden de Diputados.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
if (loading) return <p>Cargando orden de Diputados...</p>;
|
||||||
<div className="admin-module">
|
|
||||||
<h3>Ordenar Agrupaciones (Diputados)</h3>
|
return (
|
||||||
<p>Arrastre para reordenar.</p>
|
<div className="admin-module">
|
||||||
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
<h3>Ordenar Agrupaciones (Diputados)</h3>
|
||||||
<DndContext
|
<p>Arrastre para reordenar.</p>
|
||||||
sensors={sensors}
|
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
||||||
collisionDetection={closestCenter}
|
<DndContext
|
||||||
onDragEnd={handleDragEnd}
|
sensors={sensors}
|
||||||
>
|
collisionDetection={closestCenter}
|
||||||
<SortableContext
|
onDragEnd={handleDragEnd}
|
||||||
items={agrupaciones.map(a => a.id)}
|
>
|
||||||
strategy={horizontalListSortingStrategy}
|
<SortableContext
|
||||||
>
|
items={agrupaciones.map(a => a.id)}
|
||||||
<ul className="sortable-list-horizontal">
|
strategy={horizontalListSortingStrategy}
|
||||||
{agrupaciones.map(agrupacion => (
|
>
|
||||||
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
<ul className="sortable-list-horizontal">
|
||||||
{agrupacion.nombreCorto || agrupacion.nombre}
|
{agrupaciones.map(agrupacion => (
|
||||||
</SortableItem>
|
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
||||||
))}
|
{`(${agrupacion.id}) ${agrupacion.nombreCorto || agrupacion.nombre}`}
|
||||||
</ul>
|
</SortableItem>
|
||||||
</SortableContext>
|
))}
|
||||||
</DndContext>
|
</ul>
|
||||||
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden Diputados</button>
|
</SortableContext>
|
||||||
</div>
|
</DndContext>
|
||||||
);
|
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden Diputados</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
@@ -11,92 +11,92 @@ import './AgrupacionesManager.css';
|
|||||||
const ELECCION_ID_NACIONAL = 2;
|
const ELECCION_ID_NACIONAL = 2;
|
||||||
|
|
||||||
export const OrdenDiputadosNacionalesManager = () => {
|
export const OrdenDiputadosNacionalesManager = () => {
|
||||||
// Estado para la lista que el usuario puede ordenar
|
// Estado para la lista que el usuario puede ordenar
|
||||||
const [agrupacionesOrdenadas, setAgrupacionesOrdenadas] = useState<AgrupacionPolitica[]>([]);
|
const [agrupacionesOrdenadas, setAgrupacionesOrdenadas] = useState<AgrupacionPolitica[]>([]);
|
||||||
|
|
||||||
// Query 1: Obtener TODAS las agrupaciones para tener sus datos completos (nombre, etc.)
|
|
||||||
const { data: todasAgrupaciones = [], isLoading: isLoadingAgrupaciones } = useQuery<AgrupacionPolitica[]>({
|
|
||||||
queryKey: ['agrupaciones'],
|
|
||||||
queryFn: getAgrupaciones,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Query 2: Obtener los datos de composición para saber qué partidos tienen bancas
|
|
||||||
const { data: composicionData, isLoading: isLoadingComposicion } = useQuery({
|
|
||||||
queryKey: ['composicionNacional', ELECCION_ID_NACIONAL],
|
|
||||||
queryFn: () => getComposicionNacional(ELECCION_ID_NACIONAL),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Este efecto se ejecuta cuando los datos de las queries estén disponibles
|
// Query 1: Obtener TODAS las agrupaciones para tener sus datos completos (nombre, etc.)
|
||||||
useEffect(() => {
|
const { data: todasAgrupaciones = [], isLoading: isLoadingAgrupaciones } = useQuery<AgrupacionPolitica[]>({
|
||||||
// No hacemos nada hasta que ambas queries hayan cargado sus datos
|
queryKey: ['agrupaciones'],
|
||||||
if (!composicionData || !todasAgrupaciones || todasAgrupaciones.length === 0) {
|
queryFn: getAgrupaciones,
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Creamos un Set con los IDs de los partidos que tienen al menos una banca de diputado
|
// Query 2: Obtener los datos de composición para saber qué partidos tienen bancas
|
||||||
const partidosConBancasIds = new Set(
|
const { data: composicionData, isLoading: isLoadingComposicion } = useQuery({
|
||||||
composicionData.diputados.partidos
|
queryKey: ['composicionNacional', ELECCION_ID_NACIONAL],
|
||||||
.filter(p => p.bancasTotales > 0)
|
queryFn: () => getComposicionNacional(ELECCION_ID_NACIONAL),
|
||||||
.map(p => p.id)
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// Filtramos la lista completa de agrupaciones, quedándonos solo con las relevantes
|
// Este efecto se ejecuta cuando los datos de las queries estén disponibles
|
||||||
const agrupacionesFiltradas = todasAgrupaciones.filter(a => partidosConBancasIds.has(a.id));
|
useEffect(() => {
|
||||||
|
// No hacemos nada hasta que ambas queries hayan cargado sus datos
|
||||||
|
if (!composicionData || !todasAgrupaciones || todasAgrupaciones.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Ordenamos la lista filtrada según el orden guardado en la BD
|
// Creamos un Set con los IDs de los partidos que tienen al menos una banca de diputado
|
||||||
agrupacionesFiltradas.sort((a, b) => (a.ordenDiputadosNacionales || 999) - (b.ordenDiputadosNacionales || 999));
|
const partidosConBancasIds = new Set(
|
||||||
|
composicionData.diputados.partidos
|
||||||
// Actualizamos el estado que se renderiza y que el usuario puede ordenar
|
.filter(p => p.bancasTotales > 0)
|
||||||
setAgrupacionesOrdenadas(agrupacionesFiltradas);
|
.map(p => p.id)
|
||||||
|
|
||||||
}, [todasAgrupaciones, composicionData]); // Dependencias: se re-ejecuta si los datos cambian
|
|
||||||
|
|
||||||
const sensors = useSensors(
|
|
||||||
useSensor(PointerSensor),
|
|
||||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragEnd = (event: DragEndEvent) => {
|
// Filtramos la lista completa de agrupaciones, quedándonos solo con las relevantes
|
||||||
const { active, over } = event;
|
const agrupacionesFiltradas = todasAgrupaciones.filter(a => partidosConBancasIds.has(a.id));
|
||||||
if (over && active.id !== over.id) {
|
|
||||||
setAgrupacionesOrdenadas((items) => {
|
|
||||||
const oldIndex = items.findIndex((item) => item.id === active.id);
|
|
||||||
const newIndex = items.findIndex((item) => item.id === over.id);
|
|
||||||
return arrayMove(items, oldIndex, newIndex);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveOrder = async () => {
|
// Ordenamos la lista filtrada según el orden guardado en la BD
|
||||||
const idsOrdenados = agrupacionesOrdenadas.map(a => a.id);
|
agrupacionesFiltradas.sort((a, b) => (a.ordenDiputadosNacionales || 999) - (b.ordenDiputadosNacionales || 999));
|
||||||
try {
|
|
||||||
await updateOrden('diputados-nacionales', idsOrdenados);
|
|
||||||
alert('Orden de Diputados Nacionales guardado con éxito!');
|
|
||||||
} catch (error) {
|
|
||||||
alert('Error al guardar el orden de Diputados Nacionales.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isLoading = isLoadingAgrupaciones || isLoadingComposicion;
|
// Actualizamos el estado que se renderiza y que el usuario puede ordenar
|
||||||
if (isLoading) return <p>Cargando orden de Diputados Nacionales...</p>;
|
setAgrupacionesOrdenadas(agrupacionesFiltradas);
|
||||||
|
|
||||||
return (
|
}, [todasAgrupaciones, composicionData]); // Dependencias: se re-ejecuta si los datos cambian
|
||||||
<div className="admin-module">
|
|
||||||
<h3>Ordenar Agrupaciones (Diputados Nacionales)</h3>
|
const sensors = useSensors(
|
||||||
<p>Arrastre para reordenar. Solo se muestran los partidos con bancas.</p>
|
useSensor(PointerSensor),
|
||||||
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||||
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
);
|
||||||
<SortableContext items={agrupacionesOrdenadas.map(a => a.id)} strategy={horizontalListSortingStrategy}>
|
|
||||||
<ul className="sortable-list-horizontal">
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
{agrupacionesOrdenadas.map(agrupacion => (
|
const { active, over } = event;
|
||||||
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
if (over && active.id !== over.id) {
|
||||||
{agrupacion.nombreCorto || agrupacion.nombre}
|
setAgrupacionesOrdenadas((items) => {
|
||||||
</SortableItem>
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
))}
|
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||||
</ul>
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
</SortableContext>
|
});
|
||||||
</DndContext>
|
}
|
||||||
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden</button>
|
};
|
||||||
</div>
|
|
||||||
);
|
const handleSaveOrder = async () => {
|
||||||
|
const idsOrdenados = agrupacionesOrdenadas.map(a => a.id);
|
||||||
|
try {
|
||||||
|
await updateOrden('diputados-nacionales', idsOrdenados);
|
||||||
|
alert('Orden de Diputados Nacionales guardado con éxito!');
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error al guardar el orden de Diputados Nacionales.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isLoading = isLoadingAgrupaciones || isLoadingComposicion;
|
||||||
|
if (isLoading) return <p>Cargando orden de Diputados Nacionales...</p>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h3>Ordenar Agrupaciones (Diputados Nacionales)</h3>
|
||||||
|
<p>Arrastre para reordenar. Solo se muestran los partidos con bancas.</p>
|
||||||
|
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
||||||
|
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
||||||
|
<SortableContext items={agrupacionesOrdenadas.map(a => a.id)} strategy={horizontalListSortingStrategy}>
|
||||||
|
<ul className="sortable-list-horizontal">
|
||||||
|
{agrupacionesOrdenadas.map(agrupacion => (
|
||||||
|
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
||||||
|
{`(${agrupacion.id}) ${agrupacion.nombreCorto || agrupacion.nombre}`}
|
||||||
|
</SortableItem>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
@@ -25,12 +25,12 @@ import './AgrupacionesManager.css'; // Reutilizamos los estilos
|
|||||||
const updateOrdenSenadoresApi = async (ids: string[]) => {
|
const updateOrdenSenadoresApi = async (ids: string[]) => {
|
||||||
const token = localStorage.getItem('admin-jwt-token');
|
const token = localStorage.getItem('admin-jwt-token');
|
||||||
const response = await fetch('http://localhost:5217/api/admin/agrupaciones/orden-senadores', {
|
const response = await fetch('http://localhost:5217/api/admin/agrupaciones/orden-senadores', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify(ids)
|
body: JSON.stringify(ids)
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Failed to save Senadores order");
|
throw new Error("Failed to save Senadores order");
|
||||||
@@ -38,77 +38,77 @@ const updateOrdenSenadoresApi = async (ids: string[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const OrdenSenadoresManager = () => {
|
export const OrdenSenadoresManager = () => {
|
||||||
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(PointerSensor),
|
useSensor(PointerSensor),
|
||||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchAndSortAgrupaciones = async () => {
|
const fetchAndSortAgrupaciones = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const data = await getAgrupaciones();
|
const data = await getAgrupaciones();
|
||||||
// Ordenar por el orden de Senadores. Los nulos van al final.
|
// Ordenar por el orden de Senadores. Los nulos van al final.
|
||||||
data.sort((a, b) => (a.ordenSenadores || 999) - (b.ordenSenadores || 999));
|
data.sort((a, b) => (a.ordenSenadores || 999) - (b.ordenSenadores || 999));
|
||||||
setAgrupaciones(data);
|
setAgrupaciones(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch agrupaciones for Senadores:", error);
|
console.error("Failed to fetch agrupaciones for Senadores:", error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
|
||||||
};
|
|
||||||
fetchAndSortAgrupaciones();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDragEnd = (event: DragEndEvent) => {
|
|
||||||
const { active, over } = event;
|
|
||||||
if (over && active.id !== over.id) {
|
|
||||||
setAgrupaciones((items) => {
|
|
||||||
const oldIndex = items.findIndex((item) => item.id === active.id);
|
|
||||||
const newIndex = items.findIndex((item) => item.id === over.id);
|
|
||||||
return arrayMove(items, oldIndex, newIndex);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
fetchAndSortAgrupaciones();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSaveOrder = async () => {
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
const idsOrdenados = agrupaciones.map(a => a.id);
|
const { active, over } = event;
|
||||||
try {
|
if (over && active.id !== over.id) {
|
||||||
await updateOrdenSenadoresApi(idsOrdenados);
|
setAgrupaciones((items) => {
|
||||||
alert('Orden de Senadores guardado con éxito!');
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
} catch (error) {
|
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||||
alert('Error al guardar el orden de Senadores.');
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
}
|
});
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (loading) return <p>Cargando orden de Senadores...</p>;
|
const handleSaveOrder = async () => {
|
||||||
|
const idsOrdenados = agrupaciones.map(a => a.id);
|
||||||
|
try {
|
||||||
|
await updateOrdenSenadoresApi(idsOrdenados);
|
||||||
|
alert('Orden de Senadores guardado con éxito!');
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error al guardar el orden de Senadores.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
if (loading) return <p>Cargando orden de Senadores...</p>;
|
||||||
<div className="admin-module">
|
|
||||||
<h3>Ordenar Agrupaciones (Senado)</h3>
|
return (
|
||||||
<p>Arrastre para reordenar.</p>
|
<div className="admin-module">
|
||||||
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
<h3>Ordenar Agrupaciones (Senado)</h3>
|
||||||
<DndContext
|
<p>Arrastre para reordenar.</p>
|
||||||
sensors={sensors}
|
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
||||||
collisionDetection={closestCenter}
|
<DndContext
|
||||||
onDragEnd={handleDragEnd}
|
sensors={sensors}
|
||||||
>
|
collisionDetection={closestCenter}
|
||||||
<SortableContext
|
onDragEnd={handleDragEnd}
|
||||||
items={agrupaciones.map(a => a.id)}
|
>
|
||||||
strategy={horizontalListSortingStrategy}
|
<SortableContext
|
||||||
>
|
items={agrupaciones.map(a => a.id)}
|
||||||
<ul className="sortable-list-horizontal">
|
strategy={horizontalListSortingStrategy}
|
||||||
{agrupaciones.map(agrupacion => (
|
>
|
||||||
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
<ul className="sortable-list-horizontal">
|
||||||
{agrupacion.nombreCorto || agrupacion.nombre}
|
{agrupaciones.map(agrupacion => (
|
||||||
</SortableItem>
|
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
||||||
))}
|
{`(${agrupacion.id}) ${agrupacion.nombreCorto || agrupacion.nombre}`}
|
||||||
</ul>
|
</SortableItem>
|
||||||
</SortableContext>
|
))}
|
||||||
</DndContext>
|
</ul>
|
||||||
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden Senado</button>
|
</SortableContext>
|
||||||
</div>
|
</DndContext>
|
||||||
);
|
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden Senado</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
@@ -11,84 +11,84 @@ import './AgrupacionesManager.css';
|
|||||||
const ELECCION_ID_NACIONAL = 2;
|
const ELECCION_ID_NACIONAL = 2;
|
||||||
|
|
||||||
export const OrdenSenadoresNacionalesManager = () => {
|
export const OrdenSenadoresNacionalesManager = () => {
|
||||||
const [agrupacionesOrdenadas, setAgrupacionesOrdenadas] = useState<AgrupacionPolitica[]>([]);
|
const [agrupacionesOrdenadas, setAgrupacionesOrdenadas] = useState<AgrupacionPolitica[]>([]);
|
||||||
|
|
||||||
const { data: todasAgrupaciones = [], isLoading: isLoadingAgrupaciones } = useQuery<AgrupacionPolitica[]>({
|
|
||||||
queryKey: ['agrupaciones'],
|
|
||||||
queryFn: getAgrupaciones,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: composicionData, isLoading: isLoadingComposicion } = useQuery({
|
|
||||||
queryKey: ['composicionNacional', ELECCION_ID_NACIONAL],
|
|
||||||
queryFn: () => getComposicionNacional(ELECCION_ID_NACIONAL),
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: todasAgrupaciones = [], isLoading: isLoadingAgrupaciones } = useQuery<AgrupacionPolitica[]>({
|
||||||
if (!composicionData || !todasAgrupaciones || todasAgrupaciones.length === 0) {
|
queryKey: ['agrupaciones'],
|
||||||
return;
|
queryFn: getAgrupaciones,
|
||||||
}
|
});
|
||||||
|
|
||||||
// Creamos un Set con los IDs de los partidos que tienen al menos una banca de senador
|
const { data: composicionData, isLoading: isLoadingComposicion } = useQuery({
|
||||||
const partidosConBancasIds = new Set(
|
queryKey: ['composicionNacional', ELECCION_ID_NACIONAL],
|
||||||
composicionData.senadores.partidos
|
queryFn: () => getComposicionNacional(ELECCION_ID_NACIONAL),
|
||||||
.filter(p => p.bancasTotales > 0)
|
});
|
||||||
.map(p => p.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
const agrupacionesFiltradas = todasAgrupaciones.filter(a => partidosConBancasIds.has(a.id));
|
useEffect(() => {
|
||||||
|
if (!composicionData || !todasAgrupaciones || todasAgrupaciones.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
agrupacionesFiltradas.sort((a, b) => (a.ordenSenadoresNacionales || 999) - (b.ordenSenadoresNacionales || 999));
|
// Creamos un Set con los IDs de los partidos que tienen al menos una banca de senador
|
||||||
|
const partidosConBancasIds = new Set(
|
||||||
setAgrupacionesOrdenadas(agrupacionesFiltradas);
|
composicionData.senadores.partidos
|
||||||
|
.filter(p => p.bancasTotales > 0)
|
||||||
}, [todasAgrupaciones, composicionData]);
|
.map(p => p.id)
|
||||||
|
|
||||||
const sensors = useSensors(
|
|
||||||
useSensor(PointerSensor),
|
|
||||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragEnd = (event: DragEndEvent) => {
|
const agrupacionesFiltradas = todasAgrupaciones.filter(a => partidosConBancasIds.has(a.id));
|
||||||
const { active, over } = event;
|
|
||||||
if (over && active.id !== over.id) {
|
|
||||||
setAgrupacionesOrdenadas((items) => {
|
|
||||||
const oldIndex = items.findIndex((item) => item.id === active.id);
|
|
||||||
const newIndex = items.findIndex((item) => item.id === over.id);
|
|
||||||
return arrayMove(items, oldIndex, newIndex);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveOrder = async () => {
|
agrupacionesFiltradas.sort((a, b) => (a.ordenSenadoresNacionales || 999) - (b.ordenSenadoresNacionales || 999));
|
||||||
const idsOrdenados = agrupacionesOrdenadas.map(a => a.id);
|
|
||||||
try {
|
|
||||||
await updateOrden('senadores-nacionales', idsOrdenados);
|
|
||||||
alert('Orden de Senadores Nacionales guardado con éxito!');
|
|
||||||
} catch (error) {
|
|
||||||
alert('Error al guardar el orden de Senadores Nacionales.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isLoading = isLoadingAgrupaciones || isLoadingComposicion;
|
setAgrupacionesOrdenadas(agrupacionesFiltradas);
|
||||||
if (isLoading) return <p>Cargando orden de Senadores Nacionales...</p>;
|
|
||||||
|
|
||||||
return (
|
}, [todasAgrupaciones, composicionData]);
|
||||||
<div className="admin-module">
|
|
||||||
<h3>Ordenar Agrupaciones (Senado de la Nación)</h3>
|
const sensors = useSensors(
|
||||||
<p>Arrastre para reordenar. Solo se muestran los partidos con bancas.</p>
|
useSensor(PointerSensor),
|
||||||
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||||
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
);
|
||||||
<SortableContext items={agrupacionesOrdenadas.map(a => a.id)} strategy={horizontalListSortingStrategy}>
|
|
||||||
<ul className="sortable-list-horizontal">
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
{agrupacionesOrdenadas.map(agrupacion => (
|
const { active, over } = event;
|
||||||
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
if (over && active.id !== over.id) {
|
||||||
{agrupacion.nombreCorto || agrupacion.nombre}
|
setAgrupacionesOrdenadas((items) => {
|
||||||
</SortableItem>
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
))}
|
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||||
</ul>
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
</SortableContext>
|
});
|
||||||
</DndContext>
|
}
|
||||||
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden</button>
|
};
|
||||||
</div>
|
|
||||||
);
|
const handleSaveOrder = async () => {
|
||||||
|
const idsOrdenados = agrupacionesOrdenadas.map(a => a.id);
|
||||||
|
try {
|
||||||
|
await updateOrden('senadores-nacionales', idsOrdenados);
|
||||||
|
alert('Orden de Senadores Nacionales guardado con éxito!');
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error al guardar el orden de Senadores Nacionales.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isLoading = isLoadingAgrupaciones || isLoadingComposicion;
|
||||||
|
if (isLoading) return <p>Cargando orden de Senadores Nacionales...</p>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h3>Ordenar Agrupaciones (Senado de la Nación)</h3>
|
||||||
|
<p>Arrastre para reordenar. Solo se muestran los partidos con bancas.</p>
|
||||||
|
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
||||||
|
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
||||||
|
<SortableContext items={agrupacionesOrdenadas.map(a => a.id)} strategy={horizontalListSortingStrategy}>
|
||||||
|
<ul className="sortable-list-horizontal">
|
||||||
|
{agrupacionesOrdenadas.map(agrupacion => (
|
||||||
|
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
||||||
|
{`(${agrupacion.id}) ${agrupacion.nombreCorto || agrupacion.nombre}`}
|
||||||
|
</SortableItem>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
@@ -14,7 +14,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+2b7fb927e2f0d9ff06dffa820bc9809d6e138b01")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+069446b90326f5acee630bf3b88238e4e054764f")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
Reference in New Issue
Block a user