Improve place routing and loading

* Normalize OSM POIs and always use and store the OSM type and tags
* Pass place objects to place route, do not load from API if passed
* Construct place URLs with osm prefix including the type
* Load specific type from API when given
This commit is contained in:
2026-01-20 16:03:51 +07:00
parent 598ac5e587
commit 42bf8455e5
5 changed files with 83 additions and 55 deletions

View File

@@ -147,7 +147,7 @@ export default class MapComponent extends Component {
clearTimeout(locateTimeout);
locateTimeout = null;
}
// Remove listener
try {
if (locateListenerKey) {
@@ -181,7 +181,7 @@ export default class MapComponent extends Component {
resolution,
coordinates
);
const diameterInMeters = (accuracy || 50) * 2;
const diameterInMeters = (accuracy || 50) * 2;
const diameterInPixels = diameterInMeters / pointResolution;
this.locationOverlayElement.style.width = `${diameterInPixels}px`;
@@ -248,7 +248,7 @@ export default class MapComponent extends Component {
// 4. Start Following
locateListenerKey = geolocation.on('change:position', zoomToLocation);
// 5. Set Safety Timeout (10s)
locateTimeout = setTimeout(() => {
stopLocating();
@@ -425,12 +425,10 @@ export default class MapComponent extends Component {
// Sort by distance from click
pois = pois
.map((p) => {
// Use center lat/lon for ways/relations if available, else lat/lon
const pLat = p.lat || p.center?.lat;
const pLon = p.lon || p.center?.lon;
// p is already normalized by service, so lat/lon are at top level
return {
...p,
_distance: pLat && pLon ? getDistance(lat, lon, pLat, pLon) : 9999,
_distance: getDistance(lat, lon, p.lat, p.lon),
};
})
.sort((a, b) => a._distance - b._distance);
@@ -442,9 +440,9 @@ export default class MapComponent extends Component {
// 1. Exact Name Match
matchedPlace = pois.find(
(p) =>
p.tags &&
(p.tags.name === selectedFeatureName ||
p.tags['name:en'] === selectedFeatureName)
p.osmTags &&
(p.osmTags.name === selectedFeatureName ||
p.osmTags['name:en'] === selectedFeatureName)
);
// 2. If no exact match, look for VERY close (<=20m) and matching type
@@ -454,9 +452,9 @@ export default class MapComponent extends Component {
// Check type compatibility if available
// (visual tile 'class' is often 'cafe', osm tag is 'amenity'='cafe')
const pType =
topCandidate.tags.amenity ||
topCandidate.tags.shop ||
topCandidate.tags.tourism;
topCandidate.osmTags.amenity ||
topCandidate.osmTags.shop ||
topCandidate.osmTags.tourism;
if (
selectedFeatureType &&
pType &&

View File

@@ -172,7 +172,8 @@ export default class PlacesSidebar extends Component {
@selectedPlace.osmTags.amenity
@selectedPlace.osmTags.shop
@selectedPlace.osmTags.tourism
"Point of Interest"
@selectedPlace.osmTags.leisure
@selectedPlace.osmTags.historic
}}
{{#if @selectedPlace.description}}
{{@selectedPlace.description}}
@@ -241,15 +242,17 @@ export default class PlacesSidebar extends Component {
{{on "click" (fn this.selectPlace place)}}
>
<div class="place-name">{{or
place.tags.name
place.tags.name:en
place.title
place.osmTags.name
place.osmTags.name:en
"Unnamed Place"
}}</div>
<div class="place-type">{{or
place.tags.amenity
place.tags.shop
place.tags.tourism
"Point of Interest"
place.osmTags.amenity
place.osmTags.shop
place.osmTags.tourism
place.osmTags.leisure
place.osmTags.historic
}}</div>
</button>
</li>