Skip to content
Open
Changes from all 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
80 changes: 78 additions & 2 deletions src/components/maps/GlobalMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import { MapToolbar } from './MapToolbar'
import { SelectedFeature } from './AreaActiveMarker'
import { useRouter } from 'next/navigation'
import { useUrlParams } from '@/js/hooks/useUrlParams'
import Spinner from '@/components/ui/Spinner'
import { Button } from '@/components/ui/Button'
import { toast } from 'react-toastify'

export interface CameraInfo {
center: {
Expand Down Expand Up @@ -68,6 +71,10 @@ export const GlobalMap: React.FC<GlobalMapProps> = ({
heatmap: false,
crags: true
})

const [isLoading, setIsLoading] = useState(true)
const [hasError, setHasError] = useState(false)

const router = useRouter()
const urlParams = useUrlParams()

Expand Down Expand Up @@ -95,6 +102,9 @@ export const GlobalMap: React.FC<GlobalMapProps> = ({
if (e.target == null) return
setMapInstance(e.target)

setIsLoading(false)
setHasError(false)

Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace on line 107 should be removed to maintain clean code formatting.

Suggested change

Copilot uses AI. Check for mistakes.
// Only apply jumpTo if initial values are defined
if (initialCenter != null && initialZoom != null) {
e.target.jumpTo({ center: initialCenter, zoom: initialZoom ?? 6 })
Expand All @@ -103,6 +113,39 @@ export const GlobalMap: React.FC<GlobalMapProps> = ({
}
}, [initialCenter, initialZoom, initialViewState])

useEffect(() => {
if (!isLoading) return
const timeout = setTimeout(() => {
setHasError(true)
setIsLoading(false)
toast.error('Map load timeout')
}, 10000)
return () => clearTimeout(timeout)
}, [isLoading])

useEffect(() => {
if (!mapInstance) return
const handleError = (err: any) => {
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error parameter type is 'any' which bypasses type safety. Consider using a more specific type like 'Error' or 'MapboxError' if available from the map library.

Suggested change
const handleError = (err: any) => {
const handleError = (err: Error) => {

Copilot uses AI. Check for mistakes.
console.error('Map error:', err)
setHasError(true)
setIsLoading(false)
toast.error('Failed to load map')
}
mapInstance.on('error', handleError)
return () => {
mapInstance.off('error', handleError)
}
}, [mapInstance])

const handleReload = () => {
setIsLoading(true)
setHasError(false)
if (mapInstance) {
mapInstance.remove()
setMapInstance(null)
}
}

/**
* Handle click event on the map. Place a marker on the map and activate the side drawer.
*/
Expand Down Expand Up @@ -215,7 +258,34 @@ export const GlobalMap: React.FC<GlobalMapProps> = ({

return (
<div className='relative w-full h-full'>
<Map
{hasError && (
<div className="absolute inset-0 flex items-center justify-center bg-white/20 ">
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing space inside the className string should be removed for cleaner code.

Suggested change
<div className="absolute inset-0 flex items-center justify-center bg-white/20 ">
<div className="absolute inset-0 flex items-center justify-center bg-white/20">

Copilot uses AI. Check for mistakes.
<div className="flex flex-col items-center justify-center bg-white rounded-xl shadow-lg border border-red-200 w-80 h-72 p-6">
<svg
className="w-12 h-12 text-red-600 mb-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M18.364 5.636l-12.728 12.728M5.636 5.636l12.728 12.728" />
</svg>
<p className="text-red-700 font-semibold text-lg mb-2 text-center">
Error loading map
</p>
<p className="text-gray-600 text-sm mb-6 text-center">
Please try reloading the map.
</p>
<Button
label="Reboot"
onClick={handleReload}
className="btn-secondary px-6 py-2"
/>
</div>
</div>
)}

{!hasError &&<Map
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space between '&&' and '<Map' reduces readability. Add a space for proper formatting.

Suggested change
{!hasError &&<Map
{!hasError && <Map

Copilot uses AI. Check for mistakes.
id='global-map'
onLoad={onLoad}
onDragStart={() => setCursor('move')}
Expand All @@ -235,6 +305,12 @@ export const GlobalMap: React.FC<GlobalMapProps> = ({
cooperativeGestures={showFullscreenControl}
interactiveLayerIds={['crag-markers', 'crag-name-labels', 'area-boundaries', 'organizations']}
>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-white/80 z-50">
<Spinner/>
<p className="ml-3">Loading map...</p>
</div>
)}
<MapToolbar layerState={dataLayersDisplayState} onChange={setDataLayersDisplayState} />
<MapLayersSelector emit={updateMapLayer} />
<ScaleControl unit='imperial' style={{ marginBottom: 10 }} position='bottom-left' />
Expand All @@ -253,7 +329,7 @@ export const GlobalMap: React.FC<GlobalMapProps> = ({
<HoverCard {...hoverInfo} onClick={onHoverCardClick} />
)}
{children}
</Map>
</Map>}
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The closing JSX brace should be on the same line as '' or properly indented on a new line for better readability.

Suggested change
</Map>}
</Map>
}

Copilot uses AI. Check for mistakes.
</div>
)
}
Expand Down