Fix Overrides Candidatos
This commit is contained in:
@@ -9,6 +9,14 @@ const SENADORES_ID = 5;
|
|||||||
const DIPUTADOS_ID = 6;
|
const DIPUTADOS_ID = 6;
|
||||||
const CONCEJALES_ID = 7;
|
const CONCEJALES_ID = 7;
|
||||||
|
|
||||||
|
// Esta función limpia cualquier carácter no válido de un string de color.
|
||||||
|
const sanitizeColor = (color: string | null | undefined): string => {
|
||||||
|
if (!color) return '#000000'; // Devuelve un color válido por defecto si es nulo
|
||||||
|
// Usa una expresión regular para eliminar todo lo que no sea un '#' o un carácter hexadecimal
|
||||||
|
const sanitized = color.replace(/[^#0-9a-fA-F]/g, '');
|
||||||
|
return sanitized.startsWith('#') ? sanitized : `#${sanitized}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const AgrupacionesManager = () => {
|
export const AgrupacionesManager = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
@@ -27,20 +35,33 @@ export const AgrupacionesManager = () => {
|
|||||||
queryFn: getLogos,
|
queryFn: getLogos,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Usamos useEffect para reaccionar cuando los datos de 'logos' se cargan o cambian.
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (logos) {
|
// Solo procedemos si los datos de agrupaciones están disponibles
|
||||||
setEditedLogos(logos);
|
if (agrupaciones && agrupaciones.length > 0) {
|
||||||
|
// Inicializamos el estado de 'editedAgrupaciones' una sola vez.
|
||||||
|
// Usamos una función en setState para asegurarnos de que solo se ejecute
|
||||||
|
// si el estado está vacío, evitando sobreescribir ediciones del usuario.
|
||||||
|
setEditedAgrupaciones(prev => {
|
||||||
|
if (Object.keys(prev).length === 0) {
|
||||||
|
return Object.fromEntries(agrupaciones.map(a => [a.id, {}]));
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [logos]);
|
|
||||||
|
|
||||||
// Usamos otro useEffect para reaccionar a los datos de 'agrupaciones'.
|
// Hacemos lo mismo para los logos
|
||||||
useEffect(() => {
|
if (logos && logos.length > 0) {
|
||||||
if (agrupaciones) {
|
setEditedLogos(prev => {
|
||||||
const initialEdits = Object.fromEntries(agrupaciones.map(a => [a.id, {}]));
|
if (prev.length === 0) {
|
||||||
setEditedAgrupaciones(initialEdits);
|
// Creamos una copia profunda para evitar mutaciones accidentales
|
||||||
|
return JSON.parse(JSON.stringify(logos));
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [agrupaciones]);
|
// La dependencia ahora es el estado de carga. El hook se ejecutará cuando
|
||||||
|
// isLoadingAgrupaciones o isLoadingLogos cambien de true a false.
|
||||||
|
}, [agrupaciones, logos]);
|
||||||
|
|
||||||
const handleInputChange = (id: string, field: 'nombreCorto' | 'color', value: string) => {
|
const handleInputChange = (id: string, field: 'nombreCorto' | 'color', value: string) => {
|
||||||
setEditedAgrupaciones(prev => ({
|
setEditedAgrupaciones(prev => ({
|
||||||
@@ -130,7 +151,14 @@ export const AgrupacionesManager = () => {
|
|||||||
<tr key={agrupacion.id}>
|
<tr key={agrupacion.id}>
|
||||||
<td>{agrupacion.nombre}</td>
|
<td>{agrupacion.nombre}</td>
|
||||||
<td><input type="text" value={editedAgrupaciones[agrupacion.id]?.nombreCorto ?? agrupacion.nombreCorto ?? ''} onChange={(e) => handleInputChange(agrupacion.id, 'nombreCorto', e.target.value)} /></td>
|
<td><input type="text" value={editedAgrupaciones[agrupacion.id]?.nombreCorto ?? agrupacion.nombreCorto ?? ''} onChange={(e) => handleInputChange(agrupacion.id, 'nombreCorto', e.target.value)} /></td>
|
||||||
<td><input type="color" value={editedAgrupaciones[agrupacion.id]?.color ?? agrupacion.color ?? '#000000'} onChange={(e) => handleInputChange(agrupacion.id, 'color', e.target.value)} /></td>
|
<td>
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
// Usamos la función sanitizeColor para asegurarnos de que el valor sea siempre válido
|
||||||
|
value={sanitizeColor(editedAgrupaciones[agrupacion.id]?.color ?? agrupacion.color)}
|
||||||
|
onChange={(e) => handleInputChange(agrupacion.id, 'color', e.target.value)}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, SENADORES_ID)} onChange={(e) => handleLogoChange(agrupacion.id, SENADORES_ID, e.target.value)} /></td>
|
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, SENADORES_ID)} onChange={(e) => handleLogoChange(agrupacion.id, SENADORES_ID, e.target.value)} /></td>
|
||||||
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, DIPUTADOS_ID)} onChange={(e) => handleLogoChange(agrupacion.id, DIPUTADOS_ID, e.target.value)} /></td>
|
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, DIPUTADOS_ID)} onChange={(e) => handleLogoChange(agrupacion.id, DIPUTADOS_ID, e.target.value)} /></td>
|
||||||
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, CONCEJALES_ID)} onChange={(e) => handleLogoChange(agrupacion.id, CONCEJALES_ID, e.target.value)} /></td>
|
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, CONCEJALES_ID)} onChange={(e) => handleLogoChange(agrupacion.id, CONCEJALES_ID, e.target.value)} /></td>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
// src/components/CandidatoOverridesManager.tsx
|
||||||
|
|
||||||
import { useState, useMemo, useEffect } from 'react';
|
import { useState, useMemo, useEffect } from 'react';
|
||||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
import { getMunicipiosForAdmin, getAgrupaciones, getCandidatos, updateCandidatos } from '../services/apiService';
|
import { getMunicipiosForAdmin, getAgrupaciones, getCandidatos, updateCandidatos } from '../services/apiService';
|
||||||
import type { MunicipioSimple, AgrupacionPolitica, CandidatoOverride } from '../types';
|
import type { MunicipioSimple, AgrupacionPolitica, CandidatoOverride } from '../types';
|
||||||
|
|
||||||
// Las categorías son las mismas que para los logos
|
|
||||||
const CATEGORIAS_OPTIONS = [
|
const CATEGORIAS_OPTIONS = [
|
||||||
{ value: 5, label: 'Senadores' },
|
{ value: 5, label: 'Senadores' },
|
||||||
{ value: 6, label: 'Diputados' },
|
{ value: 6, label: 'Diputados' },
|
||||||
@@ -15,23 +16,31 @@ export const CandidatoOverridesManager = () => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { data: municipios = [] } = useQuery<MunicipioSimple[]>({ queryKey: ['municipiosForAdmin'], queryFn: getMunicipiosForAdmin });
|
const { data: municipios = [] } = useQuery<MunicipioSimple[]>({ queryKey: ['municipiosForAdmin'], queryFn: getMunicipiosForAdmin });
|
||||||
const { data: agrupaciones = [] } = useQuery<AgrupacionPolitica[]>({ queryKey: ['agrupaciones'], queryFn: getAgrupaciones });
|
const { data: agrupaciones = [] } = useQuery<AgrupacionPolitica[]>({ queryKey: ['agrupaciones'], queryFn: getAgrupaciones });
|
||||||
// --- Usar la query para candidatos ---
|
|
||||||
const { data: candidatos = [] } = useQuery<CandidatoOverride[]>({ queryKey: ['candidatos'], queryFn: getCandidatos });
|
const { data: candidatos = [] } = useQuery<CandidatoOverride[]>({ queryKey: ['candidatos'], queryFn: getCandidatos });
|
||||||
|
|
||||||
const [selectedCategoria, setSelectedCategoria] = useState<{ value: number; label: string } | null>(null);
|
const [selectedCategoria, setSelectedCategoria] = useState<{ value: number; label: string } | null>(null);
|
||||||
const [selectedMunicipio, setSelectedMunicipio] = useState<{ value: string; label: string } | null>(null);
|
const [selectedMunicipio, setSelectedMunicipio] = useState<{ value: string; label: string } | null>(null);
|
||||||
const [selectedAgrupacion, setSelectedAgrupacion] = useState<{ value: string; label: string } | null>(null);
|
const [selectedAgrupacion, setSelectedAgrupacion] = useState<{ value: string; label: string } | null>(null);
|
||||||
// --- El estado es para el nombre del candidato ---
|
|
||||||
const [nombreCandidato, setNombreCandidato] = useState('');
|
const [nombreCandidato, setNombreCandidato] = useState('');
|
||||||
|
|
||||||
const municipioOptions = useMemo(() => municipios.map(m => ({ value: m.id, label: m.nombre })), [municipios]);
|
const municipioOptions = useMemo(() =>
|
||||||
|
// Añadimos la opción "General" que representará un ámbito nulo
|
||||||
|
[{ value: 'general', label: 'General (Todos los Municipios)' }, ...municipios.map(m => ({ value: m.id, label: m.nombre }))]
|
||||||
|
, [municipios]);
|
||||||
|
|
||||||
const agrupacionOptions = useMemo(() => agrupaciones.map(a => ({ value: a.id, label: a.nombre })), [agrupaciones]);
|
const agrupacionOptions = useMemo(() => agrupaciones.map(a => ({ value: a.id, label: a.nombre })), [agrupaciones]);
|
||||||
|
|
||||||
// --- Lógica para encontrar el nombre del candidato actual ---
|
|
||||||
const currentCandidato = useMemo(() => {
|
const currentCandidato = useMemo(() => {
|
||||||
if (!selectedMunicipio || !selectedAgrupacion || !selectedCategoria) return '';
|
if (!selectedAgrupacion || !selectedCategoria) return '';
|
||||||
|
|
||||||
|
// Determina si estamos buscando un override general (null) o específico (ID numérico)
|
||||||
|
const ambitoIdBuscado = selectedMunicipio?.value === 'general' ? null : (selectedMunicipio ? parseInt(selectedMunicipio.value) : undefined);
|
||||||
|
|
||||||
|
// Si no se ha seleccionado un municipio, no buscamos nada
|
||||||
|
if (ambitoIdBuscado === undefined) return '';
|
||||||
|
|
||||||
return candidatos.find(c =>
|
return candidatos.find(c =>
|
||||||
c.ambitoGeograficoId === parseInt(selectedMunicipio.value) &&
|
c.ambitoGeograficoId === ambitoIdBuscado &&
|
||||||
c.agrupacionPoliticaId === selectedAgrupacion.value &&
|
c.agrupacionPoliticaId === selectedAgrupacion.value &&
|
||||||
c.categoriaId === selectedCategoria.value
|
c.categoriaId === selectedCategoria.value
|
||||||
)?.nombreCandidato || '';
|
)?.nombreCandidato || '';
|
||||||
@@ -42,34 +51,40 @@ export const CandidatoOverridesManager = () => {
|
|||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
if (!selectedMunicipio || !selectedAgrupacion || !selectedCategoria) return;
|
if (!selectedMunicipio || !selectedAgrupacion || !selectedCategoria) return;
|
||||||
|
|
||||||
// --- Construir el objeto CandidatoOverride ---
|
const ambitoIdParaEnviar = selectedMunicipio.value === 'general'
|
||||||
|
? null
|
||||||
|
: parseInt(selectedMunicipio.value);
|
||||||
|
|
||||||
const newCandidatoEntry: CandidatoOverride = {
|
const newCandidatoEntry: CandidatoOverride = {
|
||||||
id: 0, // El backend no necesita el ID para un upsert
|
id: 0, // El backend no lo necesita para el upsert
|
||||||
agrupacionPoliticaId: selectedAgrupacion.value,
|
agrupacionPoliticaId: selectedAgrupacion.value,
|
||||||
categoriaId: selectedCategoria.value,
|
categoriaId: selectedCategoria.value,
|
||||||
ambitoGeograficoId: parseInt(selectedMunicipio.value),
|
ambitoGeograficoId: ambitoIdParaEnviar,
|
||||||
nombreCandidato: nombreCandidato
|
nombreCandidato: nombreCandidato || null
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateCandidatos([newCandidatoEntry]);
|
await updateCandidatos([newCandidatoEntry]);
|
||||||
queryClient.invalidateQueries({ queryKey: ['candidatos'] });
|
queryClient.invalidateQueries({ queryKey: ['candidatos'] });
|
||||||
alert('Override de candidato guardado.');
|
alert('Override de candidato guardado.');
|
||||||
} catch { alert('Error al guardar.'); }
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
alert('Error al guardar el override del candidato.');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="admin-module">
|
<div className="admin-module">
|
||||||
<h3>Overrides de Nombres de Candidatos</h3>
|
<h3>Overrides de Nombres de Candidatos</h3>
|
||||||
<p>Configure un nombre de candidato específico para un partido en un municipio y categoría determinados.</p>
|
<p>Configure un nombre de candidato específico para un partido, categoría y municipio (o general).</p>
|
||||||
<div style={{ display: 'flex', gap: '1rem', alignItems: 'flex-end' }}>
|
<div style={{ display: 'flex', gap: '1rem', alignItems: 'flex-end', flexWrap: 'wrap' }}>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<label>Categoría</label>
|
<label>Categoría</label>
|
||||||
<Select options={CATEGORIAS_OPTIONS} value={selectedCategoria} onChange={setSelectedCategoria} isClearable placeholder="Seleccione..."/>
|
<Select options={CATEGORIAS_OPTIONS} value={selectedCategoria} onChange={setSelectedCategoria} isClearable placeholder="Seleccione..."/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<label>Municipio</label>
|
<label>Municipio (Opcional)</label>
|
||||||
<Select options={municipioOptions} value={selectedMunicipio} onChange={setSelectedMunicipio} isClearable placeholder="Seleccione..."/>
|
<Select options={municipioOptions} value={selectedMunicipio} onChange={setSelectedMunicipio} isClearable placeholder="General..."/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<label>Agrupación</label>
|
<label>Agrupación</label>
|
||||||
@@ -77,9 +92,9 @@ export const CandidatoOverridesManager = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 2 }}>
|
<div style={{ flex: 2 }}>
|
||||||
<label>Nombre del Candidato</label>
|
<label>Nombre del Candidato</label>
|
||||||
<input type="text" value={nombreCandidato} onChange={e => setNombreCandidato(e.target.value)} style={{ width: '100%' }} disabled={!selectedMunicipio || !selectedAgrupacion || !selectedCategoria} />
|
<input type="text" value={nombreCandidato} onChange={e => setNombreCandidato(e.target.value)} style={{ width: '100%' }} disabled={!selectedAgrupacion || !selectedCategoria} />
|
||||||
</div>
|
</div>
|
||||||
<button onClick={handleSave} disabled={!selectedMunicipio || !selectedAgrupacion || !selectedCategoria}>Guardar</button>
|
<button onClick={handleSave} disabled={!selectedAgrupacion || !selectedCategoria}>Guardar</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ export const LogoOverridesManager = () => {
|
|||||||
const [selectedAgrupacion, setSelectedAgrupacion] = useState<{ value: string; label: string } | null>(null);
|
const [selectedAgrupacion, setSelectedAgrupacion] = useState<{ value: string; label: string } | null>(null);
|
||||||
const [logoUrl, setLogoUrl] = useState('');
|
const [logoUrl, setLogoUrl] = useState('');
|
||||||
|
|
||||||
const municipioOptions = useMemo(() => municipios.map(m => ({ value: m.id, label: m.nombre })), [municipios]);
|
const municipioOptions = useMemo(() =>
|
||||||
|
[{ value: 'general', label: 'General (Todas las secciones)' }, ...municipios.map(m => ({ value: m.id, label: m.nombre }))]
|
||||||
|
, [municipios]);
|
||||||
const agrupacionOptions = useMemo(() => agrupaciones.map(a => ({ value: a.id, label: a.nombre })), [agrupaciones]);
|
const agrupacionOptions = useMemo(() => agrupaciones.map(a => ({ value: a.id, label: a.nombre })), [agrupaciones]);
|
||||||
|
|
||||||
const currentLogo = useMemo(() => {
|
const currentLogo = useMemo(() => {
|
||||||
|
|||||||
@@ -55,5 +55,5 @@ export interface CandidatoOverride {
|
|||||||
agrupacionPoliticaId: string;
|
agrupacionPoliticaId: string;
|
||||||
categoriaId: number;
|
categoriaId: number;
|
||||||
ambitoGeograficoId: number | null;
|
ambitoGeograficoId: number | null;
|
||||||
nombreCandidato: string;
|
nombreCandidato: string | null;
|
||||||
}
|
}
|
||||||
@@ -252,11 +252,10 @@ public class AdminController : ControllerBase
|
|||||||
/// Guarda (actualiza o crea) una lista de overrides de candidatos.
|
/// Guarda (actualiza o crea) una lista de overrides de candidatos.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPut("candidatos")]
|
[HttpPut("candidatos")]
|
||||||
public async Task<IActionResult> UpdateCandidatos([FromBody] List<CandidatoOverride> candidatos)
|
public async Task<IActionResult> UpdateCandidatos([FromBody] List<UpdateCandidatoDto> candidatos)
|
||||||
{
|
{
|
||||||
foreach (var candidatoDto in candidatos)
|
foreach (var candidatoDto in candidatos)
|
||||||
{
|
{
|
||||||
// Buscamos un override existente basado en la combinación única
|
|
||||||
var candidatoExistente = await _dbContext.CandidatosOverrides
|
var candidatoExistente = await _dbContext.CandidatosOverrides
|
||||||
.FirstOrDefaultAsync(c =>
|
.FirstOrDefaultAsync(c =>
|
||||||
c.AgrupacionPoliticaId == candidatoDto.AgrupacionPoliticaId &&
|
c.AgrupacionPoliticaId == candidatoDto.AgrupacionPoliticaId &&
|
||||||
@@ -265,18 +264,24 @@ public class AdminController : ControllerBase
|
|||||||
|
|
||||||
if (candidatoExistente != null)
|
if (candidatoExistente != null)
|
||||||
{
|
{
|
||||||
// Si existe y el nombre es diferente, lo actualizamos.
|
// El registro ya existe
|
||||||
if (candidatoExistente.NombreCandidato != candidatoDto.NombreCandidato)
|
if (string.IsNullOrWhiteSpace(candidatoDto.NombreCandidato))
|
||||||
{
|
{
|
||||||
|
// El usuario envió un nombre vacío -> Eliminar el registro
|
||||||
|
_dbContext.CandidatosOverrides.Remove(candidatoExistente);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// El usuario envió un nombre válido -> Actualizar
|
||||||
candidatoExistente.NombreCandidato = candidatoDto.NombreCandidato;
|
candidatoExistente.NombreCandidato = candidatoDto.NombreCandidato;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Si no se encontró un registro exacto, lo añadimos a la base de datos,
|
// El registro no existe
|
||||||
// pero solo si el nombre del candidato no está vacío.
|
|
||||||
if (!string.IsNullOrWhiteSpace(candidatoDto.NombreCandidato))
|
if (!string.IsNullOrWhiteSpace(candidatoDto.NombreCandidato))
|
||||||
{
|
{
|
||||||
|
// El usuario envió un nombre válido -> Crear nuevo registro
|
||||||
_dbContext.CandidatosOverrides.Add(new CandidatoOverride
|
_dbContext.CandidatosOverrides.Add(new CandidatoOverride
|
||||||
{
|
{
|
||||||
AgrupacionPoliticaId = candidatoDto.AgrupacionPoliticaId,
|
AgrupacionPoliticaId = candidatoDto.AgrupacionPoliticaId,
|
||||||
@@ -285,27 +290,11 @@ public class AdminController : ControllerBase
|
|||||||
NombreCandidato = candidatoDto.NombreCandidato
|
NombreCandidato = candidatoDto.NombreCandidato
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Si no existe y el nombre está vacío, no hacemos nada.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// También necesitamos manejar los casos donde se borra un nombre (se envía un string vacío)
|
|
||||||
var overridesAEliminar = await _dbContext.CandidatosOverrides
|
|
||||||
.Where(c => candidatos.Any(dto =>
|
|
||||||
dto.AgrupacionPoliticaId == c.AgrupacionPoliticaId &&
|
|
||||||
dto.CategoriaId == c.CategoriaId &&
|
|
||||||
dto.AmbitoGeograficoId == c.AmbitoGeograficoId &&
|
|
||||||
string.IsNullOrWhiteSpace(dto.NombreCandidato)
|
|
||||||
))
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
if (overridesAEliminar.Any())
|
|
||||||
{
|
|
||||||
_dbContext.CandidatosOverrides.RemoveRange(overridesAEliminar);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
await _dbContext.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
_logger.LogInformation("Se procesaron {Count} overrides de candidatos.", candidatos.Count);
|
return NoContent();
|
||||||
return NoContent(); // Respuesta estándar para un PUT exitoso
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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+479c2c60f214472aeffd4404b482ffb940c3049e")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d78a02a0ebc4c70ea01e48821db963110e7ce280")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","/hrHm\u002B3v8DuHSlyFsxHPCFUvDW\u002BZsLR4kaMxNwUHl2M=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","v\u002BEjGaN1m59e9gwl3kXTpjNw\u002B3kwhJD2SLKx38/opjM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Kt4ImnGs0wklEJp/6NxrhrTvGLQxPfYUAB5LMWAnz10=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","v1SBeIVg8rE3EddYwnvF/EsPYr2F5GAppt/Egvdtr/0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","/hrHm\u002B3v8DuHSlyFsxHPCFUvDW\u002BZsLR4kaMxNwUHl2M=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","v\u002BEjGaN1m59e9gwl3kXTpjNw\u002B3kwhJD2SLKx38/opjM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Kt4ImnGs0wklEJp/6NxrhrTvGLQxPfYUAB5LMWAnz10=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","v1SBeIVg8rE3EddYwnvF/EsPYr2F5GAppt/Egvdtr/0="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Elecciones.Core.DTOs.ApiRequests;
|
||||||
|
|
||||||
|
public class UpdateCandidatoDto
|
||||||
|
{
|
||||||
|
// Esta clase solo contiene los IDs y el valor, igual que lo que envía el frontend.
|
||||||
|
public string AgrupacionPoliticaId { get; set; } = null!;
|
||||||
|
public int CategoriaId { get; set; }
|
||||||
|
public int? AmbitoGeograficoId { get; set; }
|
||||||
|
public string? NombreCandidato { get; set; }
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")]
|
||||||
[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+479c2c60f214472aeffd4404b482ffb940c3049e")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d78a02a0ebc4c70ea01e48821db963110e7ce280")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")]
|
||||||
[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+479c2c60f214472aeffd4404b482ffb940c3049e")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d78a02a0ebc4c70ea01e48821db963110e7ce280")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")]
|
||||||
[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+479c2c60f214472aeffd4404b482ffb940c3049e")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d78a02a0ebc4c70ea01e48821db963110e7ce280")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
Reference in New Issue
Block a user