107 lines
6.3 KiB
TypeScript
107 lines
6.3 KiB
TypeScript
// src/components/LogoOverridesManager.tsx
|
|
import { useState, useMemo, useEffect } from 'react';
|
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
import Select from 'react-select';
|
|
import { getProvinciasForAdmin, getMunicipiosForAdmin, getAgrupaciones, getLogos, updateLogos } from '../services/apiService';
|
|
import type { MunicipioSimple, AgrupacionPolitica, LogoAgrupacionCategoria, ProvinciaSimple } from '../types';
|
|
import { CATEGORIAS_NACIONALES_OPTIONS, CATEGORIAS_PROVINCIALES_OPTIONS } from '../constants/categorias';
|
|
|
|
const ELECCION_OPTIONS = [
|
|
{ value: 0, label: 'General (Toda la elección)' },
|
|
{ value: 2, label: 'Elecciones Nacionales' },
|
|
{ value: 1, label: 'Elecciones Provinciales' }
|
|
];
|
|
|
|
const AMBITO_LEVEL_OPTIONS = [
|
|
{ value: 'general', label: 'General (Toda la elección)' },
|
|
{ value: 'provincia', label: 'Por Provincia' },
|
|
{ value: 'municipio', label: 'Por Municipio' }
|
|
];
|
|
|
|
export const LogoOverridesManager = () => {
|
|
const queryClient = useQueryClient();
|
|
|
|
// --- ESTADOS ---
|
|
const [selectedEleccion, setSelectedEleccion] = useState(ELECCION_OPTIONS[0]);
|
|
const [selectedAmbitoLevel, setSelectedAmbitoLevel] = useState(AMBITO_LEVEL_OPTIONS[0]);
|
|
const [selectedProvincia, setSelectedProvincia] = useState<ProvinciaSimple | null>(null);
|
|
const [selectedMunicipio, setSelectedMunicipio] = useState<MunicipioSimple | null>(null);
|
|
const [selectedCategoria, setSelectedCategoria] = useState<{ value: number; label: string } | null>(null);
|
|
const [selectedAgrupacion, setSelectedAgrupacion] = useState<AgrupacionPolitica | null>(null);
|
|
const [logoUrl, setLogoUrl] = useState('');
|
|
|
|
// --- QUERIES ---
|
|
const { data: provincias = [] } = useQuery<ProvinciaSimple[]>({ queryKey: ['provinciasForAdmin'], queryFn: getProvinciasForAdmin });
|
|
const { data: municipios = [] } = useQuery<MunicipioSimple[]>({ queryKey: ['municipiosForAdmin'], queryFn: getMunicipiosForAdmin });
|
|
const { data: agrupaciones = [] } = useQuery<AgrupacionPolitica[]>({ queryKey: ['agrupaciones'], queryFn: getAgrupaciones });
|
|
const { data: logos = [] } = useQuery<LogoAgrupacionCategoria[]>({
|
|
queryKey: ['logos', selectedEleccion.value],
|
|
queryFn: () => getLogos(selectedEleccion.value)
|
|
});
|
|
|
|
// --- LÓGICA DE SELECTORES DINÁMICOS ---
|
|
const categoriaOptions = selectedEleccion.value === 2 ? CATEGORIAS_NACIONALES_OPTIONS : CATEGORIAS_PROVINCIALES_OPTIONS;
|
|
|
|
const getAmbitoId = () => {
|
|
if (selectedAmbitoLevel.value === 'municipio' && selectedMunicipio) return parseInt(selectedMunicipio.id);
|
|
if (selectedAmbitoLevel.value === 'provincia' && selectedProvincia) return parseInt(selectedProvincia.id);
|
|
return 0;
|
|
};
|
|
|
|
const currentLogo = useMemo(() => {
|
|
if (!selectedAgrupacion || !selectedCategoria) return '';
|
|
const ambitoId = getAmbitoId();
|
|
return logos.find(l =>
|
|
l.ambitoGeograficoId === ambitoId &&
|
|
l.agrupacionPoliticaId === selectedAgrupacion.id &&
|
|
l.categoriaId === selectedCategoria.value
|
|
)?.logoUrl || '';
|
|
}, [logos, selectedAmbitoLevel, selectedProvincia, selectedMunicipio, selectedAgrupacion, selectedCategoria]);
|
|
|
|
useEffect(() => { setLogoUrl(currentLogo || ''); }, [currentLogo]);
|
|
|
|
const handleSave = async () => {
|
|
if (!selectedAgrupacion || !selectedCategoria) return;
|
|
const newLogoEntry: LogoAgrupacionCategoria = {
|
|
id: 0,
|
|
eleccionId: selectedEleccion.value,
|
|
agrupacionPoliticaId: selectedAgrupacion.id,
|
|
categoriaId: selectedCategoria.value,
|
|
ambitoGeograficoId: getAmbitoId(),
|
|
logoUrl: logoUrl || null
|
|
};
|
|
try {
|
|
await updateLogos([newLogoEntry]);
|
|
queryClient.invalidateQueries({ queryKey: ['logos', selectedEleccion.value] });
|
|
alert('Override de logo guardado.');
|
|
} catch { alert('Error al guardar.'); }
|
|
};
|
|
|
|
return (
|
|
<div className="admin-module">
|
|
<h3>Overrides de Logos</h3>
|
|
<p>Configure una imagen específica para un partido en un contexto determinado.</p>
|
|
<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={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={AMBITO_LEVEL_OPTIONS} value={selectedAmbitoLevel} onChange={(opt) => { setSelectedAmbitoLevel(opt!); setSelectedProvincia(null); setSelectedMunicipio(null); }} />
|
|
|
|
{selectedAmbitoLevel.value === 'provincia' || selectedAmbitoLevel.value === 'municipio' ? (
|
|
<Select options={provincias.map(p => ({ value: p.id, label: p.nombre, ...p }))} getOptionValue={opt => opt.id} getOptionLabel={opt => opt.nombre} value={selectedProvincia} onChange={setSelectedProvincia} placeholder="Seleccione Provincia..." />
|
|
) : <div />}
|
|
|
|
{selectedAmbitoLevel.value === 'municipio' ? (
|
|
<Select options={municipios.map(m => ({ value: m.id, label: m.nombre, ...m }))} getOptionValue={opt => opt.id} getOptionLabel={opt => opt.nombre} value={selectedMunicipio} onChange={setSelectedMunicipio} placeholder="Seleccione Municipio..." isDisabled={!selectedProvincia} />
|
|
) : <div />}
|
|
</div>
|
|
<div style={{ display: 'flex', gap: '1rem', alignItems: 'flex-end', marginTop: '1rem' }}>
|
|
<div style={{ flex: 1 }}>
|
|
<label>URL del Logo Específico</label>
|
|
<input type="text" value={logoUrl} onChange={e => setLogoUrl(e.target.value)} style={{ width: '100%' }} disabled={!selectedAgrupacion || !selectedCategoria} />
|
|
</div>
|
|
<button onClick={handleSave} disabled={!selectedAgrupacion || !selectedCategoria}>Guardar</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}; |