mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 14:44:51 +02:00
fix(place): add reverse geocode fallback for place details
When a place is selected without osm_type/osm_id (e.g., clicking on a basemap label), trigger a reverse geocode to obtain the OSM identifiers. This enables fetching place details including boundary, wiki_summary, and other enriched data. The existing placeDetails useEffect will then fire once the osm_type/osm_id are available in the selectedPlace.raw object. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e42ed06a5c
commit
497a671504
2 changed files with 53 additions and 2 deletions
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import OpeningHours from "opening_hours"
|
import OpeningHours from "opening_hours"
|
||||||
import toast from "react-hot-toast"
|
import toast from "react-hot-toast"
|
||||||
import { useStore } from "../store"
|
import { useStore } from "../store"
|
||||||
import { fetchElevation, fetchPlaceDetails, fetchPlaceByWikidata, fetchDriveTime, fetchNearbyContacts, fetchLandclass } from "../api"
|
import { fetchElevation, fetchPlaceDetails, fetchPlaceByWikidata, fetchDriveTime, fetchNearbyContacts, fetchLandclass, fetchReverse } from "../api"
|
||||||
import { hasFeature } from "../config"
|
import { hasFeature } from "../config"
|
||||||
import { buildAddress } from "../utils/place"
|
import { buildAddress } from "../utils/place"
|
||||||
|
|
||||||
|
|
@ -328,6 +328,32 @@ export function PlaceCard({ place, variant = "preview", expanded = true, onToggl
|
||||||
return () => { cancelled = true }
|
return () => { cancelled = true }
|
||||||
}, [placeLat, placeLon])
|
}, [placeLat, placeLon])
|
||||||
|
|
||||||
|
// Reverse geocode to get OSM type/id if not present (e.g., basemap label clicks)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!hasFeature('has_nominatim_details')) return
|
||||||
|
if (osmType && osmId) return
|
||||||
|
if (placeLat == null || placeLon == null) return
|
||||||
|
// Skip for dropped pins - they get reverse geocoded by MapView
|
||||||
|
if (place?.source === 'map_click') return
|
||||||
|
|
||||||
|
const controller = new AbortController()
|
||||||
|
fetchReverse(placeLat, placeLon).then((result) => {
|
||||||
|
if (controller.signal.aborted) return
|
||||||
|
if (result?.raw?.osm_type && result?.raw?.osm_id) {
|
||||||
|
const current = useStore.getState().selectedPlace
|
||||||
|
if (current && current.lat === placeLat && current.lon === placeLon) {
|
||||||
|
// Merge OSM data into raw, preserving existing data
|
||||||
|
useStore.getState().setSelectedPlace({
|
||||||
|
...current,
|
||||||
|
raw: { ...current.raw, osm_type: result.raw.osm_type, osm_id: result.raw.osm_id }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return () => controller.abort()
|
||||||
|
}, [placeLat, placeLon, osmType, osmId, place?.source])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasFeature("has_nominatim_details") || !osmType || !osmId) { setPlaceDetails(null); return }
|
if (!hasFeature("has_nominatim_details") || !osmType || !osmId) { setPlaceDetails(null); return }
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import OpeningHours from 'opening_hours'
|
import OpeningHours from 'opening_hours'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { useStore } from '../store'
|
import { useStore } from '../store'
|
||||||
import { fetchElevation, fetchPlaceDetails, fetchPlaceByWikidata, fetchDriveTime, fetchNearbyContacts, fetchLandclass } from '../api'
|
import { fetchElevation, fetchPlaceDetails, fetchPlaceByWikidata, fetchDriveTime, fetchNearbyContacts, fetchLandclass, fetchReverse } from '../api'
|
||||||
import { hasFeature } from '../config'
|
import { hasFeature } from '../config'
|
||||||
import { buildAddress } from '../utils/place'
|
import { buildAddress } from '../utils/place'
|
||||||
|
|
||||||
|
|
@ -514,6 +514,31 @@ export default function PlaceDetail() {
|
||||||
return () => { cancelled = true }
|
return () => { cancelled = true }
|
||||||
}, [placeLat, placeLon])
|
}, [placeLat, placeLon])
|
||||||
|
|
||||||
|
// Reverse geocode to get OSM type/id if not present (e.g., basemap label clicks)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!hasFeature('has_nominatim_details')) return
|
||||||
|
if (selectedPlace?.raw?.osm_type && selectedPlace?.raw?.osm_id) return
|
||||||
|
if (placeLat == null || placeLon == null) return
|
||||||
|
// Skip for dropped pins - they get reverse geocoded by MapView
|
||||||
|
if (selectedPlace?.source === 'map_click') return
|
||||||
|
|
||||||
|
const controller = new AbortController()
|
||||||
|
fetchReverse(placeLat, placeLon).then((result) => {
|
||||||
|
if (controller.signal.aborted) return
|
||||||
|
if (result?.raw?.osm_type && result?.raw?.osm_id) {
|
||||||
|
const current = useStore.getState().selectedPlace
|
||||||
|
if (current && current.lat === placeLat && current.lon === placeLon) {
|
||||||
|
useStore.getState().setSelectedPlace({
|
||||||
|
...current,
|
||||||
|
raw: { ...current.raw, osm_type: result.raw.osm_type, osm_id: result.raw.osm_id }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return () => controller.abort()
|
||||||
|
}, [placeLat, placeLon, selectedPlace?.raw?.osm_type, selectedPlace?.raw?.osm_id, selectedPlace?.source])
|
||||||
|
|
||||||
|
|
||||||
// Fetch place details when place changes (if feature enabled)
|
// Fetch place details when place changes (if feature enabled)
|
||||||
const osmType = selectedPlace?.raw?.osm_type
|
const osmType = selectedPlace?.raw?.osm_type
|
||||||
const osmId = selectedPlace?.raw?.osm_id
|
const osmId = selectedPlace?.raw?.osm_id
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue