diff --git a/src/components/maps/GlobalMap.tsx b/src/components/maps/GlobalMap.tsx index 663952a05..ca918e979 100644 --- a/src/components/maps/GlobalMap.tsx +++ b/src/components/maps/GlobalMap.tsx @@ -213,6 +213,26 @@ export const GlobalMap: React.FC = ({ } }, [mapInstance, isSourceLoaded, initialAreaId, findAreaById]) + const [allCrags, setAllCrags] = useState([]) + useEffect(() => { + if (!mapInstance) return + const features = mapInstance.querySourceFeatures('crags', { sourceLayer: 'crags' }) + const cragsFeatures = features + .map(f => tileToFeature('crag-name-labels', {x:0,y:0}, f.geometry, f.properties as TileProps, mapInstance)) + .filter((f): f is ActiveFeature => f !== null) // фильтруем null и сохраняем тип + setAllCrags(cragsFeatures) + }, [mapInstance]) + + const highlightCrag = (crag: ActiveFeature) => { + setClickInfo(prev => { + if (prev) setActiveFeatureVisual(prev, { selected: false, hover: false }) + setActiveFeatureVisual(crag, { selected: true, hover: false }) + return crag + }) + const [lng, lat] = crag.geometry.coordinates as [number, number] + mapInstance?.flyTo({ center: [lng, lat], zoom: 15 }) + } + return (
= ({ cooperativeGestures={showFullscreenControl} interactiveLayerIds={['crag-markers', 'crag-name-labels', 'area-boundaries', 'organizations']} > - + @@ -262,3 +287,4 @@ export const LazyGlobalMap = dynamic(async () => await import('. module => module.GlobalMap), { ssr: false }) + diff --git a/src/components/maps/MapToolbar.tsx b/src/components/maps/MapToolbar.tsx index 0f4d0f4de..036aef5e2 100644 --- a/src/components/maps/MapToolbar.tsx +++ b/src/components/maps/MapToolbar.tsx @@ -1,19 +1,42 @@ -import { ChangeEventHandler } from 'react' +import { ChangeEventHandler, ChangeEvent, useState } from 'react' import { DataLayersDisplayState } from './GlobalMap' +import { ActiveFeature } from './TileTypes' -export interface MapToolbarProps { +interface MapToolbarProps { layerState: DataLayersDisplayState onChange: (newLayerState: DataLayersDisplayState) => void + cragsList: ActiveFeature[] + onSelectCrag: (crag: ActiveFeature) => void } -/** - * Toolbar for filtering/toggling data layers - */ -export const MapToolbar: React.FC = ({ onChange, layerState }) => { +export const MapToolbar: React.FC = ({ layerState, onChange, cragsList, onSelectCrag }) => { const { areaBoundaries, crags } = layerState + const [search, setSearch] = useState('') + const [suggestions, setSuggestions] = useState([]) + + const handleSearchChange = (e: ChangeEvent) => { + const value = e.target.value + setSearch(value) + if (value.length === 0) { + setSuggestions([]) + return + } + + const filtered = cragsList.filter(c => + c.data.areaName.toLowerCase().includes(value.toLowerCase()) + ) + setSuggestions(filtered) + } + + const handleSelect = (crag: ActiveFeature) => { + onSelectCrag(crag) + setSearch('') + setSuggestions([]) + } + return ( -
-
    +
    +
      = ({ onChange, layerState }) label='Boundaries' onChange={() => onChange({ ...layerState, areaBoundaries: !areaBoundaries })} /> +
      + + {suggestions.length > 0 && ( +
        + {suggestions.map(c => ( +
      • handleSelect(c)} + className='cursor-pointer p-2 hover:bg-gray-200' + > + {c.data.areaName} +
      • + ))} +
      + )} +
    )