import { create } from 'zustand' import { persist, createJSONStorage } from 'zustand/middleware' import { Coordenadas, MapaEstado, Geocerca, POI, VehiculoEstado, VehiculoMovimiento, VehiculoTipo, } from '@/types' interface MapaStoreState { // Map state centro: Coordenadas zoom: number bounds: { north: number; south: number; east: number; west: number } | null // Selection vehiculoSeleccionado: string | null geocercaSeleccionada: string | null poiSeleccionado: string | null // Filters filtros: { estados: VehiculoEstado[] movimientos: VehiculoMovimiento[] tipos: VehiculoTipo[] grupos: string[] } // Layers visibility capas: { vehiculos: boolean geocercas: boolean pois: boolean trafico: boolean rutas: boolean labels: boolean } // Drawing herramienta: 'seleccionar' | 'medir' | 'dibujar_circulo' | 'dibujar_poligono' | null dibujando: boolean puntosDibujo: Coordenadas[] // Data (cached for map display) geocercas: Geocerca[] pois: POI[] // Map style estilo: 'dark' | 'light' | 'satellite' // Following vehicle siguiendoVehiculo: string | null // Actions setCentro: (centro: Coordenadas) => void setZoom: (zoom: number) => void setBounds: (bounds: { north: number; south: number; east: number; west: number } | null) => void setView: (centro: Coordenadas, zoom: number) => void fitBounds: (bounds: { north: number; south: number; east: number; west: number }) => void setVehiculoSeleccionado: (id: string | null) => void setGeocercaSeleccionada: (id: string | null) => void setPoiSeleccionado: (id: string | null) => void setFiltros: (filtros: Partial) => void toggleFiltro: ( key: K, value: MapaStoreState['filtros'][K][number] ) => void resetFiltros: () => void setCapa: (capa: keyof MapaStoreState['capas'], visible: boolean) => void toggleCapa: (capa: keyof MapaStoreState['capas']) => void setHerramienta: (herramienta: MapaStoreState['herramienta']) => void startDibujo: () => void addPuntoDibujo: (punto: Coordenadas) => void removePuntoDibujo: (index: number) => void finishDibujo: () => void cancelDibujo: () => void setGeocercas: (geocercas: Geocerca[]) => void setPois: (pois: POI[]) => void setEstilo: (estilo: MapaStoreState['estilo']) => void setSiguiendoVehiculo: (id: string | null) => void // Utils centrarEnVehiculo: (lat: number, lng: number) => void centrarEnGeocerca: (geocerca: Geocerca) => void } const defaultFiltros = { estados: [] as VehiculoEstado[], movimientos: [] as VehiculoMovimiento[], tipos: [] as VehiculoTipo[], grupos: [] as string[], } const defaultCapas = { vehiculos: true, geocercas: true, pois: true, trafico: false, rutas: false, labels: true, } // Default center (Mexico City) const defaultCentro: Coordenadas = { lat: 19.4326, lng: -99.1332 } export const useMapaStore = create()( persist( (set, get) => ({ centro: defaultCentro, zoom: 12, bounds: null, vehiculoSeleccionado: null, geocercaSeleccionada: null, poiSeleccionado: null, filtros: defaultFiltros, capas: defaultCapas, herramienta: null, dibujando: false, puntosDibujo: [], geocercas: [], pois: [], estilo: 'dark', siguiendoVehiculo: null, setCentro: (centro) => set({ centro }), setZoom: (zoom) => set({ zoom }), setBounds: (bounds) => set({ bounds }), setView: (centro, zoom) => set({ centro, zoom }), fitBounds: (bounds) => set({ bounds }), setVehiculoSeleccionado: (id) => set({ vehiculoSeleccionado: id, geocercaSeleccionada: null, poiSeleccionado: null, }), setGeocercaSeleccionada: (id) => set({ geocercaSeleccionada: id, vehiculoSeleccionado: null, poiSeleccionado: null, }), setPoiSeleccionado: (id) => set({ poiSeleccionado: id, vehiculoSeleccionado: null, geocercaSeleccionada: null, }), setFiltros: (filtros) => set((state) => ({ filtros: { ...state.filtros, ...filtros }, })), toggleFiltro: (key, value) => set((state) => { const current = state.filtros[key] as unknown[] const newValues = current.includes(value) ? current.filter((v) => v !== value) : [...current, value] return { filtros: { ...state.filtros, [key]: newValues }, } }), resetFiltros: () => set({ filtros: defaultFiltros }), setCapa: (capa, visible) => set((state) => ({ capas: { ...state.capas, [capa]: visible }, })), toggleCapa: (capa) => set((state) => ({ capas: { ...state.capas, [capa]: !state.capas[capa] }, })), setHerramienta: (herramienta) => set({ herramienta, dibujando: false, puntosDibujo: [], }), startDibujo: () => set({ dibujando: true, puntosDibujo: [] }), addPuntoDibujo: (punto) => set((state) => ({ puntosDibujo: [...state.puntosDibujo, punto], })), removePuntoDibujo: (index) => set((state) => ({ puntosDibujo: state.puntosDibujo.filter((_, i) => i !== index), })), finishDibujo: () => set({ dibujando: false, herramienta: null, }), cancelDibujo: () => set({ dibujando: false, puntosDibujo: [], herramienta: null, }), setGeocercas: (geocercas) => set({ geocercas }), setPois: (pois) => set({ pois }), setEstilo: (estilo) => set({ estilo }), setSiguiendoVehiculo: (id) => set({ siguiendoVehiculo: id }), centrarEnVehiculo: (lat, lng) => set({ centro: { lat, lng }, zoom: 16, }), centrarEnGeocerca: (geocerca) => { if (geocerca.tipo === 'circulo' && geocerca.centroLat && geocerca.centroLng) { set({ centro: { lat: geocerca.centroLat, lng: geocerca.centroLng }, zoom: 14, }) } else if (geocerca.vertices && geocerca.vertices.length > 0) { // Calculate center of polygon const lats = geocerca.vertices.map((v) => v.lat) const lngs = geocerca.vertices.map((v) => v.lng) const centerLat = (Math.max(...lats) + Math.min(...lats)) / 2 const centerLng = (Math.max(...lngs) + Math.min(...lngs)) / 2 set({ centro: { lat: centerLat, lng: centerLng }, zoom: 14, }) } }, }), { name: 'flotillas-mapa', storage: createJSONStorage(() => localStorage), partialize: (state) => ({ centro: state.centro, zoom: state.zoom, capas: state.capas, estilo: state.estilo, }), } ) )