Preparación Legislativas Nacionales 2025
This commit is contained in:
		| @@ -0,0 +1,82 @@ | ||||
| // src/features/legislativas/nacionales/components/MapaProvincial.tsx | ||||
| import axios from 'axios'; | ||||
| import { useEffect } from 'react'; | ||||
| import { useSuspenseQuery } from '@tanstack/react-query'; | ||||
| import { Geographies, Geography } from 'react-simple-maps'; | ||||
| import { geoCentroid } from 'd3-geo'; | ||||
| import { feature } from 'topojson-client'; | ||||
| import { API_BASE_URL, assetBaseUrl } from '../../../../apiService'; | ||||
| import type { ResultadoMapaDto, AmbitoGeography } from '../../../../types/types'; | ||||
|  | ||||
| const DEFAULT_MAP_COLOR = '#E0E0E0'; | ||||
| const normalizarTexto = (texto: string = ''): string => texto.trim().toUpperCase().normalize("NFD").replace(/[\u0300-\u036f]/g, ""); | ||||
| type PointTuple = [number, number]; | ||||
|  | ||||
| interface MapaProvincialProps { | ||||
|   eleccionId: number; | ||||
|   categoriaId: number; | ||||
|   distritoId: string; | ||||
|   nombreProvincia: string; | ||||
|   nombreMunicipioSeleccionado: string | null; | ||||
|   nivel: 'provincia' | 'municipio'; | ||||
|   onMunicipioSelect: (ambitoId: string, nombre: string) => void; | ||||
|   onCalculatedCenter: (center: PointTuple, zoom: number) => void; | ||||
| } | ||||
|  | ||||
| export const MapaProvincial = ({ eleccionId, categoriaId, distritoId, nombreProvincia, nombreMunicipioSeleccionado, nivel, onMunicipioSelect, onCalculatedCenter }: MapaProvincialProps) => { | ||||
|   const { data: mapaData = [] } = useSuspenseQuery<ResultadoMapaDto[]>({ | ||||
|     queryKey: ['mapaResultados', eleccionId, categoriaId, distritoId], | ||||
|     queryFn: async () => { | ||||
|       const url = `${API_BASE_URL}/elecciones/${eleccionId}/mapa-resultados?categoriaId=${categoriaId}&distritoId=${distritoId}`; | ||||
|       const response = await axios.get(url); | ||||
|       return response.data; | ||||
|     }, | ||||
|   }); | ||||
|    | ||||
|   // El nombre del archivo ahora es completamente dinámico | ||||
|   const { data: geoData } = useSuspenseQuery<any>({ | ||||
|     queryKey: ['geoDataProvincial', nombreProvincia], | ||||
|     queryFn: async () => { | ||||
|       const nombreNormalizado = nombreProvincia.toLowerCase().replace(/ /g, '_'); | ||||
|       const mapFile = `departamentos-${nombreNormalizado}.topojson`; | ||||
|       return axios.get(`${assetBaseUrl}/maps/${mapFile}`).then(res => res.data); | ||||
|     }, | ||||
|   }); | ||||
|  | ||||
|   // useEffect para calcular y "exportar" la posición del municipio al padre | ||||
|   useEffect(() => { | ||||
|     if (nivel === 'municipio' && geoData?.objects && nombreMunicipioSeleccionado) { | ||||
|       const geometries = geoData.objects[Object.keys(geoData.objects)[0]].geometries; | ||||
|       const municipioGeo = geometries.find((g: any) => normalizarTexto(g.properties.departamento) === normalizarTexto(nombreMunicipioSeleccionado)); | ||||
|       if (municipioGeo) { | ||||
|           const municipioFeature = feature(geoData, municipioGeo); | ||||
|           const centroid = geoCentroid(municipioFeature); | ||||
|           // Usamos un zoom genérico alto para cualquier municipio | ||||
|           onCalculatedCenter(centroid as PointTuple, 40); | ||||
|       } | ||||
|     } | ||||
|   }, [nivel, nombreMunicipioSeleccionado, geoData, onCalculatedCenter]); | ||||
|  | ||||
|   const resultadosPorNombre = new Map<string, ResultadoMapaDto>(mapaData.map(d => [normalizarTexto(d.ambitoNombre), d])); | ||||
|  | ||||
|   return ( | ||||
|     <Geographies geography={geoData}> | ||||
|       {({ geographies }: { geographies: AmbitoGeography[] }) => geographies.map((geo) => { | ||||
|         const resultado = resultadosPorNombre.get(normalizarTexto(geo.properties.departamento)); | ||||
|         const esSeleccionado = nombreMunicipioSeleccionado ? normalizarTexto(geo.properties.departamento) === normalizarTexto(nombreMunicipioSeleccionado) : false; | ||||
|  | ||||
|         return ( | ||||
|           <Geography | ||||
|             key={geo.rsmKey} | ||||
|             geography={geo} | ||||
|             className={`rsm-geography ${esSeleccionado ? 'selected' : ''} ${nombreMunicipioSeleccionado && !esSeleccionado ? 'rsm-geography-faded-municipality' : ''}`} | ||||
|             fill={resultado?.colorGanador || DEFAULT_MAP_COLOR} | ||||
|             onClick={resultado ? () => onMunicipioSelect(resultado.ambitoId.toString(), resultado.ambitoNombre) : undefined} | ||||
|             data-tooltip-id="mapa-tooltip" | ||||
|             data-tooltip-content={geo.properties.departamento} | ||||
|           /> | ||||
|         ); | ||||
|       })} | ||||
|     </Geographies> | ||||
|   ); | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user