mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-02-06 09:55:47 +00:00
110 lines
2.8 KiB
TypeScript
110 lines
2.8 KiB
TypeScript
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
import { useState, useEffect } from 'react'
|
|
|
|
interface GeocodeResult {
|
|
street?: string
|
|
housenumber?: string
|
|
postcode?: string
|
|
city?: string
|
|
town?: string
|
|
village?: string
|
|
district?: string
|
|
suburb?: string
|
|
neighbourhood?: string
|
|
state?: string
|
|
country?: string
|
|
}
|
|
|
|
interface GeocodeFeature {
|
|
properties: GeocodeResult
|
|
}
|
|
|
|
interface GeocodeResponse {
|
|
features?: GeocodeFeature[]
|
|
}
|
|
|
|
export function useReverseGeocode(
|
|
coordinates?: [number, number] | null,
|
|
enabled = true,
|
|
accuracy: 'municipality' | 'street' | 'house_number' = 'municipality',
|
|
) {
|
|
const [address, setAddress] = useState('')
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
|
useEffect(() => {
|
|
if (!enabled || !coordinates) {
|
|
setAddress('')
|
|
return
|
|
}
|
|
|
|
const [longitude, latitude] = coordinates
|
|
if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) {
|
|
return
|
|
}
|
|
|
|
const reverseGeocode = async () => {
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
try {
|
|
const response = await fetch(
|
|
`https://photon.komoot.io/reverse?lat=${latitude}&lon=${longitude}&lang=de&limit=1`,
|
|
)
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Geocoding request failed')
|
|
}
|
|
|
|
const data = (await response.json()) as GeocodeResponse
|
|
|
|
if (data.features && data.features.length > 0) {
|
|
const props = data.features[0].properties
|
|
const municipality = props.city ?? props.town ?? props.village
|
|
|
|
let addressString = ''
|
|
|
|
switch (accuracy) {
|
|
case 'municipality':
|
|
addressString = municipality ?? ''
|
|
break
|
|
case 'street':
|
|
if (props.street && municipality) {
|
|
addressString = `${props.street}, ${municipality}`
|
|
} else {
|
|
addressString = municipality ?? ''
|
|
}
|
|
break
|
|
case 'house_number':
|
|
if (props.street && props.housenumber && municipality) {
|
|
addressString = `${props.street} ${props.housenumber}, ${municipality}`
|
|
} else if (props.street && municipality) {
|
|
addressString = `${props.street}, ${municipality}`
|
|
} else {
|
|
addressString = municipality ?? ''
|
|
}
|
|
break
|
|
}
|
|
|
|
setAddress(addressString)
|
|
} else {
|
|
setAddress('')
|
|
}
|
|
} catch (err) {
|
|
if (err instanceof Error) {
|
|
setError(err.message)
|
|
setAddress('')
|
|
} else {
|
|
throw err
|
|
}
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
void reverseGeocode()
|
|
}, [coordinates, enabled, accuracy])
|
|
|
|
return { address, loading, error }
|
|
}
|