Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix/map zoom out #2352

Open
wants to merge 7 commits into
base: hotfix/plantlocation-render-issue
Choose a base branch
from
29 changes: 3 additions & 26 deletions src/features/projectsV2/ProjectsMap/MultipleProjectsView.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,19 @@
import type { CategorizedProjects } from './ProjectMarkers';
import type { MapRef } from '../../common/types/projectv2';

import { useEffect, useMemo } from 'react';
import { useMemo } from 'react';
import ProjectMarkers from './ProjectMarkers';
import { useProjects } from '../ProjectsContext';
import { useProjectsMap } from '../ProjectsMapContext'; // Add this import
import { getProjectCategory } from '../../../utils/projectV2';
import { zoomOutMap } from '../../../utils/mapsV2/zoomToProjectSite';

interface MultipleProjectsViewProps {
mapRef: MapRef;
page: 'project-list' | 'project-details';
}

const MultipleProjectsView = ({ mapRef, page }: MultipleProjectsViewProps) => {
const MultipleProjectsView = ({ page }: MultipleProjectsViewProps) => {
const { projects, isLoading, isError, filteredProjects } = useProjects();
const { handleViewStateChange } = useProjectsMap();
if (isLoading || isError || !projects) {
return null;
}

useEffect(() => {
//Wrapping the logic in Promise.resolve().then() defers the map-related code until after synchronous tasks finish,
//Giving the map time to initialize fully. This ensures mapRef.current is ready for interaction.
Promise.resolve().then(() => {
if (mapRef.current) {
const map = mapRef.current.getMap
? mapRef.current.getMap()
: mapRef.current;
zoomOutMap(map, () => {
handleViewStateChange({
...map.getCenter(),
zoom: map.getZoom(),
});
});
}
});
}, []);
if (isLoading || isError || !projects) return null;

const categorizedProjects = useMemo(() => {
return filteredProjects?.reduce<CategorizedProjects>(
Expand Down
30 changes: 18 additions & 12 deletions src/features/projectsV2/ProjectsMap/SingleProjectView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import PlantLocations from './microComponents/PlantLocations';
import { zoomToPolygonPlantLocation } from '../../../utils/mapsV2/zoomToPolygonPlantLocation';
import zoomToLocation from '../../../utils/mapsV2/zoomToLocation';
import ProjectLocation from './microComponents/ProjectLocation';
import { MAIN_MAP_ANIMATION_DURATIONS } from '../../../utils/projectV2';

interface Props {
mapRef: MapRef;
Expand Down Expand Up @@ -48,12 +49,19 @@ const SingleProjectView = ({ mapRef }: Props) => {
polygonCoordinates,
mapRef,
handleViewStateChange,
4000
MAIN_MAP_ANIMATION_DURATIONS.ZOOM_IN
);
} else if (isPointLocation) {
const [lon, lat] = coordinates;
if (typeof lon === 'number' && typeof lat === 'number') {
zoomToLocation(handleViewStateChange, lon, lat, 20, 4000, mapRef);
zoomToLocation(
handleViewStateChange,
lon,
lat,
20,
MAIN_MAP_ANIMATION_DURATIONS.ZOOM_IN,
mapRef
);
}
}
}, [selectedPlantLocation, router.isReady, requestedPlantLocation]);
Expand All @@ -72,7 +80,7 @@ const SingleProjectView = ({ mapRef }: Props) => {
sitesGeojson,
selectedSite,
handleViewStateChange,
4000
MAIN_MAP_ANIMATION_DURATIONS.ZOOM_IN
);
} else {
const { lat: latitude, lon: longitude } = singleProject.coordinates;
Expand All @@ -99,16 +107,14 @@ const SingleProjectView = ({ mapRef }: Props) => {
requestedSite,
]);

// Enable satellite view for 'conservation' projects or 'trees' projects without plant locations(tree mapper data).
useEffect(() => {
if (plantLocations === null) return;
const hasNoPlantLocations = !plantLocations?.length;
const isSingleProjectLocation = hasNoPlantLocations && hasNoSites;
// Satellite view will be:
// - false if there are no plant locations and no sites (i.e., a single project location only)
// - true if there are no plant locations but there are multiple sites
setIsSatelliteView(!isSingleProjectLocation && hasNoPlantLocations);
}, [plantLocations, hasNoSites]);
const isSatelliteView =
singleProject.purpose === 'conservation' ||
(singleProject.purpose === 'trees' && plantLocations?.length === 0);

setIsSatelliteView(isSatelliteView);
}, [plantLocations, singleProject.purpose]);
return (
<>
{hasNoSites ? (
Expand All @@ -123,7 +129,7 @@ const SingleProjectView = ({ mapRef }: Props) => {
isSatelliteView={isSatelliteView}
geoJson={sitesGeojson}
/>
{isSatelliteView && plantLocations !== null && <SatelliteLayer />}
{isSatelliteView && <SatelliteLayer />}
</>
)}

Expand Down
22 changes: 21 additions & 1 deletion src/features/projectsV2/ProjectsMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { SetState } from '../../common/types/common';
import type { PlantLocationSingle } from '../../common/types/plantLocation';
import type { ExtendedMapLibreMap, MapRef } from '../../common/types/projectv2';

import { useCallback, useMemo, useRef } from 'react';
import { useCallback, useEffect, useMemo, useRef } from 'react';
import 'maplibre-gl/dist/maplibre-gl.css';
import Map, { NavigationControl } from 'react-map-gl-v7/maplibre';
import { useProjectsMap } from '../ProjectsMapContext';
Expand All @@ -24,6 +24,7 @@ import MultiPlantLocationInfo from '../ProjectDetails/components/MultiPlantLocat
import SinglePlantLocationInfo from '../ProjectDetails/components/SinglePlantLocationInfo';
import styles from './ProjectsMap.module.scss';
import { useDebouncedEffect } from '../../../utils/useDebouncedEffect';
import { zoomOutMap } from '../../../utils/mapsV2/zoomToProjectSite';

export type ProjectsMapDesktopProps = {
isMobile: false;
Expand Down Expand Up @@ -110,6 +111,25 @@ function ProjectsMap(props: ProjectsMapProps) {
mobileOS,
};

useEffect(() => {
if (props.page === 'project-details') return;
//Wrapping the logic in Promise.resolve().then() defers the map-related code until after synchronous tasks finish,
//Giving the map time to initialize fully. This ensures mapRef.current is ready for interaction.
Promise.resolve().then(() => {
if (mapRef.current) {
const map = mapRef.current.getMap
? mapRef.current.getMap()
: mapRef.current;
zoomOutMap(map, () => {
handleViewStateChange({
...map.getCenter(),
zoom: map.getZoom(),
});
});
}
});
}, [props.page]);

const onMove = useCallback(
(evt: ViewStateChangeEvent) => {
handleViewStateChange(evt.viewState);
Expand Down
9 changes: 4 additions & 5 deletions src/utils/mapsV2/zoomToProjectSite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ import type { MapRef } from '../../features/common/types/projectv2';

import * as turf from '@turf/turf';
import { DEFAULT_VIEW_STATE } from '../../features/projectsV2/ProjectsMapContext';
import { MAIN_MAP_ANIMATION_DURATIONS } from '../projectV2';

export function zoomOutMap(map: Map, callback: () => void) {
map.flyTo({
center: [DEFAULT_VIEW_STATE.longitude, DEFAULT_VIEW_STATE.latitude],
zoom: 2,
duration: 1600,
zoom: DEFAULT_VIEW_STATE.zoom,
duration: MAIN_MAP_ANIMATION_DURATIONS.ZOOM_OUT,
});

map.once('moveend', () => {
callback();
});
map.once('moveend', () => callback());
}
export function zoomInToProjectSite(
mapRef: MapRef,
Expand Down
5 changes: 5 additions & 0 deletions src/utils/projectV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export type MobileOs = 'android' | 'ios' | undefined;

const paramsToDelete = ['ploc', 'backNavigationUrl', 'site'];

export const MAIN_MAP_ANIMATION_DURATIONS = {
ZOOM_OUT: 1600,
ZOOM_IN: 4000,
};

type RouteParams = {
siteId?: string | null;
plocId?: string | null;
Expand Down