fix: Add coordinate validation to prevent Invalid LngLat errors

- Add isValidCoordinate() helper to validate lat/lng ranges
- Validate viewport center on map initialization
- Skip participants and waypoints with invalid coordinates
- Add validation to auto-center and fitToParticipants

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-25 21:28:34 -05:00
parent eeab19ceac
commit 39f8c83ba9
1 changed files with 47 additions and 9 deletions

View File

@ -24,6 +24,20 @@ const DEFAULT_VIEWPORT: MapViewport = {
zoom: 15,
};
// Validate coordinates are within valid ranges
function isValidCoordinate(lat: number, lng: number): boolean {
return (
typeof lat === 'number' &&
typeof lng === 'number' &&
!isNaN(lat) &&
!isNaN(lng) &&
lat >= -90 &&
lat <= 90 &&
lng >= -180 &&
lng <= 180
);
}
export default function MapView({
participants,
waypoints = [],
@ -45,6 +59,12 @@ export default function MapView({
useEffect(() => {
if (!mapContainer.current || map.current) return;
// Validate viewport center coordinates, fall back to default if invalid
const [lng, lat] = initialViewport.center;
const validCenter = isValidCoordinate(lat, lng)
? initialViewport.center
: DEFAULT_VIEWPORT.center;
map.current = new maplibregl.Map({
container: mapContainer.current,
style: {
@ -73,8 +93,8 @@ export default function MapView({
},
],
},
center: initialViewport.center,
zoom: initialViewport.zoom,
center: validCenter,
zoom: initialViewport.zoom || DEFAULT_VIEWPORT.zoom,
bearing: initialViewport.bearing ?? 0,
pitch: initialViewport.pitch ?? 0,
});
@ -133,6 +153,12 @@ export default function MapView({
if (!participant.location) return;
const { latitude, longitude } = participant.location;
// Skip invalid coordinates
if (!isValidCoordinate(latitude, longitude)) {
console.warn('Invalid coordinates for participant:', participant.id, latitude, longitude);
return;
}
let marker = currentMarkers.get(participant.id);
if (marker) {
@ -169,12 +195,15 @@ export default function MapView({
if (autoCenterOnUser && !hasCenteredOnUserRef.current && currentUserId) {
const currentUser = participants.find(p => p.id === currentUserId);
if (currentUser?.location && map.current) {
console.log('Auto-centering on user location:', currentUser.location.latitude, currentUser.location.longitude);
map.current.flyTo({
center: [currentUser.location.longitude, currentUser.location.latitude],
zoom: 16,
});
hasCenteredOnUserRef.current = true;
const { latitude, longitude } = currentUser.location;
if (isValidCoordinate(latitude, longitude)) {
console.log('Auto-centering on user location:', latitude, longitude);
map.current.flyTo({
center: [longitude, latitude],
zoom: 16,
});
hasCenteredOnUserRef.current = true;
}
}
}
}, [participants, mapLoaded, currentUserId, onParticipantClick, autoCenterOnUser]);
@ -197,6 +226,13 @@ export default function MapView({
// Add/update waypoint markers
waypoints.forEach((waypoint) => {
const { latitude, longitude } = waypoint.location;
// Skip invalid coordinates
if (!isValidCoordinate(latitude, longitude)) {
console.warn('Invalid coordinates for waypoint:', waypoint.id, latitude, longitude);
return;
}
let marker = currentWaypointMarkers.get(waypoint.id);
if (marker) {
@ -271,7 +307,9 @@ export default function MapView({
const fitToParticipants = () => {
if (!map.current || participants.length === 0) return;
const locatedParticipants = participants.filter((p) => p.location);
const locatedParticipants = participants.filter(
(p) => p.location && isValidCoordinate(p.location.latitude, p.location.longitude)
);
if (locatedParticipants.length === 0) return;
if (locatedParticipants.length === 1) {