From a78fcf66c02bdaf39203e080da8cfda887a7fd8b Mon Sep 17 00:00:00 2001 From: dmolinari Date: Mon, 20 Oct 2025 14:38:10 -0300 Subject: [PATCH] feat: Partido Politico Manual --- .../src/components/AddAgrupacionForm.tsx | 79 +++++++++++++++++++ .../src/components/AgrupacionesManager.tsx | 31 +++++--- .../src/components/FormStyles.css | 72 +++++++++++++++++ .../frontend-admin/src/services/apiService.ts | 70 +++++++++------- .../Controllers/AdminController.cs | 45 +++++++++++ .../net9.0/Elecciones.Api.AssemblyInfo.cs | 2 +- .../Debug/net9.0/rjsmcshtml.dswa.cache.json | 2 +- .../Debug/net9.0/rjsmrazor.dswa.cache.json | 2 +- .../DTOs/ApiRequests/CreateAgrupacionDto.cs | 17 ++++ .../net9.0/Elecciones.Core.AssemblyInfo.cs | 2 +- .../Elecciones.Database.AssemblyInfo.cs | 2 +- .../Elecciones.Infrastructure.AssemblyInfo.cs | 2 +- 12 files changed, 280 insertions(+), 46 deletions(-) create mode 100644 Elecciones-Web/frontend-admin/src/components/AddAgrupacionForm.tsx create mode 100644 Elecciones-Web/frontend-admin/src/components/FormStyles.css create mode 100644 Elecciones-Web/src/Elecciones.Core/DTOs/ApiRequests/CreateAgrupacionDto.cs diff --git a/Elecciones-Web/frontend-admin/src/components/AddAgrupacionForm.tsx b/Elecciones-Web/frontend-admin/src/components/AddAgrupacionForm.tsx new file mode 100644 index 0000000..ef071a6 --- /dev/null +++ b/Elecciones-Web/frontend-admin/src/components/AddAgrupacionForm.tsx @@ -0,0 +1,79 @@ +// src/components/AddAgrupacionForm.tsx +import { useState } from 'react'; +import { createAgrupacion } from '../services/apiService'; +import type { CreateAgrupacionData } from '../services/apiService'; +// Importa el nuevo archivo CSS si lo creaste, o el existente +import './FormStyles.css'; + +interface Props { + onSuccess: () => void; +} + +export const AddAgrupacionForm = ({ onSuccess }: Props) => { + const [nombre, setNombre] = useState(''); + const [nombreCorto, setNombreCorto] = useState(''); + const [color, setColor] = useState('#000000'); + const [error, setError] = useState(''); + const [isLoading, setIsLoading] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!nombre.trim()) { + setError('El nombre es obligatorio.'); + return; + } + setIsLoading(true); + setError(''); + + const payload: CreateAgrupacionData = { + nombre: nombre.trim(), + nombreCorto: nombreCorto.trim() || null, + color: color, + }; + + try { + await createAgrupacion(payload); + alert(`Partido '${payload.nombre}' creado con éxito.`); + // Limpiar formulario + setNombre(''); + setNombreCorto(''); + setColor('#000000'); + // Notificar al componente padre para que refresque los datos + onSuccess(); + } catch (err: any) { + const errorMessage = err.response?.data?.message || 'Ocurrió un error inesperado.'; + setError(errorMessage); + console.error(err); + } finally { + setIsLoading(false); + } + }; + + return ( +
+

Añadir Partido Manualmente

+
+ +
+ + setNombre(e.target.value)} required /> +
+ +
+ + setNombreCorto(e.target.value)} /> +
+ +
+ + setColor(e.target.value)} /> +
+ + +
+ {error &&

{error}

} +
+ ); +}; \ No newline at end of file diff --git a/Elecciones-Web/frontend-admin/src/components/AgrupacionesManager.tsx b/Elecciones-Web/frontend-admin/src/components/AgrupacionesManager.tsx index 079f753..0b848f1 100644 --- a/Elecciones-Web/frontend-admin/src/components/AgrupacionesManager.tsx +++ b/Elecciones-Web/frontend-admin/src/components/AgrupacionesManager.tsx @@ -4,6 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import Select from 'react-select'; import { getAgrupaciones, updateAgrupacion, getLogos, updateLogos } from '../services/apiService'; import type { AgrupacionPolitica, LogoAgrupacionCategoria, UpdateAgrupacionData } from '../types'; +import { AddAgrupacionForm } from './AddAgrupacionForm'; import './AgrupacionesManager.css'; const GLOBAL_ELECTION_ID = 0; @@ -28,12 +29,17 @@ export const AgrupacionesManager = () => { const { data: agrupaciones = [], isLoading: isLoadingAgrupaciones } = useQuery({ queryKey: ['agrupaciones'], queryFn: getAgrupaciones, }); - + const { data: logos = [], isLoading: isLoadingLogos } = useQuery({ queryKey: ['allLogos'], queryFn: () => Promise.all([getLogos(0), getLogos(1), getLogos(2)]).then(res => res.flat()), }); + const handleCreationSuccess = () => { + // Invalida la query de agrupaciones para forzar una actualización + queryClient.invalidateQueries({ queryKey: ['agrupaciones'] }); + }; + useEffect(() => { if (agrupaciones.length > 0) { const initialEdits = Object.fromEntries( @@ -63,7 +69,7 @@ export const AgrupacionesManager = () => { const key = `${agrupacionId}-${selectedEleccion.value}`; setEditedLogos(prev => ({ ...prev, [key]: value })); }; - + const handleSaveAll = async () => { try { const agrupacionPromises = agrupaciones.map(agrupacion => { @@ -74,7 +80,7 @@ export const AgrupacionesManager = () => { }; return updateAgrupacion(agrupacion.id, payload); }); - + // --- CORRECCIÓN CLAVE 2: Enviar `null` a la API en lugar de `0` --- const logosPayload = Object.entries(editedLogos) .map(([key, logoUrl]) => { @@ -85,13 +91,13 @@ export const AgrupacionesManager = () => { const logoPromise = updateLogos(logosPayload); await Promise.all([...agrupacionPromises, logoPromise]); - + await queryClient.invalidateQueries({ queryKey: ['agrupaciones'] }); await queryClient.invalidateQueries({ queryKey: ['allLogos'] }); alert('¡Todos los cambios han sido guardados!'); } catch (err) { console.error("Error al guardar todo:", err); alert("Ocurrió un error."); } }; - + const getLogoValue = (agrupacionId: string): string => { const key = `${agrupacionId}-${selectedEleccion.value}`; return editedLogos[key] ?? ''; @@ -101,9 +107,9 @@ export const AgrupacionesManager = () => { return (
-
+

Gestión de Agrupaciones y Logos

-
+
handleInputChange(agrupacion.id, 'nombreCorto', e.target.value)} /> handleInputChange(agrupacion.id, 'color', e.target.value)} /> - handleLogoInputChange(agrupacion.id, e.target.value)} + handleLogoInputChange(agrupacion.id, e.target.value)} /> @@ -142,6 +148,7 @@ export const AgrupacionesManager = () => { + )}
diff --git a/Elecciones-Web/frontend-admin/src/components/FormStyles.css b/Elecciones-Web/frontend-admin/src/components/FormStyles.css new file mode 100644 index 0000000..9b75fd6 --- /dev/null +++ b/Elecciones-Web/frontend-admin/src/components/FormStyles.css @@ -0,0 +1,72 @@ +/* src/components/FormStyles.css */ + +.add-entity-form-container { + border-top: 2px solid #007bff; + padding-top: 1.5rem; + margin-top: 2rem; +} + +.add-entity-form-container h4 { + margin-top: 0; + margin-bottom: 1rem; + color: #333; +} + +.add-entity-form { + display: grid; + /* Usamos grid para un control preciso de las columnas */ + grid-template-columns: 3fr 2fr 0.5fr auto; + gap: 1rem; + align-items: flex-end; /* Alinea los elementos en la parte inferior de la celda */ +} + +.form-field { + display: flex; + flex-direction: column; + margin-right: 15px; +} + +.form-field label { + font-size: 0.85rem; + font-weight: 500; + margin-bottom: 0.25rem; + color: #555; + text-align: left; +} + +.form-field input[type="text"] { + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 1rem; + width: 100%; +} + +.form-field input[type="color"] { + height: 38px; /* Misma altura que los inputs de texto */ + width: 100%; + border: 1px solid #ccc; + border-radius: 4px; + padding: 4px; /* Padding interno para el color */ +} + +.add-entity-form button { + padding: 8px 16px; + height: 38px; /* Misma altura que los inputs */ + border: none; + background-color: #28a745; /* Un color verde para la acción de "crear" */ + color: white; + font-weight: bold; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s; +} + +.add-entity-form button:hover:not(:disabled) { + background-color: #218838; +} + +.add-entity-form button:disabled { + background-color: #6c757d; + cursor: not-allowed; +} \ No newline at end of file diff --git a/Elecciones-Web/frontend-admin/src/services/apiService.ts b/Elecciones-Web/frontend-admin/src/services/apiService.ts index 9a83b0a..b5869c0 100644 --- a/Elecciones-Web/frontend-admin/src/services/apiService.ts +++ b/Elecciones-Web/frontend-admin/src/services/apiService.ts @@ -1,9 +1,11 @@ // src/services/apiService.ts import axios from 'axios'; import { triggerLogout } from '../context/authUtils'; -import type { CandidatoOverride, AgrupacionPolitica, +import type { + CandidatoOverride, AgrupacionPolitica, UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria, - MunicipioSimple, BancaPrevia, ProvinciaSimple } from '../types'; + MunicipioSimple, BancaPrevia, ProvinciaSimple +} from '../types'; /** * URL base para las llamadas a la API. @@ -29,8 +31,8 @@ const adminApiClient = axios.create({ // Cliente de API para endpoints públicos (no envía token) const apiClient = axios.create({ - baseURL: API_URL_BASE, - headers: { 'Content-Type': 'application/json' }, + baseURL: API_URL_BASE, + headers: { 'Content-Type': 'application/json' }, }); @@ -60,26 +62,26 @@ adminApiClient.interceptors.response.use( // --- INTERFACES PARA COMPOSICIÓN NACIONAL (NECESARIAS PARA EL NUEVO MÉTODO) --- export interface PartidoComposicionNacional { - id: string; - nombre: string; - nombreCorto: string | null; - color: string | null; - bancasFijos: number; - bancasGanadas: number; - bancasTotales: number; - ordenDiputadosNacionales: number | null; - ordenSenadoresNacionales: number | null; + id: string; + nombre: string; + nombreCorto: string | null; + color: string | null; + bancasFijos: number; + bancasGanadas: number; + bancasTotales: number; + ordenDiputadosNacionales: number | null; + ordenSenadoresNacionales: number | null; } export interface CamaraComposicionNacional { - camaraNombre: string; - totalBancas: number; - bancasEnJuego: number; - partidos: PartidoComposicionNacional[]; - presidenteBancada: { color: string | null; tipoBanca: 'ganada' | 'previa' | null } | null; + camaraNombre: string; + totalBancas: number; + bancasEnJuego: number; + partidos: PartidoComposicionNacional[]; + presidenteBancada: { color: string | null; tipoBanca: 'ganada' | 'previa' | null } | null; } export interface ComposicionNacionalData { - diputados: CamaraComposicionNacional; - senadores: CamaraComposicionNacional; + diputados: CamaraComposicionNacional; + senadores: CamaraComposicionNacional; } @@ -173,22 +175,34 @@ export const updateLoggingLevel = async (data: UpdateLoggingLevelData): Promise< // 9. Bancas Previas export const getBancasPrevias = async (eleccionId: number): Promise => { - const response = await adminApiClient.get(`/bancas-previas/${eleccionId}`); - return response.data; + const response = await adminApiClient.get(`/bancas-previas/${eleccionId}`); + return response.data; }; export const updateBancasPrevias = async (eleccionId: number, data: BancaPrevia[]): Promise => { - await adminApiClient.put(`/bancas-previas/${eleccionId}`, data); + await adminApiClient.put(`/bancas-previas/${eleccionId}`, data); }; // 10. Obtener Composición Nacional (Endpoint Público) export const getComposicionNacional = async (eleccionId: number): Promise => { - // Este es un endpoint público, por lo que usamos el cliente sin token de admin. - const response = await apiClient.get(`/elecciones/${eleccionId}/composicion-nacional`); - return response.data; + // Este es un endpoint público, por lo que usamos el cliente sin token de admin. + const response = await apiClient.get(`/elecciones/${eleccionId}/composicion-nacional`); + return response.data; }; // Obtenemos las provincias para el selector de ámbito export const getProvinciasForAdmin = async (): Promise => { -const response = await adminApiClient.get('/catalogos/provincias'); -return response.data; + const response = await adminApiClient.get('/catalogos/provincias'); + return response.data; +}; + +export interface CreateAgrupacionData { + nombre: string; + nombreCorto: string | null; + color: string | null; +} + +// Servicio para crear una nueva agrupación +export const createAgrupacion = async (data: CreateAgrupacionData): Promise => { + const response = await adminApiClient.post('/agrupaciones', data); + return response.data; }; \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Api/Controllers/AdminController.cs b/Elecciones-Web/src/Elecciones.Api/Controllers/AdminController.cs index 67ce109..3fed898 100644 --- a/Elecciones-Web/src/Elecciones.Api/Controllers/AdminController.cs +++ b/Elecciones-Web/src/Elecciones.Api/Controllers/AdminController.cs @@ -417,4 +417,49 @@ public class AdminController : ControllerBase _logger.LogInformation("Se actualizaron las bancas previas para la EleccionId: {EleccionId}", eleccionId); return NoContent(); } + + // Endpoint para crear una nueva agrupación política manualmente + [HttpPost("agrupaciones")] + public async Task CreateAgrupacion([FromBody] CreateAgrupacionDto agrupacionDto) + { + // 1. Validar si ya existe una agrupación con el mismo nombre para evitar duplicados + if (await _dbContext.AgrupacionesPoliticas.AnyAsync(a => a.Nombre == agrupacionDto.Nombre)) + { + return BadRequest(new { message = $"Ya existe una agrupación con el nombre '{agrupacionDto.Nombre}'." }); + } + + // 2. Lógica para generar el nuevo ID a partir de 10000 + var agrupacionesManualesIds = await _dbContext.AgrupacionesPoliticas + .Select(a => a.Id) + .ToListAsync(); + + int maxId = 9999; // Empezamos justo antes de 10000 + foreach (var idStr in agrupacionesManualesIds) + { + if (int.TryParse(idStr, out int idNum) && idNum > maxId) + { + maxId = idNum; + } + } + int nuevoId = maxId + 1; + + // 3. Crear la nueva entidad + var nuevaAgrupacion = new AgrupacionPolitica + { + Id = nuevoId.ToString(), + Nombre = agrupacionDto.Nombre, + NombreCorto = agrupacionDto.NombreCorto, + Color = agrupacionDto.Color, + IdTelegrama = $"MANUAL-{nuevoId}" // Asignamos un IdTelegrama distintivo + }; + + // 4. Guardar en la base de datos + await _dbContext.AgrupacionesPoliticas.AddAsync(nuevaAgrupacion); + await _dbContext.SaveChangesAsync(); + + _logger.LogInformation("Se creó una nueva agrupación manual: {Nombre} (ID: {Id})", nuevaAgrupacion.Nombre, nuevaAgrupacion.Id); + + // 5. Devolver la entidad creada (buena práctica REST) + return Ok(nuevaAgrupacion); + } } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs index 418c77a..0043616 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5c11763386c5031abd33b743abc7508bddb1c9d6")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json index 42a086d..fc443fd 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","UIntj4QoiyGr7bnJN8KK5PGrhQd89m\u002BLfh4T8VKPxAk=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","0wGwodjfj889i2s44QRDh9fS1bl2C5rnUPRORJGYKGU=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","fcHt1pC/7h4c2VRBtPGhHnv9Du3oNVywnesibd9Kv5U="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","UIntj4QoiyGr7bnJN8KK5PGrhQd89m\u002BLfh4T8VKPxAk=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","QcSegZUKmWiZEM0Lb/6DeWnkj3Sf005BA6CwcKCfcn8=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","fuuUBrp2adKb2JTGKx6DlNAi3cvFULSlaTZ159rWB7w="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json index 9e7b2c3..ef2b40f 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","UIntj4QoiyGr7bnJN8KK5PGrhQd89m\u002BLfh4T8VKPxAk=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","0wGwodjfj889i2s44QRDh9fS1bl2C5rnUPRORJGYKGU=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","fcHt1pC/7h4c2VRBtPGhHnv9Du3oNVywnesibd9Kv5U="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","UIntj4QoiyGr7bnJN8KK5PGrhQd89m\u002BLfh4T8VKPxAk=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","QcSegZUKmWiZEM0Lb/6DeWnkj3Sf005BA6CwcKCfcn8=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","fuuUBrp2adKb2JTGKx6DlNAi3cvFULSlaTZ159rWB7w="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/DTOs/ApiRequests/CreateAgrupacionDto.cs b/Elecciones-Web/src/Elecciones.Core/DTOs/ApiRequests/CreateAgrupacionDto.cs new file mode 100644 index 0000000..685b1e1 --- /dev/null +++ b/Elecciones-Web/src/Elecciones.Core/DTOs/ApiRequests/CreateAgrupacionDto.cs @@ -0,0 +1,17 @@ +// src/Elecciones.Core/DTOs/ApiRequests/CreateAgrupacionDto.cs +using System.ComponentModel.DataAnnotations; + +namespace Elecciones.Core.DTOs.ApiRequests; + +public class CreateAgrupacionDto +{ + [Required(ErrorMessage = "El nombre es obligatorio.")] + [MaxLength(255)] + public string Nombre { get; set; } = null!; + + [MaxLength(50)] + public string? NombreCorto { get; set; } + + [MaxLength(7)] // Formato #RRGGBB + public string? Color { get; set; } +} \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs index 0677474..0f3a3e3 100644 --- a/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5c11763386c5031abd33b743abc7508bddb1c9d6")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs index 1dafc9d..d28c50e 100644 --- a/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5c11763386c5031abd33b743abc7508bddb1c9d6")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs index 8dbb4e7..858d828 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5c11763386c5031abd33b743abc7508bddb1c9d6")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]