diff --git a/client/src/containers/datasets/layers/projects/hooks.tsx b/client/src/containers/datasets/layers/projects/hooks.tsx new file mode 100644 index 00000000..23050ae5 --- /dev/null +++ b/client/src/containers/datasets/layers/projects/hooks.tsx @@ -0,0 +1,35 @@ +import { CircleLayer } from 'mapbox-gl'; + +import { Settings } from '@/components/map/legend/types'; + +export function useLayers({ settings }: { settings: Settings }) { + return [ + { + id: 'projects_points_shadow', + type: 'circle', + paint: { + 'circle-radius': 32, + 'circle-color': '#ccc', + 'circle-blur': 1, + }, + }, + { + id: 'projects', + type: 'circle', + paint: { + 'circle-stroke-color': '#ffffff', + 'circle-stroke-width': 9, + 'circle-radius': 10, + 'circle-color': [ + 'case', + ['boolean', ['feature-state', 'hover'], false], + '#77CCFF', + '#176252', + ], + }, + layout: { + visibility: settings.visibility ? 'visible' : 'none', + }, + }, + ] as CircleLayer[]; +} diff --git a/client/src/containers/datasets/layers/projects/layer.tsx b/client/src/containers/datasets/layers/projects/layer.tsx index cd2885a6..3538eb92 100644 --- a/client/src/containers/datasets/layers/projects/layer.tsx +++ b/client/src/containers/datasets/layers/projects/layer.tsx @@ -1,52 +1,24 @@ -import { useMemo } from 'react'; - import { Layer, Source } from 'react-map-gl'; -import { GeoJSONSourceRaw, GeoJSONSourceOptions, CircleLayer } from 'mapbox-gl'; +import { GeoJSONSourceRaw, GeoJSONSourceOptions } from 'mapbox-gl'; import type { LayerProps } from '@/types/layers'; +import { useLayers } from './hooks'; import mockData from './mock.json'; const GEOJSON = mockData as GeoJSON.FeatureCollection; -const SOURCE: GeoJSONSourceRaw & GeoJSONSourceOptions = { +const SOURCE: GeoJSONSourceRaw & GeoJSONSourceOptions & { id: string } = { type: 'geojson', data: GEOJSON, + id: 'projects', }; export const ProjectsLayer = ({ beforeId, settings }: LayerProps) => { - const LAYERS: CircleLayer[] = useMemo(() => { - return [ - { - id: 'points_shadow', - type: 'circle', - paint: { - 'circle-radius': 32, - 'circle-color': '#ccc', - 'circle-blur': 1, - }, - }, - { - id: 'projects', - type: 'circle', - paint: { - 'circle-stroke-color': '#ffffff', - 'circle-stroke-width': 9, - 'circle-radius': 10, - 'circle-color': [ - 'case', - ['boolean', ['feature-state', 'hover'], false], - '#176252', - '#77CCFF', - ], - }, - layout: { - visibility: settings.visibility ? 'visible' : 'none', - }, - }, - ]; - }, [settings.visibility]); + const LAYERS = useLayers({ + settings, + }); if (!SOURCE || !LAYERS.length) return null; diff --git a/client/src/containers/map/index.tsx b/client/src/containers/map/index.tsx index ac5be122..22830250 100644 --- a/client/src/containers/map/index.tsx +++ b/client/src/containers/map/index.tsx @@ -130,40 +130,51 @@ export default function MapContainer() { } if (e.features && e.features[0]) { - push(`/projects/${e.features[0].properties.slug}`); + push(`/projects/${e.features[0].properties?.slug}`); } }, [layersInteractive, layersInteractiveData, setPopup, push] ); - let hoveredStateId: string | null = null; + let hoveredStateId: undefined | string = undefined; const handleMouseMove = useCallback( (e: MapLayerMouseEvent) => { + const ProjectsLayer = e?.features && e?.features.find(({ layer }) => layer.id === 'projects'); + + // *ON MOUSE ENTER if (e.features && e.features[0] && map) { setCursor('pointer'); - if (hoveredStateId !== null) { + if (hoveredStateId !== undefined) { map?.setFeatureState( { - source: 'jsx-source-1', + source: 'projects', id: hoveredStateId, }, { hover: false } ); } } - hoveredStateId = 'projects'; - if (e.features && !e.features[0]) { + hoveredStateId = ProjectsLayer?.layer.id; + map?.setFeatureState( + { + source: 'projects', + id: hoveredStateId, + }, + { hover: true } + ); + + // *ON MOUSE LEAVE + if (!ProjectsLayer) { setCursor('grab'); - if (hoveredStateId === null) { - map?.setFeatureState( - { - source: 'jsx-source-1', - id: hoveredStateId, - }, - { hover: true } - ); - } + map?.setFeatureState( + { + source: 'projects', + id: hoveredStateId, + }, + { hover: false } + ); + hoveredStateId = undefined; } }, [setCursor, map, hoveredStateId]