Feat Widgets Controles y Estilos
This commit is contained in:
@@ -289,6 +289,11 @@ export const getResumenPorProvincia = async (eleccionId: number, params: Resumen
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getMunicipiosPorDistrito = async (distritoId: string): Promise<CatalogoItem[]> => {
|
||||
const response = await apiClient.get(`/catalogos/municipios-por-distrito/${distritoId}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getHomeResumen = async (eleccionId: number, distritoId: string, categoriaId: number): Promise<CategoriaResumenHome> => {
|
||||
const queryParams = new URLSearchParams({
|
||||
eleccionId: eleccionId.toString(),
|
||||
|
||||
@@ -144,7 +144,6 @@
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
|
||||
.panel-main-content {
|
||||
display: flex;
|
||||
height: 75vh;
|
||||
@@ -180,15 +179,16 @@
|
||||
|
||||
.partido-logo {
|
||||
flex-shrink: 0;
|
||||
width: 65px; /* ANTES: 75px */
|
||||
height: 65px; /* ANTES: 75px */
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
border-radius: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.partido-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 10%;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.partido-main-content {
|
||||
@@ -279,7 +279,6 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
/* --- MAPA Y ELEMENTOS ASOCIADOS --- */
|
||||
.mapa-componente-container {
|
||||
width: 100%;
|
||||
@@ -313,7 +312,7 @@
|
||||
transition: transform 0.75s ease-in-out;
|
||||
}
|
||||
|
||||
/* AÑADIDO: Desactivar la transición durante el arrastre */
|
||||
/* Desactivar la transición durante el arrastre */
|
||||
.rsm-zoomable-group.panning {
|
||||
transition: none;
|
||||
}
|
||||
@@ -475,52 +474,12 @@
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* --- NUEVOS ESTILOS PARA EL TOGGLE MÓVIL --- */
|
||||
.mobile-view-toggle {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* <-- CAMBIO: De 'fixed' a 'absolute' */
|
||||
bottom: 10px;
|
||||
/* <-- AJUSTE: Menos espacio desde abajo */
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 100;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 30px;
|
||||
padding: 5px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
gap: 5px;
|
||||
backdrop-filter: blur(5px);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.mobile-view-toggle .toggle-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
border-radius: 25px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.mobile-view-toggle .toggle-btn.active {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* --- ESTILOS PARA LOS BOTONES DE ZOOM DEL MAPA --- */
|
||||
.zoom-controls-container {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
z-index: 30;
|
||||
/* Debe ser MAYOR que el z-index del header (20) */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
@@ -542,15 +501,12 @@
|
||||
}
|
||||
|
||||
.zoom-icon-wrapper {
|
||||
/* Contenedor del icono */
|
||||
display: flex;
|
||||
/* Necesario para que el SVG interno se alinee */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.zoom-icon-wrapper svg {
|
||||
/* Apunta directamente al SVG del icono */
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: #333;
|
||||
@@ -558,9 +514,7 @@
|
||||
|
||||
.zoom-btn.disabled {
|
||||
opacity: 0.5;
|
||||
/* Lo hace semitransparente */
|
||||
cursor: not-allowed;
|
||||
/* Muestra el cursor de "no permitido" */
|
||||
}
|
||||
|
||||
.zoom-btn:hover {
|
||||
@@ -576,22 +530,41 @@
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
/* El cursor 'grabbing' se aplica automáticamente por el navegador durante el arrastre */
|
||||
.header-bottom-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 1rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.municipio-search-container {
|
||||
min-width: 280px; /* Ancho mínimo para el buscador en desktop */
|
||||
}
|
||||
|
||||
/* --- MEDIA QUERY PARA RESPONSIVE (ENFOQUE FINAL CON CAPAS) --- */
|
||||
/* --- MEDIA QUERY PARA RESPONSIVE (REFACTORIZADA) --- */
|
||||
@media (max-width: 800px) {
|
||||
|
||||
/* --- CONFIGURACIÓN GENERAL --- */
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
.panel-nacional-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* Controles de vista y header (sin cambios) */
|
||||
.mobile-view-toggle {
|
||||
display: flex;
|
||||
.panel-header {
|
||||
flex-shrink: 0;
|
||||
padding: 1rem;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.panel-main-content {
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.panel-toggle-btn {
|
||||
@@ -608,21 +581,10 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* --- NUEVO LAYOUT DE CAPAS SUPERPUESTAS --- */
|
||||
|
||||
/* 1. El contenedor principal ahora es un ancla de posicionamiento */
|
||||
.panel-main-content {
|
||||
position: relative;
|
||||
/* Clave para que los hijos se posicionen dentro de él */
|
||||
height: calc(100vh - 200px);
|
||||
/* Le damos una altura fija y predecible */
|
||||
min-height: 450px;
|
||||
}
|
||||
|
||||
/* 2. Ambas columnas son capas que ocupan el 100% del espacio del padre */
|
||||
.mapa-column,
|
||||
.resultados-column {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -630,30 +592,20 @@
|
||||
transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
/* Le damos un estilo específico a la columna del mapa para subirla */
|
||||
.mapa-column {
|
||||
top: -50px;
|
||||
left: -10px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
|
||||
/* Hacemos que la columna de resultados pueda tener su propio scroll... */
|
||||
.resultados-column {
|
||||
top: 0;
|
||||
/* Aseguramos que los resultados se queden en su sitio */
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
/* 3. Lógica de visibilidad: controlamos qué capa está "arriba" */
|
||||
.panel-main-content.mobile-view-mapa .resultados-column {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
/* Esta es la propiedad clave que ya tenías, pero es importante verificarla */
|
||||
pointer-events: none;
|
||||
/* Asegura que la capa oculta no bloquee el mapa */
|
||||
}
|
||||
|
||||
.panel-main-content.mobile-view-resultados .mapa-column {
|
||||
@@ -662,85 +614,35 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Hacemos que la columna de resultados pueda tener su propio scroll si el contenido es largo */
|
||||
.resultados-column {
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 4. Estilos de los resultados (ya estaban bien, se mantienen) */
|
||||
.partido-fila {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 1rem 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
border-left: 5px solid;
|
||||
/* Grosor del borde */
|
||||
border-radius: 12px;
|
||||
/* Redondeamos las esquinas */
|
||||
padding-left: 1rem;
|
||||
/* Espacio a la izquierda */
|
||||
}
|
||||
|
||||
.partido-logo {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.partido-main-content {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.partido-top-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.partido-info-wrapper {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.partido-nombre {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.partido-stats {
|
||||
text-align: right;
|
||||
flex-shrink: 0;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
/* --- AJUSTE DE TAMAÑO DEL CONTENEDOR INTERNO DEL MAPA --- */
|
||||
.mapa-column .mapa-componente-container,
|
||||
.mapa-column .mapa-render-area {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Margen de seguridad para el último elemento de la lista de resultados */
|
||||
.panel-partidos-container .partido-fila:last-child {
|
||||
margin-bottom: 90px;
|
||||
}
|
||||
|
||||
.zoom-controls-container {
|
||||
top: 55px;
|
||||
.zoom-controls-container, .mapa-volver-btn {
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
.mapa-volver-btn {
|
||||
top: 55px;
|
||||
left: 12px;
|
||||
.header-bottom-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch; /* Para que ambos elementos ocupen el ancho completo */
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.municipio-search-container {
|
||||
min-width: 100%; /* El buscador ocupa todo el ancho en móvil */
|
||||
}
|
||||
|
||||
/* --- MEDIA QUERY ADICIONAL PARA MÓVIL EN HORIZONTAL --- */
|
||||
/* Se activa cuando la pantalla es ancha pero no muy alta, como un teléfono en landscape */
|
||||
@media (max-width: 900px) and (orientation: landscape) {
|
||||
|
||||
/* Layout flexible de dos columnas */
|
||||
.panel-main-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -748,11 +650,8 @@
|
||||
height: 85vh;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.mapa-column,
|
||||
.resultados-column {
|
||||
.mapa-column, .resultados-column {
|
||||
position: static;
|
||||
/* Desactivamos el posicionamiento absoluto */
|
||||
height: auto;
|
||||
width: auto;
|
||||
opacity: 1;
|
||||
@@ -760,23 +659,177 @@
|
||||
pointer-events: auto;
|
||||
flex: 3;
|
||||
overflow-y: auto;
|
||||
/* Permitimos que la columna de resultados tenga su propio scroll */
|
||||
}
|
||||
|
||||
.resultados-column {
|
||||
flex: 2;
|
||||
min-width: 300px;
|
||||
/* Un mínimo para que no se comprima */
|
||||
}
|
||||
.mobile-results-card-container { display: none; }
|
||||
.panel-toggle-btn { display: flex; }
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. Ocultamos los botones de cambio de vista móvil, ya que ambas se ven */
|
||||
.mobile-view-toggle {
|
||||
display: none;
|
||||
}
|
||||
/* --- ESTILOS PARA LA TARJETA DE RESULTADOS EN MÓVIL (ACTUALIZADOS) --- */
|
||||
.mobile-results-card-container {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 40;
|
||||
width: 95%;
|
||||
max-width: 450px;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease-in-out;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 4. Mostramos de nuevo el botón lateral para colapsar el panel de resultados */
|
||||
.panel-toggle-btn {
|
||||
display: flex;
|
||||
.mobile-results-card-container.view-resultados .collapsible-section {
|
||||
display: none;
|
||||
}
|
||||
.mobile-results-card-container.view-resultados .mobile-card-view-toggle {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
|
||||
.collapsible-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mobile-results-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 18px; /* REDUCIDO */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mobile-results-header .header-info {
|
||||
display: flex; /* AÑADIDO */
|
||||
align-items: baseline; /* AÑADIDO */
|
||||
gap: 12px; /* AÑADIDO */
|
||||
}
|
||||
|
||||
.mobile-results-header .header-info h4 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* SELECTOR ESPECÍFICO PARA EL TEXTO DE ACCIÓN */
|
||||
.mobile-results-header .header-info .header-action-text {
|
||||
font-size: 0.8rem;
|
||||
color: #6c757d;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.mobile-results-header .header-toggle-icon {
|
||||
font-size: 1.5rem;
|
||||
color: #007bff;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.mobile-results-content {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease-in-out, opacity 0.3s ease-in-out, padding 0.3s ease-in-out;
|
||||
padding: 0 15px;
|
||||
border-top: 1px solid transparent;
|
||||
}
|
||||
|
||||
.mobile-results-card-container.expanded .mobile-results-content {
|
||||
max-height: 500px;
|
||||
opacity: 1;
|
||||
padding: 5px 15px 15px 15px;
|
||||
border-top-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.mobile-result-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
border-left: 4px solid;
|
||||
padding-left: 8px;
|
||||
}
|
||||
.mobile-result-row:last-child { border-bottom: none; }
|
||||
|
||||
.mobile-result-logo {
|
||||
flex-shrink: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.mobile-result-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.mobile-result-info { flex-grow: 1; min-width: 0; }
|
||||
.mobile-result-party-name { display: block; font-weight: 600; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.mobile-result-candidate-name { display: block; font-size: 0.75rem; color: #6c757d; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.mobile-result-stats { display: flex; flex-direction: column; align-items: flex-end; flex-shrink: 0; }
|
||||
.mobile-result-stats strong { font-size: 0.95rem; font-weight: 700; }
|
||||
.mobile-result-stats span { font-size: 0.7rem; color: #6c757d; }
|
||||
.no-results-text { padding: 1rem; text-align: center; color: #6c757d; font-size: 0.9rem; }
|
||||
|
||||
.mobile-card-view-toggle {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
background-color: rgba(230, 230, 230, 0.6);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.mobile-card-view-toggle .toggle-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 10px 15px; /* Aumentado para pantallas más grandes */
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
border-radius: 25px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem; /* Mantenido para pantallas más grandes */
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.mobile-card-view-toggle .toggle-btn.active {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
box-shadow: 0 2px 5px rgba(0, 123, 255, 0.2);
|
||||
}
|
||||
|
||||
/* Ajustes para pantallas pequeñas como el iPhone SE */
|
||||
@media (max-width: 380px) {
|
||||
.mobile-results-header {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.mobile-results-header .header-info h4 {
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase; /* Se achica el título */
|
||||
}
|
||||
|
||||
.mobile-results-header .header-info .header-action-text {
|
||||
font-size: 0.7rem; /* Se achica el texto de acción */
|
||||
}
|
||||
|
||||
.mobile-card-view-toggle .toggle-btn {
|
||||
padding: 6px 10px; /* Se reduce el padding de los botones */
|
||||
font-size: 0.8rem; /* Se achica la fuente de los botones */
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,130 @@
|
||||
// src/features/legislativas/nacionales/PanelNacionalWidget.tsx
|
||||
import { useMemo, useState, Suspense } from 'react';
|
||||
import { useMemo, useState, Suspense, useEffect } from 'react';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { getPanelElectoral } from '../../../apiService';
|
||||
import { MapaNacional } from './components/MapaNacional';
|
||||
import { PanelResultados } from './components/PanelResultados';
|
||||
import { Breadcrumbs } from './components/Breadcrumbs';
|
||||
import { MunicipioSearch } from './components/MunicipioSearch';
|
||||
import './PanelNacional.css';
|
||||
import Select from 'react-select';
|
||||
import type { PanelElectoralDto } from '../../../types/types';
|
||||
import { FiMap, FiList } from 'react-icons/fi';
|
||||
import type { PanelElectoralDto, ResultadoTicker } from '../../../types/types';
|
||||
import { FiMap, FiList, FiChevronDown, FiChevronUp } from 'react-icons/fi';
|
||||
import { useMediaQuery } from './hooks/useMediaQuery';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
import { ImageWithFallback } from '../../../components/common/ImageWithFallback';
|
||||
import { assetBaseUrl } from '../../../apiService';
|
||||
|
||||
// --- COMPONENTE INTERNO PARA LA TARJETA DE RESULTADOS EN MÓVIL ---
|
||||
interface MobileResultsCardProps {
|
||||
eleccionId: number;
|
||||
ambitoId: string | null;
|
||||
categoriaId: number;
|
||||
ambitoNombre: string;
|
||||
ambitoNivel: 'pais' | 'provincia' | 'municipio';
|
||||
}
|
||||
|
||||
const formatPercent = (num: number) => `${(num || 0).toFixed(2).replace('.', ',')}%`;
|
||||
|
||||
// --- SUB-COMPONENTE PARA UNA FILA DE RESULTADO ---
|
||||
const ResultRow = ({ partido }: { partido: ResultadoTicker }) => (
|
||||
<div className="mobile-result-row" style={{ borderLeftColor: partido.color || '#ccc' }}>
|
||||
<div className="mobile-result-logo" style={{ backgroundColor: partido.color || '#e9ecef' }}>
|
||||
<ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc={`${assetBaseUrl}/default-avatar.png`} alt={partido.nombre} />
|
||||
</div>
|
||||
<div className="mobile-result-info">
|
||||
{partido.nombreCandidato ? (
|
||||
<>
|
||||
<span className="mobile-result-party-name">{partido.nombreCandidato}</span>
|
||||
<span className="mobile-result-candidate-name">{partido.nombreCorto || partido.nombre}</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="mobile-result-party-name">{partido.nombreCorto || partido.nombre}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="mobile-result-stats">
|
||||
<strong>{formatPercent(partido.porcentaje)}</strong>
|
||||
<span>{partido.votos.toLocaleString('es-AR')}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
// --- COMPONENTE REFACTORIZADO PARA LA TARJETA MÓVIL ---
|
||||
interface MobileResultsCardProps {
|
||||
eleccionId: number;
|
||||
ambitoId: string | null;
|
||||
categoriaId: number;
|
||||
ambitoNombre: string;
|
||||
ambitoNivel: 'pais' | 'provincia' | 'municipio';
|
||||
mobileView: 'mapa' | 'resultados';
|
||||
setMobileView: (view: 'mapa' | 'resultados') => void;
|
||||
}
|
||||
|
||||
const MobileResultsCard = ({
|
||||
eleccionId, ambitoId, categoriaId, ambitoNombre, ambitoNivel, mobileView, setMobileView
|
||||
}: MobileResultsCardProps) => {
|
||||
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
|
||||
const { data } = useSuspenseQuery<PanelElectoralDto>({
|
||||
queryKey: ['panelElectoral', eleccionId, ambitoId, categoriaId],
|
||||
queryFn: () => getPanelElectoral(eleccionId, ambitoId, categoriaId),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setIsExpanded(ambitoNivel === 'municipio');
|
||||
}, [ambitoNivel]);
|
||||
|
||||
const topResults = data.resultadosPanel.slice(0, 4);
|
||||
|
||||
if (topResults.length === 0 && ambitoNivel === 'pais') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`mobile-results-card-container ${isExpanded ? 'expanded' : ''} view-${mobileView}`}>
|
||||
{/* Sección Colapsable con Resultados */}
|
||||
<div className="collapsible-section">
|
||||
<div className="mobile-results-header" onClick={() => setIsExpanded(!isExpanded)}>
|
||||
<div className="header-info">
|
||||
<h4>{ambitoNombre}</h4>
|
||||
{/* Se añade una clase para estilizar este texto específicamente */}
|
||||
<span className="header-action-text">{isExpanded ? 'Ocultar resultados' : 'Ver top 4'}</span>
|
||||
</div>
|
||||
<div className="header-toggle-icon">
|
||||
{isExpanded ? <FiChevronUp /> : <FiChevronDown />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mobile-results-content">
|
||||
{topResults.length > 0 ? (
|
||||
topResults.map(partido => <ResultRow key={partido.id} partido={partido} />)
|
||||
) : (
|
||||
<p className="no-results-text">No hay resultados para esta selección.</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer Fijo con Botones de Navegación */}
|
||||
<div className="mobile-card-view-toggle">
|
||||
<button
|
||||
className={`toggle-btn ${mobileView === 'mapa' ? 'active' : ''}`}
|
||||
onClick={() => setMobileView('mapa')}
|
||||
>
|
||||
<FiMap />
|
||||
<span>Mapa</span>
|
||||
</button>
|
||||
<button
|
||||
className={`toggle-btn ${mobileView === 'resultados' ? 'active' : ''}`}
|
||||
onClick={() => setMobileView('resultados')}
|
||||
>
|
||||
<FiList />
|
||||
<span>Resultados</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// --- WIDGET PRINCIPAL ---
|
||||
interface PanelNacionalWidgetProps {
|
||||
eleccionId: number;
|
||||
}
|
||||
@@ -42,7 +155,6 @@ export const PanelNacionalWidget = ({ eleccionId }: PanelNacionalWidgetProps) =>
|
||||
const [categoriaId, setCategoriaId] = useState<number>(2);
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(true);
|
||||
const [mobileView, setMobileView] = useState<'mapa' | 'resultados'>('mapa');
|
||||
// --- DETECCIÓN DE VISTA MÓVIL ---
|
||||
const isMobile = useMediaQuery('(max-width: 800px)');
|
||||
|
||||
const handleAmbitoSelect = (nuevoAmbitoId: string, nuevoNivel: 'provincia' | 'municipio', nuevoNombre: string) => {
|
||||
@@ -91,62 +203,55 @@ export const PanelNacionalWidget = ({ eleccionId }: PanelNacionalWidgetProps) =>
|
||||
classNamePrefix="categoria-selector"
|
||||
isSearchable={false}
|
||||
/>
|
||||
<Breadcrumbs
|
||||
nivel={ambitoActual.nivel}
|
||||
nombreAmbito={ambitoActual.nombre}
|
||||
nombreProvincia={ambitoActual.provinciaNombre}
|
||||
onReset={handleResetToPais}
|
||||
onVolverProvincia={handleVolverAProvincia}
|
||||
/>
|
||||
</div>
|
||||
{/* --- 2. NUEVO CONTENEDOR PARA BREADCRUMBS Y BUSCADOR --- */}
|
||||
<div className="header-bottom-row">
|
||||
<Breadcrumbs
|
||||
nivel={ambitoActual.nivel}
|
||||
nombreAmbito={ambitoActual.nombre}
|
||||
nombreProvincia={ambitoActual.provinciaNombre}
|
||||
onReset={handleResetToPais}
|
||||
onVolverProvincia={handleVolverAProvincia}
|
||||
/>
|
||||
{/* --- 3. RENDERIZADO CONDICIONAL DEL BUSCADOR --- */}
|
||||
{ambitoActual.nivel === 'provincia' && ambitoActual.provinciaDistritoId && (
|
||||
<MunicipioSearch
|
||||
distritoId={ambitoActual.provinciaDistritoId}
|
||||
onMunicipioSelect={(municipioId, municipioNombre) =>
|
||||
handleAmbitoSelect(municipioId, 'municipio', municipioNombre)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
<main className={`panel-main-content ${!isPanelOpen ? 'panel-collapsed' : ''} ${isMobile ? `mobile-view-${mobileView}` : ''}`}>
|
||||
<div className="mapa-column">
|
||||
<button className="panel-toggle-btn" onClick={() => setIsPanelOpen(!isPanelOpen)} title={isPanelOpen ? "Ocultar panel" : "Mostrar panel"}>
|
||||
{isPanelOpen ? '›' : '‹'}
|
||||
</button>
|
||||
<button className="panel-toggle-btn" onClick={() => setIsPanelOpen(!isPanelOpen)} title={isPanelOpen ? "Ocultar panel" : "Mostrar panel"}> {isPanelOpen ? '›' : '‹'} </button>
|
||||
|
||||
<Suspense fallback={<div className="spinner" />}>
|
||||
<MapaNacional
|
||||
eleccionId={eleccionId}
|
||||
categoriaId={categoriaId}
|
||||
nivel={ambitoActual.nivel}
|
||||
nombreAmbito={ambitoActual.nombre}
|
||||
nombreProvinciaActiva={ambitoActual.provinciaNombre}
|
||||
provinciaDistritoId={ambitoActual.provinciaDistritoId ?? null}
|
||||
onAmbitoSelect={handleAmbitoSelect}
|
||||
onVolver={ambitoActual.nivel === 'municipio' ? handleVolverAProvincia : handleResetToPais}
|
||||
isMobileView={isMobile}
|
||||
/>
|
||||
<MapaNacional eleccionId={eleccionId} categoriaId={categoriaId} nivel={ambitoActual.nivel} nombreAmbito={ambitoActual.nombre} nombreProvinciaActiva={ambitoActual.provinciaNombre} provinciaDistritoId={ambitoActual.provinciaDistritoId ?? null} onAmbitoSelect={handleAmbitoSelect} onVolver={ambitoActual.nivel === 'municipio' ? handleVolverAProvincia : handleResetToPais} isMobileView={isMobile} />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="resultados-column">
|
||||
<Suspense fallback={<div className="spinner" />}>
|
||||
<PanelContenido
|
||||
eleccionId={eleccionId}
|
||||
ambitoActual={ambitoActual}
|
||||
categoriaId={categoriaId}
|
||||
/>
|
||||
<PanelContenido eleccionId={eleccionId} ambitoActual={ambitoActual} categoriaId={categoriaId} />
|
||||
</Suspense>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/* --- NUEVO CONTROLADOR DE VISTA PARA MÓVIL --- */}
|
||||
<div className="mobile-view-toggle">
|
||||
<button
|
||||
className={`toggle-btn ${mobileView === 'mapa' ? 'active' : ''}`}
|
||||
onClick={() => setMobileView('mapa')}
|
||||
>
|
||||
<FiMap />
|
||||
<span>Mapa</span>
|
||||
</button>
|
||||
<button
|
||||
className={`toggle-btn ${mobileView === 'resultados' ? 'active' : ''}`}
|
||||
onClick={() => setMobileView('resultados')}
|
||||
>
|
||||
<FiList />
|
||||
<span>Resultados</span>
|
||||
</button>
|
||||
</div>
|
||||
<Suspense fallback={null}>
|
||||
{isMobile && (
|
||||
<MobileResultsCard
|
||||
eleccionId={eleccionId}
|
||||
ambitoId={ambitoActual.id}
|
||||
categoriaId={categoriaId}
|
||||
ambitoNombre={ambitoActual.nombre}
|
||||
ambitoNivel={ambitoActual.nivel}
|
||||
mobileView={mobileView}
|
||||
setMobileView={setMobileView}
|
||||
/>
|
||||
)}
|
||||
</Suspense>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -106,6 +106,10 @@
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.candidato-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.candidato-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -114,19 +118,24 @@
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
border-left: 5px solid; /* Grosor del borde */
|
||||
border-radius: 12px; /* Redondeamos las esquinas para un look más suave */
|
||||
padding-left: 1rem; /* Añadimos un poco de espacio a la izquierda */
|
||||
padding-left: 0.75rem; /* Añadimos un poco de espacio a la izquierda */
|
||||
}
|
||||
|
||||
.candidato-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.candidato-foto {
|
||||
/* Nuevo contenedor para el logo con fondo de color */
|
||||
.candidato-foto-wrapper {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 5%;
|
||||
object-fit: cover;
|
||||
border-radius: 12px;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
background-color: #e9ecef; /* Color de fallback */
|
||||
}
|
||||
|
||||
/* La imagen ahora llena su nuevo contenedor */
|
||||
.candidato-foto {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.candidato-data {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// src/features/legislativas/nacionales/components/MapaNacional.tsx
|
||||
import axios from 'axios';
|
||||
import { Suspense, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
@@ -12,6 +11,7 @@ import { MapaProvincial } from './MapaProvincial';
|
||||
import { CabaLupa } from './CabaLupa';
|
||||
import { BiZoomIn, BiZoomOut } from "react-icons/bi";
|
||||
import toast from 'react-hot-toast';
|
||||
import { useMediaQuery } from '../hooks/useMediaQuery';
|
||||
|
||||
const DEFAULT_MAP_COLOR = '#E0E0E0';
|
||||
const FADED_BACKGROUND_COLOR = '#F0F0F0';
|
||||
@@ -19,15 +19,21 @@ const normalizarTexto = (texto: string = '') => texto.trim().toUpperCase().norma
|
||||
|
||||
type PointTuple = [number, number];
|
||||
|
||||
const PROVINCE_VIEW_CONFIG: Record<string, { center: PointTuple; zoom: number }> = {
|
||||
"BUENOS AIRES": { center: [-60.5, -37.3], zoom: 5 },
|
||||
"SANTA CRUZ": { center: [-69.5, -49.3], zoom: 5 },
|
||||
"CIUDAD AUTONOMA DE BUENOS AIRES": { center: [-58.45, -34.6], zoom: 85 },
|
||||
"CHUBUT": { center: [-68.5, -44.5], zoom: 5.5 },
|
||||
"SANTA FE": { center: [-61, -31.2], zoom: 6 },
|
||||
"CORRIENTES": { center: [-58, -29], zoom: 7 },
|
||||
"RIO NEGRO": { center: [-67.5, -40], zoom: 5.5 },
|
||||
"TIERRA DEL FUEGO": { center: [-66.5, -54.2], zoom: 7 },
|
||||
interface ViewConfig {
|
||||
center: PointTuple;
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
const PROVINCE_VIEW_CONFIG: Record<string, { desktop: ViewConfig; mobile?: ViewConfig }> = {
|
||||
"BUENOS AIRES": { desktop: { center: [-60.5, -37.3], zoom: 5 }, mobile: { center: [-60, -38], zoom: 5.5 } },
|
||||
"SANTA CRUZ": { desktop: { center: [-69.5, -49.3], zoom: 5 }, mobile: { center: [-69.5, -50], zoom: 4 } },
|
||||
"CIUDAD AUTONOMA DE BUENOS AIRES": { desktop: { center: [-58.44, -34.65], zoom: 150 } },
|
||||
"CHUBUT": { desktop: { center: [-68.5, -44.5], zoom: 5.5 }, mobile: { center: [-68, -44.5], zoom: 4.5 } },
|
||||
"SANTA FE": { desktop: { center: [-61, -31.2], zoom: 6 }, mobile: { center: [-61, -31.5], zoom: 7.5 } },
|
||||
"CORRIENTES": { desktop: { center: [-58, -29], zoom: 7 }, mobile: { center: [-57.5, -28.8], zoom: 9 } },
|
||||
"RIO NEGRO": { desktop: { center: [-67.5, -40], zoom: 5.5 }, mobile: { center: [-67.5, -40], zoom: 4.3 } },
|
||||
"SALTA": { desktop: { center: [-64.5, -24], zoom: 7 }, mobile: { center: [-65.5, -24.5], zoom: 6 } },
|
||||
"TIERRA DEL FUEGO": { desktop: { center: [-66.5, -54.2], zoom: 7 }, mobile: { center: [-66, -54], zoom: 7.5 } },
|
||||
};
|
||||
|
||||
const LUPA_SIZE_RATIO = 0.2;
|
||||
@@ -48,15 +54,20 @@ interface MapaNacionalProps {
|
||||
|
||||
// --- CONFIGURACIONES DEL MAPA ---
|
||||
const desktopProjectionConfig = { scale: 700, center: [-65, -40] as [number, number] };
|
||||
const mobileProjectionConfig = { scale: 1100, center: [-64, -41] as [number, number] };
|
||||
const mobileProjectionConfig = { scale: 1100, center: [-64, -42.5] as [number, number] };
|
||||
// --- LÍNEA A CALIBRAR ---
|
||||
const mobileSmallProjectionConfig = { scale: 900, center: [-64, -43] as [number, number] };
|
||||
|
||||
|
||||
export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nombreProvinciaActiva, provinciaDistritoId, onAmbitoSelect, onVolver, isMobileView }: MapaNacionalProps) => {
|
||||
const isMobileSmall = useMediaQuery('(max-width: 380px)');
|
||||
|
||||
const [position, setPosition] = useState({
|
||||
zoom: isMobileView ? 1.5 : 1.05, // 1.5 para móvil, 1.05 para desktop
|
||||
center: [-65, -40] as PointTuple
|
||||
zoom: isMobileView ? 1.5 : 1.05,
|
||||
center: isMobileView ? mobileProjectionConfig.center : desktopProjectionConfig.center as PointTuple
|
||||
});
|
||||
const [isPanning, setIsPanning] = useState(false);
|
||||
const initialProvincePositionRef = useRef<{ zoom: number, center: PointTuple } | null>(null);
|
||||
const initialProvincePositionRef = useRef<ViewConfig | null>(null);
|
||||
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const lupaRef = useRef<HTMLDivElement | null>(null);
|
||||
@@ -82,32 +93,38 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom
|
||||
|
||||
useEffect(() => {
|
||||
if (nivel === 'pais') {
|
||||
const currentMobileConfig = isMobileSmall ? mobileSmallProjectionConfig : mobileProjectionConfig;
|
||||
const currentMobileZoom = isMobileSmall ? 1.4 : 1.5;
|
||||
|
||||
setPosition({
|
||||
zoom: isMobileView ? 1.4 : 1.05,
|
||||
center: [-65, -40]
|
||||
zoom: isMobileView ? currentMobileZoom : 1.05,
|
||||
center: isMobileView ? currentMobileConfig.center : desktopProjectionConfig.center
|
||||
});
|
||||
initialProvincePositionRef.current = null;
|
||||
} else if (nivel === 'provincia') {
|
||||
const nombreNormalizado = normalizarTexto(nombreAmbito);
|
||||
const manualConfig = PROVINCE_VIEW_CONFIG[nombreNormalizado];
|
||||
|
||||
let provinceConfig = { zoom: 7, center: [-65, -40] as PointTuple };
|
||||
|
||||
let provinceConfig: ViewConfig | undefined;
|
||||
|
||||
if (manualConfig) {
|
||||
provinceConfig = manualConfig;
|
||||
provinceConfig = (isMobileView && manualConfig.mobile) ? manualConfig.mobile : manualConfig.desktop;
|
||||
} else {
|
||||
const provinciaGeo = geoDataNacional.objects.provincias.geometries.find((g: any) => normalizarTexto(g.properties.nombre) === nombreNormalizado);
|
||||
if (provinciaGeo) {
|
||||
const provinciaFeature = feature(geoDataNacional, provinciaGeo);
|
||||
const centroid = geoCentroid(provinciaFeature);
|
||||
provinceConfig = { zoom: 7, center: centroid as PointTuple };
|
||||
provinceConfig = { zoom: isMobileView ? 8 : 7, center: centroid as PointTuple };
|
||||
}
|
||||
}
|
||||
|
||||
setPosition(provinceConfig);
|
||||
initialProvincePositionRef.current = provinceConfig;
|
||||
if (provinceConfig) {
|
||||
setPosition(provinceConfig);
|
||||
initialProvincePositionRef.current = provinceConfig;
|
||||
}
|
||||
}
|
||||
}, [nivel, nombreAmbito, geoDataNacional, isMobileView]);
|
||||
}, [nivel, nombreAmbito, geoDataNacional, isMobileView, isMobileSmall]);
|
||||
|
||||
|
||||
const resultadosNacionalesPorNombre = new Map<string, ResultadoMapaDto>(mapaDataNacional.map(d => [normalizarTexto(d.ambitoNombre), d]));
|
||||
const nombreMunicipioSeleccionado = nivel === 'municipio' ? nombreAmbito : null;
|
||||
@@ -173,14 +190,9 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom
|
||||
position.zoom > initialProvincePositionRef.current.zoom &&
|
||||
!nombreMunicipioSeleccionado;
|
||||
|
||||
// --- INICIO DE LA CORRECCIÓN ---
|
||||
|
||||
const handleZoomIn = () => {
|
||||
// Solo mostramos la notificación si el paneo NO está ya habilitado
|
||||
if (!panEnabled && initialProvincePositionRef.current) {
|
||||
// Calculamos cuál será el nuevo nivel de zoom
|
||||
const newZoom = position.zoom * 1.8;
|
||||
// Si el nuevo zoom supera el umbral inicial, activamos la notificación
|
||||
if (newZoom > initialProvincePositionRef.current.zoom) {
|
||||
toast.success('Desplazamiento Habilitado', {
|
||||
icon: '🖐️',
|
||||
@@ -193,10 +205,8 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom
|
||||
};
|
||||
|
||||
const handleZoomOut = () => {
|
||||
// Solo mostramos la notificación si el paneo SÍ está habilitado actualmente
|
||||
if (panEnabled && initialProvincePositionRef.current) {
|
||||
const newZoom = position.zoom / 1.8;
|
||||
// Si el nuevo zoom es igual o menor al umbral, desactivamos
|
||||
if (newZoom <= initialProvincePositionRef.current.zoom) {
|
||||
toast.error('Desplazamiento Deshabilitado', {
|
||||
icon: '🔒',
|
||||
@@ -205,7 +215,6 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom
|
||||
});
|
||||
}
|
||||
}
|
||||
// La lógica para actualizar la posición no cambia
|
||||
setPosition(prev => {
|
||||
const newZoom = Math.max(prev.zoom / 1.8, 1);
|
||||
const initialPos = initialProvincePositionRef.current;
|
||||
@@ -254,7 +263,7 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom
|
||||
<div className="mapa-render-area">
|
||||
<ComposableMap
|
||||
projection="geoMercator"
|
||||
projectionConfig={isMobileView ? mobileProjectionConfig : desktopProjectionConfig}
|
||||
projectionConfig={isMobileSmall ? mobileSmallProjectionConfig : (isMobileView ? mobileProjectionConfig : desktopProjectionConfig)}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
<ZoomableGroup
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// src/features/legislativas/nacionales/components/MunicipioSearch.tsx
|
||||
import { useState } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import Select, { type SingleValue } from 'react-select';
|
||||
import { getMunicipiosPorDistrito } from '../../../../apiService';
|
||||
import type { CatalogoItem } from '../../../../types/types';
|
||||
|
||||
interface MunicipioSearchProps {
|
||||
distritoId: string;
|
||||
onMunicipioSelect: (municipioId: string, municipioNombre: string) => void;
|
||||
}
|
||||
|
||||
interface OptionType {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const customSelectStyles = {
|
||||
control: (base: any) => ({
|
||||
...base,
|
||||
borderRadius: '8px',
|
||||
borderColor: '#e0e0e0',
|
||||
boxShadow: 'none',
|
||||
'&:hover': { borderColor: '#007bff' }
|
||||
}),
|
||||
menu: (base: any) => ({
|
||||
...base,
|
||||
borderRadius: '8px',
|
||||
zIndex: 30
|
||||
})
|
||||
};
|
||||
|
||||
export const MunicipioSearch = ({ distritoId, onMunicipioSelect }: MunicipioSearchProps) => {
|
||||
const [selectedOption, setSelectedOption] = useState<SingleValue<OptionType>>(null);
|
||||
|
||||
const { data: municipios = [], isLoading } = useQuery<CatalogoItem[]>({
|
||||
queryKey: ['municipiosPorDistrito', distritoId],
|
||||
queryFn: () => getMunicipiosPorDistrito(distritoId),
|
||||
enabled: !!distritoId,
|
||||
});
|
||||
|
||||
const options: OptionType[] = municipios.map(m => ({
|
||||
value: m.id,
|
||||
label: m.nombre
|
||||
}));
|
||||
|
||||
const handleChange = (selected: SingleValue<OptionType>) => {
|
||||
if (selected) {
|
||||
onMunicipioSelect(selected.value, selected.label);
|
||||
setSelectedOption(null); // Resetea el selector para que muestre el placeholder de nuevo
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="municipio-search-container">
|
||||
<Select
|
||||
options={options}
|
||||
onChange={handleChange}
|
||||
value={selectedOption}
|
||||
isLoading={isLoading}
|
||||
placeholder="Buscar municipio..."
|
||||
isClearable
|
||||
isSearchable
|
||||
styles={customSelectStyles}
|
||||
noOptionsMessage={() => 'No se encontraron municipios'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -12,7 +12,6 @@ const formatVotes = (num: number) => Math.round(num).toLocaleString('es-AR');
|
||||
const SvgDefs = () => (
|
||||
<svg style={{ height: 0, width: 0, position: 'absolute' }}>
|
||||
<defs>
|
||||
{/* El gradiente ahora se define para que el color oscuro se mantenga en la segunda mitad del recorrido vertical */}
|
||||
<linearGradient id="participationGradient" gradientTransform="rotate(90)">
|
||||
<stop offset="0%" stopColor="#e0f3ffff" />
|
||||
<stop offset="100%" stopColor="#007bff" />
|
||||
@@ -40,13 +39,13 @@ export const PanelResultados = ({ resultados, estadoRecuento }: PanelResultadosP
|
||||
value={estadoRecuento.participacionPorcentaje}
|
||||
text={formatPercent(estadoRecuento.participacionPorcentaje)}
|
||||
strokeWidth={12}
|
||||
circleRatio={0.75} /* Se convierte en un arco de 270 grados */
|
||||
circleRatio={0.75}
|
||||
styles={buildStyles({
|
||||
textColor: '#333',
|
||||
pathColor: 'url(#participationGradient)',
|
||||
trailColor: '#e9ecef',
|
||||
textSize: '22px',
|
||||
rotation: 0.625, /* Rota el inicio para que la apertura quede abajo */
|
||||
rotation: 0.625,
|
||||
})}
|
||||
/>
|
||||
<span>Participación</span>
|
||||
@@ -56,13 +55,13 @@ export const PanelResultados = ({ resultados, estadoRecuento }: PanelResultadosP
|
||||
value={estadoRecuento.mesasTotalizadasPorcentaje}
|
||||
text={formatPercent(estadoRecuento.mesasTotalizadasPorcentaje)}
|
||||
strokeWidth={12}
|
||||
circleRatio={0.75} /* Se convierte en un arco de 270 grados */
|
||||
circleRatio={0.75}
|
||||
styles={buildStyles({
|
||||
textColor: '#333',
|
||||
pathColor: 'url(#scrutinizedGradient)',
|
||||
trailColor: '#e9ecef',
|
||||
textSize: '22px',
|
||||
rotation: 0.625, /* Rota el inicio para que la apertura quede abajo */
|
||||
rotation: 0.625,
|
||||
})}
|
||||
/>
|
||||
<span>Escrutado</span>
|
||||
@@ -76,7 +75,7 @@ export const PanelResultados = ({ resultados, estadoRecuento }: PanelResultadosP
|
||||
className="partido-fila"
|
||||
style={{ borderLeftColor: partido.color || '#ccc' }}
|
||||
>
|
||||
<div className="partido-logo">
|
||||
<div className="partido-logo" style={{ backgroundColor: partido.color || '#e9ecef' }}>
|
||||
<ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc={`${assetBaseUrl}/default-avatar.png`} alt={partido.nombre} />
|
||||
</div>
|
||||
<div className="partido-main-content">
|
||||
|
||||
@@ -4,7 +4,6 @@ import { MiniMapaSvg } from './MiniMapaSvg';
|
||||
import { ImageWithFallback } from '../../../../components/common/ImageWithFallback';
|
||||
import { assetBaseUrl } from '../../../../apiService';
|
||||
|
||||
// --- 1. AÑADIR LA PROP A AMBAS INTERFACES ---
|
||||
interface CategoriaDisplayProps {
|
||||
categoria: CategoriaResumen;
|
||||
mostrarBancas?: boolean;
|
||||
@@ -18,7 +17,6 @@ interface ProvinciaCardProps {
|
||||
const formatNumber = (num: number) => num.toLocaleString('es-AR');
|
||||
const formatPercent = (num: number) => `${num.toFixed(2).replace('.', ',')}%`;
|
||||
|
||||
// --- 2. RECIBIR Y USAR LA PROP EN EL SUB-COMPONENTE ---
|
||||
const CategoriaDisplay = ({ categoria, mostrarBancas }: CategoriaDisplayProps) => {
|
||||
return (
|
||||
<div className="categoria-bloque">
|
||||
@@ -30,20 +28,26 @@ const CategoriaDisplay = ({ categoria, mostrarBancas }: CategoriaDisplayProps) =
|
||||
className="candidato-row"
|
||||
style={{ borderLeftColor: res.color || '#ccc' }}
|
||||
>
|
||||
<ImageWithFallback
|
||||
src={res.fotoUrl ?? undefined}
|
||||
fallbackSrc={`${assetBaseUrl}/default-avatar.png`}
|
||||
alt={res.nombreCandidato ?? res.nombreAgrupacion}
|
||||
className="candidato-foto"
|
||||
/>
|
||||
{/* --- INICIO DE LA MODIFICACIÓN --- */}
|
||||
<div className="candidato-foto-wrapper" style={{ backgroundColor: res.color || '#e9ecef' }}>
|
||||
<ImageWithFallback
|
||||
src={res.fotoUrl ?? undefined}
|
||||
fallbackSrc={`${assetBaseUrl}/default-avatar.png`}
|
||||
alt={res.nombreCandidato ?? res.nombreAgrupacion}
|
||||
className="candidato-foto"
|
||||
/>
|
||||
</div>
|
||||
{/* --- FIN DE LA MODIFICACIÓN --- */}
|
||||
|
||||
<div className="candidato-data">
|
||||
{res.nombreCandidato && (
|
||||
<span className="candidato-nombre">{res.nombreCandidato}</span>
|
||||
{res.nombreCandidato ? (
|
||||
<>
|
||||
<span className="candidato-nombre">{res.nombreCandidato}</span>
|
||||
<span className="candidato-partido">{res.nombreCortoAgrupacion || res.nombreAgrupacion}</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="candidato-nombre">{res.nombreCortoAgrupacion || res.nombreAgrupacion}</span>
|
||||
)}
|
||||
<span className={`candidato-partido ${!res.nombreCandidato ? 'main-title' : ''}`}>
|
||||
{res.nombreAgrupacion}
|
||||
</span>
|
||||
<div className="progress-bar-container">
|
||||
<div className="progress-bar" style={{ width: `${res.porcentaje}%`, backgroundColor: res.color || '#ccc' }} />
|
||||
</div>
|
||||
@@ -53,8 +57,6 @@ const CategoriaDisplay = ({ categoria, mostrarBancas }: CategoriaDisplayProps) =
|
||||
<span className="stats-votos">{formatNumber(res.votos)} votos</span>
|
||||
</div>
|
||||
|
||||
{/* --- 3. RENDERIZADO CONDICIONAL DEL CUADRO DE BANCAS --- */}
|
||||
{/* Este div solo se renderizará si mostrarBancas es true */}
|
||||
{mostrarBancas && (
|
||||
<div className="stats-bancas">
|
||||
+{res.bancasObtenidas}
|
||||
@@ -82,7 +84,6 @@ const CategoriaDisplay = ({ categoria, mostrarBancas }: CategoriaDisplayProps) =
|
||||
);
|
||||
};
|
||||
|
||||
// --- 4. RECIBIR Y PASAR LA PROP EN EL COMPONENTE PRINCIPAL ---
|
||||
export const ProvinciaCard = ({ data, mostrarBancas }: ProvinciaCardProps) => {
|
||||
const colorGanador = data.categorias[0]?.resultados[0]?.color || '#d1d1d1';
|
||||
|
||||
@@ -101,7 +102,7 @@ export const ProvinciaCard = ({ data, mostrarBancas }: ProvinciaCardProps) => {
|
||||
<CategoriaDisplay
|
||||
key={categoria.categoriaId}
|
||||
categoria={categoria}
|
||||
mostrarBancas={mostrarBancas} // Pasar la prop hacia abajo
|
||||
mostrarBancas={mostrarBancas}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -175,4 +175,20 @@ public class CatalogosController : ControllerBase
|
||||
|
||||
return Ok(establecimientos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene la lista de municipios (partidos) para un distrito (provincia) específico.
|
||||
/// </summary>
|
||||
[HttpGet("municipios-por-distrito/{distritoId}")]
|
||||
public async Task<IActionResult> GetMunicipiosPorDistrito(string distritoId)
|
||||
{
|
||||
var municipios = await _dbContext.AmbitosGeograficos
|
||||
.AsNoTracking()
|
||||
.Where(a => a.NivelId == 30 && a.DistritoId == distritoId) // Nivel 30 = Municipio
|
||||
.OrderBy(a => a.Nombre)
|
||||
.Select(a => new { Id = a.Id.ToString(), a.Nombre }) // Devolvemos el ID de la BD como string
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(municipios);
|
||||
}
|
||||
}
|
||||
@@ -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+11d9417ef5e3645d51c0ab227a0804985db4b1fb")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1719e79723abcbe8891a67b4d447a068c41d9e57")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["VUEzgM3q00ehIicPw1uM8REVOid2zDpFbcwF9rvWytQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","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=","s3VnfR5av25jQd9RIy\u002BMwczWKx/CJRSzFdhJAMaIN9k=","A\u002BWemDKn7UwHxqDXzVs57jXOqpea86CLYpxVWDzRnDo=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","jAqiyVzpgWGABD/mtww8iBZneRW/QcFx5ww\u002BXozPGx4="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","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=","vsmxP35\u002Bq1R\u002BcAPfM\u002BIO\u002BoslwbDP4hbd6She759q5LA=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","S9x8x/B4N6vR0ZrYr6IZmcOPJCnhEdxrhESZuZWdF1A="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["VUEzgM3q00ehIicPw1uM8REVOid2zDpFbcwF9rvWytQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","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=","s3VnfR5av25jQd9RIy\u002BMwczWKx/CJRSzFdhJAMaIN9k=","A\u002BWemDKn7UwHxqDXzVs57jXOqpea86CLYpxVWDzRnDo=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","jAqiyVzpgWGABD/mtww8iBZneRW/QcFx5ww\u002BXozPGx4="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","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=","vsmxP35\u002Bq1R\u002BcAPfM\u002BIO\u002BoslwbDP4hbd6She759q5LA=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","S9x8x/B4N6vR0ZrYr6IZmcOPJCnhEdxrhESZuZWdF1A="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["VUEzgM3q00ehIicPw1uM8REVOid2zDpFbcwF9rvWytQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -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+11d9417ef5e3645d51c0ab227a0804985db4b1fb")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1719e79723abcbe8891a67b4d447a068c41d9e57")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -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+11d9417ef5e3645d51c0ab227a0804985db4b1fb")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1719e79723abcbe8891a67b4d447a068c41d9e57")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -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+3b0eee25e6441da1831442a90b6552cc8ef59d07")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1719e79723abcbe8891a67b4d447a068c41d9e57")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -14,7 +14,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Worker")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3a8f64bf854b2bdf66d83e503aaacc7dca77138e")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1719e79723abcbe8891a67b4d447a068c41d9e57")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
Reference in New Issue
Block a user