Refactor client UI with shadcn heatmap layout
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
|
||||
import type { LatLng } from '@/types/api'
|
||||
|
||||
function geolocationErrorMessage(error: GeolocationPositionError): string {
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
return 'Location access denied. Enable it to view nearby pings.'
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
return 'Unable to determine your position. Try again.'
|
||||
case error.TIMEOUT:
|
||||
return 'Timed out while fetching your location.'
|
||||
default:
|
||||
return 'Failed to retrieve your location.'
|
||||
}
|
||||
}
|
||||
|
||||
export function useUserLocation() {
|
||||
const [location, setLocation] = useState<LatLng | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [isRequesting, setIsRequesting] = useState<boolean>(false)
|
||||
const watchIdRef = useRef<number | null>(null)
|
||||
|
||||
const clearWatch = useCallback(() => {
|
||||
if (typeof navigator === 'undefined' || !navigator.geolocation) {
|
||||
return
|
||||
}
|
||||
if (watchIdRef.current !== null) {
|
||||
navigator.geolocation.clearWatch(watchIdRef.current)
|
||||
watchIdRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
const start = useCallback(() => {
|
||||
if (typeof navigator === 'undefined' || !navigator.geolocation) {
|
||||
setError('Geolocation is not supported in this browser.')
|
||||
setIsRequesting(false)
|
||||
return
|
||||
}
|
||||
|
||||
clearWatch()
|
||||
setIsRequesting(true)
|
||||
setError(null)
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
setLocation({ lat: position.coords.latitude, lng: position.coords.longitude })
|
||||
setIsRequesting(false)
|
||||
setError(null)
|
||||
},
|
||||
(geoError) => {
|
||||
setError(geolocationErrorMessage(geoError))
|
||||
setIsRequesting(false)
|
||||
},
|
||||
{ enableHighAccuracy: true, timeout: 10000 },
|
||||
)
|
||||
|
||||
const watchId = navigator.geolocation.watchPosition(
|
||||
(position) => {
|
||||
setLocation({ lat: position.coords.latitude, lng: position.coords.longitude })
|
||||
setError(null)
|
||||
setIsRequesting(false)
|
||||
},
|
||||
(geoError) => {
|
||||
setError(geolocationErrorMessage(geoError))
|
||||
setIsRequesting(false)
|
||||
},
|
||||
{ enableHighAccuracy: true, maximumAge: 15000, timeout: 10000 },
|
||||
)
|
||||
|
||||
watchIdRef.current = watchId
|
||||
}, [clearWatch])
|
||||
|
||||
useEffect(() => {
|
||||
start()
|
||||
|
||||
return () => {
|
||||
clearWatch()
|
||||
}
|
||||
}, [clearWatch, start])
|
||||
|
||||
return {
|
||||
location,
|
||||
error,
|
||||
isRequesting,
|
||||
refresh: start,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user