fix(geocoding): fix query param string parsing, location field mismatch, and distance_km normalization
- controller: @Query() params arrive as strings in NestJS - now explicitly
parseFloat() all numeric params (lat, lng, radius) before passing to service.
Also validates against NaN before hitting PostGIS.
- controller: reverse geocode now validates and throws 400 on invalid lat/lng.
- service: searchPlaces now normalizes all results to include:
- location: { lat, lng } nested object (frontend was crashing on place.location.lat)
- distance_km: pre-computed string field (frontend was reading undefined distance_km)
- latitude/longitude as actual floats (not decimal strings from DB)
- frontend (App.tsx): fixed map.flyTo() to read place.latitude/place.longitude
instead of the non-existent place.location.lat/lng.
- frontend (App.tsx): fixed search result click handler same way.
- frontend (App.tsx): fixed distance display to compute from res.distance (meters).
- entity: added missing source column to BasePlace entity.
This commit is contained in:
@@ -65,7 +65,12 @@ function App() {
|
||||
|
||||
if (data.results && data.results.length > 0 && map) {
|
||||
const place = data.results[0];
|
||||
map.flyTo({ center: [place.location.lng, place.location.lat], zoom: 15 });
|
||||
// API returns flat latitude/longitude fields (not a nested location object)
|
||||
const placeLng = parseFloat(place.longitude);
|
||||
const placeLat = parseFloat(place.latitude);
|
||||
if (!isNaN(placeLat) && !isNaN(placeLng)) {
|
||||
map.flyTo({ center: [placeLng, placeLat], zoom: 15 });
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Search failed", e);
|
||||
@@ -208,14 +213,14 @@ function App() {
|
||||
{searchResults.map((res) => (
|
||||
<div
|
||||
key={res.id}
|
||||
onClick={() => map?.flyTo({ center: [res.location.lng, res.location.lat], zoom: 16 })}
|
||||
onClick={() => { const rLng = parseFloat(res.longitude); const rLat = parseFloat(res.latitude); if (!isNaN(rLat) && !isNaN(rLng)) map?.flyTo({ center: [rLng, rLat], zoom: 16 }); }}
|
||||
style={{ padding: '8px', borderBottom: '1px solid var(--glass-border)', cursor: 'pointer', fontSize: '0.85rem' }}
|
||||
className="search-result-item"
|
||||
>
|
||||
<div style={{ fontWeight: 600 }}>{res.name_ar || res.name}</div>
|
||||
{res.address && <div style={{ fontSize: '0.75rem', opacity: 0.7 }}>{res.address}</div>}
|
||||
<div style={{ fontSize: '0.7rem', color: '#3b82f6', marginTop: '2px' }}>
|
||||
{res.distance_km} km away | {res.source.replace('_', ' ')}
|
||||
{res.distance ? (Number(res.distance) / 1000).toFixed(1) + ' km away' : ''} | {(res.source || '').replace('_', ' ')}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user