diff --git a/package.json b/package.json index 36b72ea5e..90252988d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "engines": { "node": "~18", - "yarn": "3.5.0" + "yarn": "3.6.0" }, "dependencies": { "@artsy/fresnel": "6.1.0", @@ -114,5 +114,5 @@ "husky": { "pre-commit": "yarn lint" }, - "packageManager": "yarn@3.5.0" + "packageManager": "yarn@3.6.0" } diff --git a/src/components/contextual/contextual-basemaps.tsx b/src/components/contextual/contextual-basemaps.tsx index 7c28b571a..130309fb2 100644 --- a/src/components/contextual/contextual-basemaps.tsx +++ b/src/components/contextual/contextual-basemaps.tsx @@ -16,13 +16,14 @@ import type { ContextualBasemapsId } from 'types/widget'; const BasemapsMapSettings = () => { const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); - const defaultActive = activeLayers.find((layer) => layer.id.includes('planet'))?.id || 'no-layer'; + const defaultActive = + activeLayers?.find((layer) => layer.id.includes('planet'))?.id || 'no-layer'; const [isActive, setIsActive] = useState(defaultActive); const handleClick = useCallback( (id) => { setIsActive(id); - const noPlanetLayers = activeLayers.filter((w) => !w.id.includes('planet_medres')); + const noPlanetLayers = activeLayers?.filter((w) => !w.id.includes('planet_medres')); const layersUpdate = id === 'no-layer' ? noPlanetLayers diff --git a/src/components/contextual/hi-res-extent-basemap.tsx b/src/components/contextual/hi-res-extent-basemap.tsx index 892c201ad..f7f903ec1 100644 --- a/src/components/contextual/hi-res-extent-basemap.tsx +++ b/src/components/contextual/hi-res-extent-basemap.tsx @@ -16,7 +16,7 @@ import type { ContextualBasemapsId } from 'types/widget'; const HighResolutionExtentBasemap = () => { const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); const defaultActive = - activeLayers.find((layer) => layer.id === 'hi-res-extent')?.id || 'no-layer'; + activeLayers?.find((layer) => layer.id === 'hi-res-extent')?.id || 'no-layer'; const [isActive, setIsActive] = useState(defaultActive); const handleClick = useCallback( @@ -24,7 +24,7 @@ const HighResolutionExtentBasemap = () => { setIsActive(id); const layersUpdate = id === 'no-layer' - ? activeLayers.filter((w) => w.id !== 'hi-res-extent') + ? activeLayers?.filter((w) => w.id !== 'hi-res-extent') : ([ ...activeLayers, { diff --git a/src/components/highlighted-places/index.tsx b/src/components/highlighted-places/index.tsx index 49728fd7a..4abf19c50 100644 --- a/src/components/highlighted-places/index.tsx +++ b/src/components/highlighted-places/index.tsx @@ -17,7 +17,7 @@ const HighlightedPlaces = ({ onSelectLocation }: { onSelectLocation: () => void const { query: { params }, } = useRouter(); - const locationType = params?.[0] as LocationTypes; + const locationType = (params?.[0] || 'worldwide') as LocationTypes; const id = params?.[1]; const { diff --git a/src/components/planet-date-select/index.tsx b/src/components/planet-date-select/index.tsx index eda81159c..9ed515101 100644 --- a/src/components/planet-date-select/index.tsx +++ b/src/components/planet-date-select/index.tsx @@ -33,7 +33,7 @@ const DateSelect = ({ const { data: dates } = useMosaicsFromSeriesPlanetSatelliteBasemaps(mosaic_id); const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); const layerToUpdate = useMemo( - () => activeLayers.find((layer) => layer.id === id), + () => activeLayers?.find((layer) => layer.id === id), [activeLayers] ); @@ -49,7 +49,7 @@ const DateSelect = ({ const handleDate = useCallback( (e) => { - const filteredLayers = activeLayers.filter((l) => l.id !== id); + const filteredLayers = activeLayers?.filter((l) => l.id !== id); if (!!layerToUpdate) { setActiveLayers([ { diff --git a/src/components/suggested-layers/index.tsx b/src/components/suggested-layers/index.tsx index f55f7d4fb..16ab8ec19 100644 --- a/src/components/suggested-layers/index.tsx +++ b/src/components/suggested-layers/index.tsx @@ -35,12 +35,12 @@ const SuggestedLayers = ({ }: SuggestionTypes) => { const Info = INFO[id]; const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); - const activeLayersIds = activeLayers.map((l) => l.id); - const isActive = useMemo(() => activeLayersIds.includes(id), [activeLayersIds, id]); + const activeLayersIds = activeLayers?.map((l) => l.id); + const isActive = useMemo(() => activeLayersIds?.includes(id), [activeLayersIds, id]); const handleClick = useCallback(() => { const layersUpdate = isActive - ? activeLayers.filter((w) => w.id !== id) + ? activeLayers?.filter((w) => w.id !== id) : ([{ id, opacity: '1', visibility: 'visible' }, ...activeLayers] as ActiveLayers[]); setActiveLayers(layersUpdate); }, [isActive, activeLayers, setActiveLayers, id]); diff --git a/src/components/widget-controls/index.tsx b/src/components/widget-controls/index.tsx index c35d3e269..a252761d2 100644 --- a/src/components/widget-controls/index.tsx +++ b/src/components/widget-controls/index.tsx @@ -35,11 +35,11 @@ const WidgetControls = ({ id, content }: WidgetControlsType) => { const locationTool = useRecoilValue(locationToolAtom); const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); - const activeLayersIds = activeLayers.map((l) => l.id); + const activeLayersIds = activeLayers?.map((l) => l.id); const isActive = useMemo(() => { // Check if the id is included in activeLayersIds - const isCurrentlyActive = activeLayersIds.includes(id); + const isCurrentlyActive = activeLayersIds?.includes(id); // Check if any id in activeLayersIds starts with 'national_dashboard' const isAnyActiveNationalDashboard = @@ -64,7 +64,7 @@ const WidgetControls = ({ id, content }: WidgetControlsType) => { setActiveLayers(layersUpdate); }, [isActive, activeLayers, setActiveLayers, id]); - const HELPER_ID = id === activeLayers[0]?.id; + const HELPER_ID = id === activeLayers?.[0]?.id; const showDownloadInfoHelpers = !isMapSettingsOpen && HELPER_ID && (locationTool === 'worldwide' || locationTool === 'search'); diff --git a/src/containers/categories-menu/index.tsx b/src/containers/categories-menu/index.tsx index cf458b8fc..90a19f387 100644 --- a/src/containers/categories-menu/index.tsx +++ b/src/containers/categories-menu/index.tsx @@ -34,7 +34,7 @@ const Category = () => { const activeWidgetsIds = widgetsFiltered.map((widget) => widget.slug); const activeLayersIds: ActiveLayers[] = LAYERS_BY_CATEGORY[ event.currentTarget.value as string - ].map((id) => ({ + ]?.map((id) => ({ id: id as WidgetSlugType | ContextualBasemapsId | 'custom-area', opacity: '1', visibility: 'visible', @@ -50,45 +50,48 @@ const Category = () => {

presets

- {CATEGORY_OPTIONS.map((category) => ( -
- - ))} +

{category.label}

+ + + + + +
+ + ); + })} ); diff --git a/src/containers/datasets/alerts/layer.tsx b/src/containers/datasets/alerts/layer.tsx index 2ff979438..83837b399 100644 --- a/src/containers/datasets/alerts/layer.tsx +++ b/src/containers/datasets/alerts/layer.tsx @@ -10,7 +10,7 @@ import { useLayers, useSources } from './hooks'; const MangrovesAlertsLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCES = useSources(); const LAYERS = useLayers({ id, diff --git a/src/containers/datasets/alerts/widget.tsx b/src/containers/datasets/alerts/widget.tsx index 413c15405..e94cfdf09 100644 --- a/src/containers/datasets/alerts/widget.tsx +++ b/src/containers/datasets/alerts/widget.tsx @@ -40,7 +40,7 @@ const AlertsWidget = () => { }, []); const isActive = useMemo( - () => activeLayers.find(({ id }) => id === 'planet_medres_visual_monthly'), + () => activeLayers?.find(({ id }) => id === 'planet_medres_visual_monthly'), [activeLayers] ); diff --git a/src/containers/datasets/biomass/layer.tsx b/src/containers/datasets/biomass/layer.tsx index fa1cdefa3..d102703ac 100644 --- a/src/containers/datasets/biomass/layer.tsx +++ b/src/containers/datasets/biomass/layer.tsx @@ -10,7 +10,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesBiomassLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/blue-carbon/layer.tsx b/src/containers/datasets/blue-carbon/layer.tsx index 0314eace3..9e2d0c7c2 100644 --- a/src/containers/datasets/blue-carbon/layer.tsx +++ b/src/containers/datasets/blue-carbon/layer.tsx @@ -10,7 +10,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/contextual-layers/allen-coral-reef/layer.tsx b/src/containers/datasets/contextual-layers/allen-coral-reef/layer.tsx index fd5c4b56f..deef31844 100644 --- a/src/containers/datasets/contextual-layers/allen-coral-reef/layer.tsx +++ b/src/containers/datasets/contextual-layers/allen-coral-reef/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesAllenCoralReefLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/contextual-layers/basemaps-planet/analytic/layer.tsx b/src/containers/datasets/contextual-layers/basemaps-planet/analytic/layer.tsx index c2f08ce86..38cf2917a 100644 --- a/src/containers/datasets/contextual-layers/basemaps-planet/analytic/layer.tsx +++ b/src/containers/datasets/contextual-layers/basemaps-planet/analytic/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; export const PlanetSatelliteBasemapAnalyticLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource({ year: activeLayer.settings?.date, diff --git a/src/containers/datasets/contextual-layers/basemaps-planet/visual/layer.tsx b/src/containers/datasets/contextual-layers/basemaps-planet/visual/layer.tsx index 411d055bc..3f67ae95f 100644 --- a/src/containers/datasets/contextual-layers/basemaps-planet/visual/layer.tsx +++ b/src/containers/datasets/contextual-layers/basemaps-planet/visual/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; export const PlanetSatelliteBasemapVisualLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource({ year: activeLayer.settings?.date, diff --git a/src/containers/datasets/contextual-layers/global-tidal-wetland-change/layer.tsx b/src/containers/datasets/contextual-layers/global-tidal-wetland-change/layer.tsx index 32b015fdb..c26c390b1 100644 --- a/src/containers/datasets/contextual-layers/global-tidal-wetland-change/layer.tsx +++ b/src/containers/datasets/contextual-layers/global-tidal-wetland-change/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; const MangroveGlobalTidalWetlandChangeLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/contextual-layers/protected-areas/layer.tsx b/src/containers/datasets/contextual-layers/protected-areas/layer.tsx index d79f0d058..24d7636f0 100644 --- a/src/containers/datasets/contextual-layers/protected-areas/layer.tsx +++ b/src/containers/datasets/contextual-layers/protected-areas/layer.tsx @@ -12,7 +12,7 @@ import { useLayers, useSource } from './hooks'; const MangrovesProtectedAreasLayer = ({ beforeId, id, onAdd, onRemove }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ id, diff --git a/src/containers/datasets/contextual-layers/salt-marsh/layer.tsx b/src/containers/datasets/contextual-layers/salt-marsh/layer.tsx index c944a888f..8bb704ff9 100644 --- a/src/containers/datasets/contextual-layers/salt-marsh/layer.tsx +++ b/src/containers/datasets/contextual-layers/salt-marsh/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesSaltMarshLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/contextual-layers/tidal-flats/layer.tsx b/src/containers/datasets/contextual-layers/tidal-flats/layer.tsx index 8e0b3f190..967aba5f9 100644 --- a/src/containers/datasets/contextual-layers/tidal-flats/layer.tsx +++ b/src/containers/datasets/contextual-layers/tidal-flats/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; const MangroveTidalFlatsLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/customize-widgets-deck/widget.tsx b/src/containers/datasets/customize-widgets-deck/widget.tsx index 06b0e1124..802932342 100644 --- a/src/containers/datasets/customize-widgets-deck/widget.tsx +++ b/src/containers/datasets/customize-widgets-deck/widget.tsx @@ -31,8 +31,7 @@ const CustomizeWidgetsDeck = () => { const { query: { params }, } = useRouter(); - const locationType = params?.[0] || ('worldwide' as LocationTypes); - + const locationType = (params?.[0] || 'worldwide') as LocationTypes; useEffect(() => { const timeoutId = setTimeout(() => { setAnimateState('end'); @@ -51,7 +50,7 @@ const CustomizeWidgetsDeck = () => { }, [animateState]); const filteredWidgetsByLocationType = widgets - .filter((w) => w.locationType.includes(locationType)) + .filter((w) => w.locationType?.includes(locationType)) .map((w) => w.slug); const filteredWidgetsToDisplay = filteredWidgetsByLocationType.filter( diff --git a/src/containers/datasets/drivers-change/layer.tsx b/src/containers/datasets/drivers-change/layer.tsx index 924f2d872..5e586e329 100644 --- a/src/containers/datasets/drivers-change/layer.tsx +++ b/src/containers/datasets/drivers-change/layer.tsx @@ -10,7 +10,7 @@ import type { LayerProps } from 'types/layers'; const MangrovesLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ id, diff --git a/src/containers/datasets/fisheries/layer.tsx b/src/containers/datasets/fisheries/layer.tsx index 93bca20c8..b700d6317 100644 --- a/src/containers/datasets/fisheries/layer.tsx +++ b/src/containers/datasets/fisheries/layer.tsx @@ -10,7 +10,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesFisheriesLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/flood-protection/storms/layers/area.tsx b/src/containers/datasets/flood-protection/storms/layers/area.tsx index 61d4ec392..df83859cd 100644 --- a/src/containers/datasets/flood-protection/storms/layers/area.tsx +++ b/src/containers/datasets/flood-protection/storms/layers/area.tsx @@ -89,7 +89,7 @@ export function useLayers({ const MangrovesFloodProtectionLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ diff --git a/src/containers/datasets/flood-protection/storms/layers/population.tsx b/src/containers/datasets/flood-protection/storms/layers/population.tsx index 76a99e0e4..29f32d4fe 100644 --- a/src/containers/datasets/flood-protection/storms/layers/population.tsx +++ b/src/containers/datasets/flood-protection/storms/layers/population.tsx @@ -60,7 +60,7 @@ export function useLayers({ const MangrovesFloodProtectionPopulationLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ diff --git a/src/containers/datasets/flood-protection/storms/layers/stock.tsx b/src/containers/datasets/flood-protection/storms/layers/stock.tsx index 9233ef210..bba9feb64 100644 --- a/src/containers/datasets/flood-protection/storms/layers/stock.tsx +++ b/src/containers/datasets/flood-protection/storms/layers/stock.tsx @@ -60,7 +60,7 @@ export function useLayers({ const MangrovesFloodProtectionStockLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ diff --git a/src/containers/datasets/flood-protection/widget.tsx b/src/containers/datasets/flood-protection/widget.tsx index 463064720..587d45098 100644 --- a/src/containers/datasets/flood-protection/widget.tsx +++ b/src/containers/datasets/flood-protection/widget.tsx @@ -58,12 +58,12 @@ const FloodProtection = ({ const id = `mangrove_coastal_protection_${indicator}` satisfies WidgetSlugType; const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); - const activeLayersIds = activeLayers.map((l) => l.id); - const isActive = useMemo(() => activeLayersIds.includes(id), [activeLayersIds, id]); + const activeLayersIds = activeLayers?.map((l) => l.id); + const isActive = useMemo(() => activeLayersIds?.includes(id), [activeLayersIds, id]); const handleClick = () => { const layersUpdate = isActive - ? activeLayers.filter((w) => w.id !== id) + ? activeLayers?.filter((w) => w.id !== id) : ([{ id, opacity: '1', visibility: 'visible' }, ...activeLayers] as ActiveLayers[]); setActiveLayers(layersUpdate); }; diff --git a/src/containers/datasets/habitat-extent/layer.tsx b/src/containers/datasets/habitat-extent/layer.tsx index 6fda28381..645066b42 100644 --- a/src/containers/datasets/habitat-extent/layer.tsx +++ b/src/containers/datasets/habitat-extent/layer.tsx @@ -13,7 +13,7 @@ import { activeLayersAtom } from 'store/layers'; const MangrovesHabitatExtentLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const year = useRecoilValue(habitatExtentSettings); const { data } = useMangroveHabitatExtent({ year }); const years = data?.years?.sort() || []; diff --git a/src/containers/datasets/height/layer.tsx b/src/containers/datasets/height/layer.tsx index 393beaadc..646ba477b 100644 --- a/src/containers/datasets/height/layer.tsx +++ b/src/containers/datasets/height/layer.tsx @@ -11,7 +11,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(years); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/index.tsx b/src/containers/datasets/index.tsx index c31dd7837..61ee4c61a 100644 --- a/src/containers/datasets/index.tsx +++ b/src/containers/datasets/index.tsx @@ -203,7 +203,7 @@ export const MAP_LEGENDS = { mangrove_coastal_protection_area: FloodProtectionAreaMapLegend, mangrove_coastal_protection_population: FloodProtectionPopulationMapLegend, mangrove_coastal_protection_stock: FloodProtectionStockMapLegend, - // mangrove_rest_sites: RestorationSitesMapLegend, + mangrove_rest_sites: RestorationSitesMapLegend, mangrove_iucn_ecoregion: IUCNEcoregionsMapLegend, mangrove_national_dashboard_layer: NationalDashboardMapLegend, }; diff --git a/src/containers/datasets/iucn-ecoregion/layer.tsx b/src/containers/datasets/iucn-ecoregion/layer.tsx index e582824df..c6c9bb626 100644 --- a/src/containers/datasets/iucn-ecoregion/layer.tsx +++ b/src/containers/datasets/iucn-ecoregion/layer.tsx @@ -12,7 +12,7 @@ import { useLayers, useSource } from './hooks'; const MangrovesLayer = ({ beforeId, id, onAdd, onRemove }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ diff --git a/src/containers/datasets/national-dashboard/indicator-source/index.tsx b/src/containers/datasets/national-dashboard/indicator-source/index.tsx index d7bfdb82f..025bdb522 100644 --- a/src/containers/datasets/national-dashboard/indicator-source/index.tsx +++ b/src/containers/datasets/national-dashboard/indicator-source/index.tsx @@ -39,14 +39,14 @@ const IndicatorSource = ({ setYearSelected, }: IndicatorSourceTypes) => { const [activeLayers, setActiveLayers] = useRecoilState(activeLayersAtom); - const activeLayersIds = activeLayers.map((l) => l.id); + const activeLayersIds = activeLayers?.map((l) => l.id); const isActive = useMemo( () => activeLayersIds.some((layerId) => layerId.startsWith('mangrove_national_dashboard')), [activeLayersIds] ); - const compareNationalLayers = activeLayersIds.includes(id); + const compareNationalLayers = activeLayersIds?.includes(id); useEffect(() => { if (isActive && !compareNationalLayers) { @@ -68,7 +68,7 @@ const IndicatorSource = ({ const handleClick = useCallback(() => { const layersUpdate = isActive - ? activeLayers.filter((w) => !w.id.includes('mangrove_national_dashboard_layer')) + ? activeLayers?.filter((w) => !w.id.includes('mangrove_national_dashboard_layer')) : ([ { id, diff --git a/src/containers/datasets/national-dashboard/layer.tsx b/src/containers/datasets/national-dashboard/layer.tsx index 91d37e6c2..931dec86c 100644 --- a/src/containers/datasets/national-dashboard/layer.tsx +++ b/src/containers/datasets/national-dashboard/layer.tsx @@ -10,7 +10,7 @@ import { useLayers, useSource } from './hooks'; const MangrovesNationalDashboardLayer = ({ beforeId, id }: LayerProps) => { const [activeLayers] = useRecoilState(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource({ settings: activeLayer.settings }); const LAYER = useLayers({ diff --git a/src/containers/datasets/national-dashboard/map-legend.tsx b/src/containers/datasets/national-dashboard/map-legend.tsx index a4e701fbf..2484648da 100644 --- a/src/containers/datasets/national-dashboard/map-legend.tsx +++ b/src/containers/datasets/national-dashboard/map-legend.tsx @@ -9,7 +9,7 @@ import { useNationalDashboard } from './hooks'; const colorsScale = chroma.scale(COLORS).colors(COLORS.length); const NationalDashboardMapLegend = () => { const [activeLayers] = useRecoilState(activeLayersAtom); - const layer = activeLayers.find(({ id }) => id.includes('mangrove_national_dashboard')); + const layer = activeLayers?.find(({ id }) => id.includes('mangrove_national_dashboard')); const { data } = useNationalDashboard(); const sources = data?.data[0]?.sources; diff --git a/src/containers/datasets/net-change/layer.tsx b/src/containers/datasets/net-change/layer.tsx index c5447bddb..717295d11 100644 --- a/src/containers/datasets/net-change/layer.tsx +++ b/src/containers/datasets/net-change/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSources } from './hooks'; export const NetChangeLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const sourceLoss = useSources('loss') satisfies SourceProps[]; const sourceGain = useSources('gain') satisfies SourceProps[]; diff --git a/src/containers/datasets/protection/layer.tsx b/src/containers/datasets/protection/layer.tsx index 410040468..e350749ca 100644 --- a/src/containers/datasets/protection/layer.tsx +++ b/src/containers/datasets/protection/layer.tsx @@ -10,7 +10,7 @@ import { useLayers, useSource } from './hooks'; const MangrovesProtectedAreasLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ id, diff --git a/src/containers/datasets/restoration-sites/layer.tsx b/src/containers/datasets/restoration-sites/layer.tsx index 29a143141..d377c4086 100644 --- a/src/containers/datasets/restoration-sites/layer.tsx +++ b/src/containers/datasets/restoration-sites/layer.tsx @@ -10,7 +10,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesRestorationSitesLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === 'mangrove_rest_sites'); + const activeLayer = activeLayers?.find((l) => l.id === 'mangrove_rest_sites'); const SOURCE = useSource(); const LAYERS = useLayer({ diff --git a/src/containers/datasets/restoration/layer.tsx b/src/containers/datasets/restoration/layer.tsx index 6e11a5897..67e292b3a 100644 --- a/src/containers/datasets/restoration/layer.tsx +++ b/src/containers/datasets/restoration/layer.tsx @@ -12,7 +12,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesLayer = ({ beforeId, id, onAdd, onRemove }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYER = useLayer({ id, diff --git a/src/containers/datasets/species-distribution/layer.tsx b/src/containers/datasets/species-distribution/layer.tsx index dbfc1c61a..c00ce2744 100644 --- a/src/containers/datasets/species-distribution/layer.tsx +++ b/src/containers/datasets/species-distribution/layer.tsx @@ -10,7 +10,7 @@ import { useLayers, useSource } from './hooks'; const MangrovesSpeciesDistributionLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayers({ id, diff --git a/src/containers/datasets/species-location/layer.tsx b/src/containers/datasets/species-location/layer.tsx index d7aed2843..403f8399a 100644 --- a/src/containers/datasets/species-location/layer.tsx +++ b/src/containers/datasets/species-location/layer.tsx @@ -10,7 +10,7 @@ import { useLayer, useSource } from './hooks'; const MangrovesSpeciesLocationLayer = ({ beforeId, id }: LayerProps) => { const activeLayers = useRecoilValue(activeLayersAtom); - const activeLayer = activeLayers.find((l) => l.id === id); + const activeLayer = activeLayers?.find((l) => l.id === id); const SOURCE = useSource(); const LAYERS = useLayer({ id, diff --git a/src/containers/location-widget/index.tsx b/src/containers/location-widget/index.tsx index 26a7ac3b2..415ee5271 100644 --- a/src/containers/location-widget/index.tsx +++ b/src/containers/location-widget/index.tsx @@ -18,12 +18,12 @@ import LocationDialogContent from 'containers/location-dialog-content'; import LocationTools from 'containers/navigation/location-tools'; import { Dialog, DialogTrigger } from 'components/ui/dialog'; -import { GrPowerReset } from 'react-icons/gr'; + const LocationWidget = () => { const { query: { params }, } = useRouter(); - const locationType = params?.[0] as LocationTypes; + const locationType = (params?.[0] || 'worldwide') as LocationTypes; const id = params?.[1]; const { data: { name }, diff --git a/src/containers/locations-list/mobile/highlighted-places/index.tsx b/src/containers/locations-list/mobile/highlighted-places/index.tsx index 7db07cf57..3fc7abec2 100644 --- a/src/containers/locations-list/mobile/highlighted-places/index.tsx +++ b/src/containers/locations-list/mobile/highlighted-places/index.tsx @@ -17,7 +17,7 @@ const HighlightedPlacesMobile = () => { const { query: { params }, } = useRouter(); - const locationType = params?.[0] as LocationTypes; + const locationType = (params?.[0] || 'worldwide') as LocationTypes; const id = params?.[1]; const { diff --git a/src/containers/map/layer-manager/index.tsx b/src/containers/map/layer-manager/index.tsx index 1f76e430c..87205ac76 100644 --- a/src/containers/map/layer-manager/index.tsx +++ b/src/containers/map/layer-manager/index.tsx @@ -25,12 +25,12 @@ const LayerManagerContainer = () => { const [, setInteractiveLayerIds] = useRecoilState(interactiveLayerIdsAtom); - const activeLayersIds = layers.map((l) => l.id); + const activeLayersIds = layers?.map((l) => l.id); const ACTIVE_LAYERS = useMemo(() => { - const filteredLayers = activeLayersIds.filter( + const filteredLayers = activeLayersIds?.filter( (layer: WidgetSlugType | ContextualBasemapsId | 'custom-area') => { - return Object.keys(LAYERS).some((k) => layer.includes(k)); + return Object.keys(LAYERS).some((k) => layer?.includes(k)); } ); @@ -42,13 +42,12 @@ const LayerManagerContainer = () => { } = useRouter(); const id = params?.[1]; - const locationType = params?.[0] || ('worldwide' as LocationTypes); - + const locationType = (params?.[0] || 'worldwide') as LocationTypes; function filterLayersByLocationType(widgets: WidgetTypes[], locationType: string): string[] { const filteredLayers: string[] = []; widgets.forEach((widget) => { - if (widget.locationType.includes(locationType)) { + if (widget.locationType?.includes(locationType)) { if (widget.layersIds) { filteredLayers.push(...widget.layersIds); } @@ -67,20 +66,19 @@ const LayerManagerContainer = () => { const filteredLayers = filterLayersByLocationType(widgets, locationType); // layers that act as basemap (such planet imagery or high resolution extent) must be always at the bottom - const basemap_layers = ACTIVE_LAYERS.filter( - (layer) => layer.includes('planet') || layer === 'hi-res-extent' + const basemap_layers = ACTIVE_LAYERS?.filter( + (layer) => layer?.includes('planet') || layer === 'hi-res-extent' ); - const no_planet_layers = ACTIVE_LAYERS.filter( + const no_planet_layers = ACTIVE_LAYERS?.filter( (layer) => - !layer.includes('planet') && layer !== 'hi-res-extent' && filteredLayers.includes(layer) + !layer?.includes('planet') && layer !== 'hi-res-extent' && filteredLayers?.includes(layer) ); - const filterNationalDashboardLayers = !NATIONAL_DASHBOARD_LOCATIONS.includes(id) - ? no_planet_layers.filter((l) => !l.includes('national_dashboard')) + const filterNationalDashboardLayers = !NATIONAL_DASHBOARD_LOCATIONS?.includes(id) + ? no_planet_layers?.filter((l) => !l?.includes('national_dashboard')) : no_planet_layers; - const LAYERS_FILTERED = [...filterNationalDashboardLayers, ...basemap_layers]; - + const LAYERS_FILTERED = [...(filterNationalDashboardLayers || []), ...(basemap_layers || [])]; const handleAdd = useCallback( (styleIds: LayerProps['id'][]) => { setInteractiveLayerIds((prevInteractiveIds) => [...prevInteractiveIds, ...styleIds]); @@ -91,7 +89,7 @@ const LayerManagerContainer = () => { const handleRemove = useCallback( (styleIds: LayerProps['id'][]) => { setInteractiveLayerIds((prevInteractiveIds) => [ - ...prevInteractiveIds.filter((id) => !styleIds.includes(id)), + ...prevInteractiveIds.filter((id) => !styleIds?.includes(id)), ]); }, [setInteractiveLayerIds] @@ -135,7 +133,7 @@ const LayerManagerContainer = () => { })} {LAYERS_FILTERED.map((layer, i) => { - const layerId = Object.keys(LAYERS).find((k) => layer.includes(k)); + const layerId = Object.keys(LAYERS).find((k) => layer?.includes(k)); const LayerComponent = LAYERS[layerId] || BASEMAPS[layerId]; const beforeId = i === 0 ? 'custom-layers' : `${LAYERS_FILTERED[i - 1]}-bg`; diff --git a/src/containers/map/legend/index.tsx b/src/containers/map/legend/index.tsx index d91e713ed..1684921ce 100644 --- a/src/containers/map/legend/index.tsx +++ b/src/containers/map/legend/index.tsx @@ -28,13 +28,12 @@ const Legend = ({ embedded = false }: { embedded?: boolean }) => { } = useRouter(); const id = params?.[1]; - const locationType = params?.[0] || ('worldwide' as LocationTypes); - + const locationType = (params?.[0] || 'worldwide') as LocationTypes; function filterLayersByLocationType(widgets: WidgetTypes[], locationType: string): string[] { const filteredLayers: string[] = []; widgets.forEach((widget) => { - if (widget.locationType.includes(locationType)) { + if (widget.locationType?.includes(locationType)) { if (widget.layersIds) { filteredLayers.push(...widget.layersIds); } @@ -51,14 +50,14 @@ const Legend = ({ embedded = false }: { embedded?: boolean }) => { } const filteredLayersIds = filterLayersByLocationType(widgets, locationType); - const filteredLayers = activeLayers.filter(({ id }) => { + const filteredLayers = activeLayers?.filter(({ id }) => { return filteredLayersIds.includes(id); }) as ActiveLayers[]; const [isOpen, setIsOpen] = useState(false); const openLegend = useCallback(() => { - if (!!activeLayers.length) setIsOpen(true); + if (!!activeLayers?.length) setIsOpen(true); }, [activeLayers]); const closeLegend = useCallback(() => { @@ -68,26 +67,26 @@ const Legend = ({ embedded = false }: { embedded?: boolean }) => { const handleChangeOrder = useCallback( (order: string[]) => { const newLayers = order.map((id) => { - return activeLayers.find((l) => l.id === id); + return activeLayers?.find((l) => l.id === id); }) as ActiveLayers[]; - const activeLayerPlanet = activeLayers.filter((l) => l.id.includes('planet')); + const activeLayerPlanet = activeLayers?.filter((l) => l.id.includes('planet')); setActiveLayers([...newLayers, ...activeLayerPlanet]); }, [activeLayers, setActiveLayers] ); // planet layers behave as a basemap so there is no need to include them in the legend - const activeLayerNoPlanet = filteredLayers.filter( + const activeLayerNoPlanet = filteredLayers?.filter( (l) => !l.id.includes('planet') && !l.id.includes('custom-area') ); const filterNationalDashboardLayers = !NATIONAL_DASHBOARD_LOCATIONS.includes(id) - ? activeLayerNoPlanet.filter((l) => !l.id.includes('national_dashboard')) + ? activeLayerNoPlanet?.filter((l) => !l.id.includes('national_dashboard')) : activeLayerNoPlanet; return (
- {!!filterNationalDashboardLayers.length && ( + {!!filterNationalDashboardLayers?.length && ( <>
Map
diff --git a/src/containers/widget/selector.ts b/src/containers/widget/selector.ts index cd3da367d..a4f558512 100644 --- a/src/containers/widget/selector.ts +++ b/src/containers/widget/selector.ts @@ -24,6 +24,6 @@ export const getLayerActive = selectorFamily< ({ get }) => { const activeLayers = get(activeLayersAtom); // Check if any object in the array has an id that matches widgetId - return activeLayers.some((layer) => layer.id === widgetId); + return activeLayers?.some((layer) => layer.id === widgetId); }, }); diff --git a/src/containers/widgets/constants.ts b/src/containers/widgets/constants.ts index c809d322a..4eee2533c 100644 --- a/src/containers/widgets/constants.ts +++ b/src/containers/widgets/constants.ts @@ -1,6 +1,17 @@ import { WidgetTypes } from 'types/widget'; const widgets_dev = [ + { + name: 'Mangrove Restoration Sites', + slug: 'mangrove_rest_sites', + locationType: ['country', 'worldwide'], + applicability: 'Global, National, and Sub-National', + categoryIds: ['all_datasets', 'restoration_and_conservation'], + layersIds: ['mangrove_rest_sites'], + }, +] satisfies WidgetTypes[]; + +const widgets_prod = [ { name: 'National Dashboard', slug: 'mangrove_national_dashboard', @@ -9,17 +20,6 @@ const widgets_dev = [ categoryIds: ['all_datasets', 'distribution_and_change'], layersIds: ['mangrove_national_dashboard'], }, - // { - // name: 'Mangrove Restoration Sites', - // slug: 'mangrove_rest_sites', - // locationType: ['country', 'worldwide'], - // applicability: 'Global, National, and Sub-National', - // categoryIds: ['all_datasets', 'restoration_and_conservation'], - // layersIds: ['mangrove_rest_sites'], - // }, -] satisfies WidgetTypes[]; - -const widgets_prod = [ { name: 'Mangrove Habitat Extent', slug: 'mangrove_habitat_extent', @@ -169,16 +169,18 @@ const widgets_prod = [ 'mangrove_coastal_protection_stock', ], }, - { - ...(process.env.NEXT_PUBLIC_VERCEL_ENV === 'development' && { - name: 'IUCN Ecosystem Red List Assessment', - slug: 'mangrove_iucn_ecoregion', - locationType: ['worldwide'], - applicability: 'Global', - categoryIds: ['all_datasets', 'distribution_and_change', 'restoration_and_conservation'], - layersIds: ['mangrove_iucn_ecoregion'], - }), - }, + ...(process.env.NEXT_PUBLIC_VERCEL_ENV === 'development' + ? ([ + { + name: 'IUCN Ecosystem Red List Assessment', + slug: 'mangrove_iucn_ecoregion', + locationType: ['worldwide'], + applicability: 'Global', + categoryIds: ['all_datasets', 'distribution_and_change', 'restoration_and_conservation'], + layersIds: ['mangrove_iucn_ecoregion'], + }, + ] as WidgetTypes[]) + : []), { name: 'Protected Areas', slug: 'mangrove_protected_areas', diff --git a/src/containers/widgets/hooks.tsx b/src/containers/widgets/hooks.tsx index 593212d3e..00871cecd 100644 --- a/src/containers/widgets/hooks.tsx +++ b/src/containers/widgets/hooks.tsx @@ -63,6 +63,7 @@ export function useWidgetsIdsByCategory(widgets) { for (const cat of WIDGETS_BY_CATEGORY) { const [category, slugsCategory] = Object.entries(cat)[0]; + // Convert each category's widget array to a set for efficient lookup const slugsCategorySet = new Set(slugsCategory); // Check if every element in the category set is in the widgets set @@ -75,7 +76,7 @@ export function useWidgetsIdsByCategory(widgets) { ); // Check for an exact match in terms of content and count - if (isCategoryFullyInWidgets && areWidgetsOnlyFromCategory) { + if (isCategoryFullyInWidgets && areWidgetsOnlyFromCategory && category !== 'all_datasets') { return category; } } diff --git a/src/containers/widgets/index.tsx b/src/containers/widgets/index.tsx index de5143b61..7b3467f0b 100644 --- a/src/containers/widgets/index.tsx +++ b/src/containers/widgets/index.tsx @@ -85,8 +85,7 @@ const WidgetsContainer: FC = () => { } = useRouter(); // Params as default don't appear in URL, when there is no location we assume worldwide - const locationType = params?.[0] || ('worldwide' as LocationTypes); - + const locationType = (params?.[0] || 'worldwide') as LocationTypes; const [{ uploadedGeojson }] = useRecoilState(drawingUploadToolAtom); const { width: screenWidth } = useWindowSize(); @@ -141,7 +140,7 @@ const WidgetsContainer: FC = () => { }, []); const activeWidgetsFilteredByLocationType = widgets - .filter((w) => w.locationType.includes(locationType)) + .filter((w) => w.locationType?.includes(locationType)) .map(({ slug }) => slug); const filteredWidgetsToDisplay = activeWidgetsFilteredByLocationType.filter( diff --git a/src/containers/widgets/widgets-menu/index.tsx b/src/containers/widgets/widgets-menu/index.tsx index c8a7d23d0..f4054c324 100644 --- a/src/containers/widgets/widgets-menu/index.tsx +++ b/src/containers/widgets/widgets-menu/index.tsx @@ -29,17 +29,16 @@ const WidgetsMenu: FC = () => { const [activeWidgets, setActiveWidgets] = useRecoilState(activeWidgetsAtom); const widgets = rawWidgets.filter(({ slug }) => slug !== 'widgets_deck_tool'); - const activeLayersIds = activeLayers.map((layer) => layer.id); + const activeLayersIds = activeLayers?.map((layer) => layer.id); const widgetsIds = widgets.map((widget) => widget.slug); const enabledWidgets = useWidgetsIdsByLocation(); - const categoryFromWidgets = useWidgetsIdsByCategory(activeWidgets); // Updates the category when user changes widgets filtering throw checkboxes, // are activated. It identifies the category associated with the active widgets and // updates it accordingly. useEffect(() => { - if (categorySelected !== categoryFromWidgets) { + if (categorySelected !== categoryFromWidgets && categoryFromWidgets !== 'all_datasets') { setCategory(categoryFromWidgets); } }, [categorySelected, categoryFromWidgets, setCategory]); @@ -49,10 +48,10 @@ const WidgetsMenu: FC = () => { }, [widgetsIds, setActiveWidgets, activeWidgets, widgets]); const handleAllLayers = useCallback(() => { - if (activeLayers.length <= LAYERS.length && activeLayers.length > 0) { + if (activeLayers?.length <= LAYERS.length && activeLayers?.length > 0) { setActiveLayers([]); } - if (LAYERS.length > activeLayers.length) { + if (LAYERS.length > activeLayers?.length) { const NewLayersActive: ActiveLayers[] = LAYERS.map((layer) => ({ id: layer.id as WidgetSlugType | ContextualBasemapsId | 'custom-area', opacity: '1', @@ -85,8 +84,8 @@ const WidgetsMenu: FC = () => { ); const handleLayers = useCallback( (e: WidgetSlugType) => { - const layersUpdate = activeLayersIds.includes(e) - ? activeLayers.filter((w) => w.id !== e) + const layersUpdate = activeLayersIds?.includes(e) + ? activeLayers?.filter((w) => w.id !== e) : [{ id: e, opacity: '1', visibility: 'visible' as Visibility }, ...activeLayers]; setActiveLayers(layersUpdate); }, @@ -125,11 +124,11 @@ const WidgetsMenu: FC = () => { data-testid="all-layers-checkbox" onCheckedChange={handleAllLayers} defaultChecked={false} - checked={LAYERS.length === activeLayers.length} + checked={LAYERS.length === activeLayers?.length} className={cn({ 'text-brand-500 m-auto h-3 w-3 rounded-sm border border-black/15 bg-white text-white': true, - 'bg-brand-800': LAYERS.length === activeLayers.length, + 'bg-brand-800': LAYERS.length === activeLayers?.length, })} > @@ -140,7 +139,7 @@ const WidgetsMenu: FC = () => { className={cn({ 'col-span-4 col-start-3 col-end-6': true, 'font-bold text-brand-800': - LAYERS.length === activeLayers.length && widgets.length === activeWidgets.length, + LAYERS.length === activeLayers?.length && widgets.length === activeWidgets.length, })} > Select All @@ -185,19 +184,19 @@ const WidgetsMenu: FC = () => { onCheckedChange={() => handleLayers(slug)} disabled={!enabledWidgets.includes(slug)} defaultChecked - checked={activeLayersIds.includes(slug)} + checked={activeLayersIds?.includes(slug)} className={cn({ 'text-brand-500 m-auto h-3 w-3 rounded-sm border border-black/15 bg-white': true, 'bg-brand-800 font-bold text-white': - activeLayersIds.includes(slug) && enabledWidgets.includes(slug), + activeLayersIds?.includes(slug) && enabledWidgets.includes(slug), })} > @@ -207,7 +206,7 @@ const WidgetsMenu: FC = () => { className={cn({ 'col-span-4 col-start-3 col-end-6': true, 'font-bold text-brand-800': - activeLayersIds.includes(slug) || activeWidgets.includes(slug), + activeLayersIds?.includes(slug) || activeWidgets.includes(slug), 'opacity-40': !enabledWidgets.includes(slug), })} key={slug} diff --git a/src/hooks/layers/index.ts b/src/hooks/layers/index.ts index bb3a91313..2fdac02d6 100644 --- a/src/hooks/layers/index.ts +++ b/src/hooks/layers/index.ts @@ -19,18 +19,18 @@ type Layer = { export function updateLayers(activeLayers: Layer[], newLayer: Layer): Layer[] { const { id } = newLayer; - const index = activeLayers.findIndex((layer) => layer.id === id); + const index = activeLayers?.findIndex((layer) => layer.id === id); const hasNationalDashboard = id.includes('national_dashboard'); - const nationalDashboardIndex = activeLayers.findIndex((layer) => + const nationalDashboardIndex = activeLayers?.findIndex((layer) => layer.id.includes('national_dashboard') ); if (index !== -1) { // Delete the layer if it already exists by creating a new array without that layer - return [...activeLayers.slice(0, index), ...activeLayers.slice(index + 1)]; + return [...activeLayers?.slice(0, index), ...activeLayers?.slice(index + 1)]; } else if (hasNationalDashboard && nationalDashboardIndex !== -1) { // Replace the national_dashboard layer with the new layer by creating a new array - return activeLayers.map((layer, idx) => (idx === nationalDashboardIndex ? newLayer : layer)); + return activeLayers?.map((layer, idx) => (idx === nationalDashboardIndex ? newLayer : layer)); } else { // Adds the new layer to the list by creating a new array with the new layer return [...activeLayers, newLayer];