feat: Partido Politico Manual
This commit is contained in:
		| @@ -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 ( | ||||||
|  |     <div className="add-entity-form-container"> | ||||||
|  |       <h4>Añadir Partido Manualmente</h4> | ||||||
|  |       <form onSubmit={handleSubmit} className="add-entity-form"> | ||||||
|  |  | ||||||
|  |         <div className="form-field"> | ||||||
|  |           <label>Nombre Completo</label> | ||||||
|  |           <input type="text" value={nombre} onChange={e => setNombre(e.target.value)} required /> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div className="form-field"> | ||||||
|  |           <label>Nombre Corto</label> | ||||||
|  |           <input type="text" value={nombreCorto} onChange={e => setNombreCorto(e.target.value)} /> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div className="form-field"> | ||||||
|  |           <label>Color</label> | ||||||
|  |           <input type="color" value={color} onChange={e => setColor(e.target.value)} /> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <button type="submit" disabled={isLoading}> | ||||||
|  |           {isLoading ? 'Guardando...' : 'Guardar Partido'} | ||||||
|  |         </button> | ||||||
|  |       </form> | ||||||
|  |       {error && <p style={{ color: 'red', marginTop: '0.5rem', textAlign: 'left' }}>{error}</p>} | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
| @@ -4,6 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; | |||||||
| import Select from 'react-select'; | import Select from 'react-select'; | ||||||
| import { getAgrupaciones, updateAgrupacion, getLogos, updateLogos } from '../services/apiService'; | import { getAgrupaciones, updateAgrupacion, getLogos, updateLogos } from '../services/apiService'; | ||||||
| import type { AgrupacionPolitica, LogoAgrupacionCategoria, UpdateAgrupacionData } from '../types'; | import type { AgrupacionPolitica, LogoAgrupacionCategoria, UpdateAgrupacionData } from '../types'; | ||||||
|  | import { AddAgrupacionForm } from './AddAgrupacionForm'; | ||||||
| import './AgrupacionesManager.css'; | import './AgrupacionesManager.css'; | ||||||
|  |  | ||||||
| const GLOBAL_ELECTION_ID = 0; | const GLOBAL_ELECTION_ID = 0; | ||||||
| @@ -34,6 +35,11 @@ export const AgrupacionesManager = () => { | |||||||
|         queryFn: () => Promise.all([getLogos(0), getLogos(1), getLogos(2)]).then(res => res.flat()), |         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(() => { |     useEffect(() => { | ||||||
|         if (agrupaciones.length > 0) { |         if (agrupaciones.length > 0) { | ||||||
|             const initialEdits = Object.fromEntries( |             const initialEdits = Object.fromEntries( | ||||||
| @@ -142,6 +148,7 @@ export const AgrupacionesManager = () => { | |||||||
|                     <button onClick={handleSaveAll} style={{ marginTop: '1rem' }}> |                     <button onClick={handleSaveAll} style={{ marginTop: '1rem' }}> | ||||||
|                         Guardar Todos los Cambios |                         Guardar Todos los Cambios | ||||||
|                     </button> |                     </button> | ||||||
|  |                     <AddAgrupacionForm onSuccess={handleCreationSuccess} /> | ||||||
|                 </> |                 </> | ||||||
|             )} |             )} | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
							
								
								
									
										72
									
								
								Elecciones-Web/frontend-admin/src/components/FormStyles.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								Elecciones-Web/frontend-admin/src/components/FormStyles.css
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  | } | ||||||
| @@ -1,9 +1,11 @@ | |||||||
| // src/services/apiService.ts | // src/services/apiService.ts | ||||||
| import axios from 'axios'; | import axios from 'axios'; | ||||||
| import { triggerLogout } from '../context/authUtils'; | import { triggerLogout } from '../context/authUtils'; | ||||||
| import type { CandidatoOverride, AgrupacionPolitica, | import type { | ||||||
|  |   CandidatoOverride, AgrupacionPolitica, | ||||||
|   UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria, |   UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria, | ||||||
|   MunicipioSimple, BancaPrevia, ProvinciaSimple } from '../types'; |   MunicipioSimple, BancaPrevia, ProvinciaSimple | ||||||
|  | } from '../types'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * URL base para las llamadas a la API. |  * URL base para las llamadas a la API. | ||||||
| @@ -192,3 +194,15 @@ export const getProvinciasForAdmin = async (): Promise<ProvinciaSimple[]> => { | |||||||
|   const response = await adminApiClient.get('/catalogos/provincias'); |   const response = await adminApiClient.get('/catalogos/provincias'); | ||||||
|   return response.data; |   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<AgrupacionPolitica> => { | ||||||
|  |   const response = await adminApiClient.post('/agrupaciones', data); | ||||||
|  |   return response.data; | ||||||
|  | }; | ||||||
| @@ -417,4 +417,49 @@ public class AdminController : ControllerBase | |||||||
|     _logger.LogInformation("Se actualizaron las bancas previas para la EleccionId: {EleccionId}", eleccionId); |     _logger.LogInformation("Se actualizaron las bancas previas para la EleccionId: {EleccionId}", eleccionId); | ||||||
|     return NoContent(); |     return NoContent(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Endpoint para crear una nueva agrupación política manualmente | ||||||
|  |   [HttpPost("agrupaciones")] | ||||||
|  |   public async Task<IActionResult> 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); | ||||||
|  |   } | ||||||
| } | } | ||||||
| @@ -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+5c11763386c5031abd33b743abc7508bddb1c9d6")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] | ||||||
| [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":["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":{}} | {"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":{}} | ||||||
| @@ -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":{}} | {"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":{}} | ||||||
| @@ -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; } | ||||||
|  | } | ||||||
| @@ -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+5c11763386c5031abd33b743abc7508bddb1c9d6")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] | ||||||
| [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+5c11763386c5031abd33b743abc7508bddb1c9d6")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] | ||||||
| [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+5c11763386c5031abd33b743abc7508bddb1c9d6")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99d56033b1a6c61db0f436c43e0d58d9a544cf53")] | ||||||
| [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