Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions front/app/components/EsriMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
getDefaultBasemapType,
getDefaultBasemap,
handleWebMapReferenceLayers,
createUserLocationGraphic,
} from './utils';

// Custom Esri styles
Expand Down Expand Up @@ -71,6 +72,7 @@ export type EsriMapProps = {
onClick?: (event: any, mapView: MapView) => void;
onHover?: (event: any, mapView: MapView) => void;
globalMapSettings: AppConfigurationMapSettings;
showUserLocation?: boolean;
};

const EsriMap = ({
Expand All @@ -84,6 +86,7 @@ const EsriMap = ({
webMapId,
initialData,
globalMapSettings,
showUserLocation = false,
}: EsriMapProps) => {
const locale = useLocale();
const isMobileOrSmaller = useBreakpoint('phone');
Expand Down Expand Up @@ -268,6 +271,55 @@ const EsriMap = ({
}
}, [appConfig?.data.attributes.settings.esri_integration?.api_key]);

// Handle user location
useEffect(() => {
if (!showUserLocation || !mapView) return;

let currentLocationGraphic: Graphic | null = null;
let watchId: number | null = null;

const updateUserLocation = (position: GeolocationPosition) => {
const { longitude, latitude } = position.coords;

// Remove existing location graphic if it exists
if (currentLocationGraphic) {
mapView.graphics.remove(currentLocationGraphic);
}

// Create new user location graphic
const locationGraphic = createUserLocationGraphic(longitude, latitude);
mapView.graphics.add(locationGraphic);
currentLocationGraphic = locationGraphic;
};

const handleLocationError = (error: GeolocationPositionError) => {
console.warn('Error getting user location:', error);
};

if ('geolocation' in navigator) {
// Use watchPosition for continuous location updates
watchId = navigator.geolocation.watchPosition(
updateUserLocation,
handleLocationError,
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 30000, // Cache location for 30 seconds
}
);
}

// Cleanup function to remove user location graphic and stop watching
return () => {
if (currentLocationGraphic) {
mapView.graphics.remove(currentLocationGraphic);
}
if (watchId !== null) {
navigator.geolocation.clearWatch(watchId);
}
};
}, [showUserLocation, mapView]);

return (
<>
<MapContainer
Expand Down
30 changes: 30 additions & 0 deletions front/app/components/EsriMap/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -713,3 +713,33 @@ export const goToLayerExtent = (
}
});
};

// Helper function to create user location marker
export const createUserLocationGraphic = (
longitude: number,
latitude: number
) => {
const point = new Point({
longitude,
latitude,
});

const symbol = new SimpleMarkerSymbol({
color: [51, 119, 255], // Blue color
size: 12,
outline: {
color: [255, 255, 255], // White outline
width: 2,
},
style: 'circle',
});

return new Graphic({
geometry: point,
symbol,
attributes: {
id: 'user-location',
title: 'Your Location',
},
});
};
11 changes: 7 additions & 4 deletions front/app/components/IdeasMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const IdeasMap = memo<Props>(
const { data: authUser } = useAuthUser();
const [searchParams] = useSearchParams();
const isMobileOrSmaller = useBreakpoint('phone');
const isTabletOrSmaller = useBreakpoint('tablet');

// Create div elements to use for inserting React components into Esri map popup
// Docs: https://developers.arcgis.com/javascript/latest/custom-ui/#introduction
Expand Down Expand Up @@ -164,23 +165,23 @@ const IdeasMap = memo<Props>(
// Map icon for ideas
const ideaIcon = useMemo(() => {
return getShapeSymbol({
shape: 'circle',
shape: isTabletOrSmaller ? 'triangle' : 'circle',
color: theme.colors.tenantPrimary,
outlineColor: colors.white,
outlineWidth: 2,
sizeInPx: 18,
});
}, [theme.colors.tenantPrimary]);
}, [theme.colors.tenantPrimary, isTabletOrSmaller]);

const ideaIconSecondary = useMemo(() => {
return getShapeSymbol({
shape: 'circle',
shape: isTabletOrSmaller ? 'triangle' : 'circle',
color: theme.colors.tenantSecondary,
outlineColor: colors.white,
outlineWidth: 2,
sizeInPx: 18,
});
}, [theme.colors.tenantSecondary]);
}, [theme.colors.tenantSecondary, isTabletOrSmaller]);

// Existing handling for dynamic container width
const { windowWidth } = useWindowSize();
Expand Down Expand Up @@ -537,6 +538,8 @@ const IdeasMap = memo<Props>(
onHover={onMapHover}
onClick={onMapClick}
id="e2e-ideas-map"
// Only show user location on mobile screens
showUserLocation={isTabletOrSmaller}
/>
<LayerHoverLabel
layer={mapConfig?.data.attributes.layers.find(
Expand Down