Feat Widgets Controles y Estilos
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user