feat(ui): mobile-first redesign — compact hero, inline submit button, map-first with collapsible list
- Hero: remove full-width mobile submit, add inline "Go" button next to locate
- Prediction cards: tighter mobile padding (px-3 py-3)
- Search filters: right-aligned toolbar, remove "X stations found" count and map toggle
- Map: initialize view immediately to avoid tile wiggle, skip recenter on fresh init
- Station list: hidden by default, toggled via "Stations {count}" pill above map
- Typography: hide desktop h1 on mobile, scale down section headings and spacing
- Footer: remove uppercase styling from headings and copyright line
- Filter popover: auto-close on fuel/radius/sort/brand selection
fix(llm): retry submit_overlay when events_cited is missing, extend Fuel Finder timeout with retries
- LlmOverlayService: add `minItems: 1` to events_cited schema, detect missing citations
in submit response, inject tool_result error and retry once with explicit prompt
- Log full raw_result context when no verified citations, capturing direction/confidence/reasoning
- FuelPriceService: add 3×1s retry with 60s timeout to batch price requests (was 30s no retry)
- Tests: cover successful retry recovery and rejection when retry also omits citations
This commit is contained in:
@@ -204,6 +204,20 @@ function initMap() {
|
||||
// map-polish:7 — replace default attribution control with custom ⓘ button
|
||||
mapInstance = L.map(mapContainer.value, {zoomControl: false, attributionControl: false})
|
||||
|
||||
// Set the initial view immediately so tiles load at the correct spot from
|
||||
// frame 1 — avoids the "wiggle" caused by setView running after the
|
||||
// container is already laid out and tiles are mid-load.
|
||||
const initialZoom = getZoomForRadius(props.radiusMiles)
|
||||
const initialCenter = props.origin?.lat != null && props.origin?.lng != null
|
||||
? [props.origin.lat, props.origin.lng]
|
||||
: props.stations.length
|
||||
? [props.stations[0].lat, props.stations[0].lng]
|
||||
: null
|
||||
if (initialCenter) {
|
||||
mapInstance.setView(initialCenter, initialZoom)
|
||||
hasInitialView = true
|
||||
}
|
||||
|
||||
// map-polish:5 — Carto Positron tile (cleaner than raw OSM)
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
|
||||
subdomains: 'abcd',
|
||||
@@ -230,7 +244,7 @@ function initMap() {
|
||||
locateUser()
|
||||
}
|
||||
|
||||
function renderMarkers() {
|
||||
function renderMarkers({skipRecenter = false} = {}) {
|
||||
if (!mapInstance || !markersLayer) return
|
||||
|
||||
markersLayer.clearLayers()
|
||||
@@ -262,6 +276,8 @@ function renderMarkers() {
|
||||
bounds.push([station.lat, station.lng])
|
||||
})
|
||||
|
||||
if (skipRecenter) return
|
||||
|
||||
const zoom = getZoomForRadius(props.radiusMiles)
|
||||
const center = props.origin?.lat != null && props.origin?.lng != null
|
||||
? [props.origin.lat, props.origin.lng]
|
||||
@@ -290,9 +306,10 @@ function destroyMap() {
|
||||
|
||||
async function openMap() {
|
||||
await nextTick()
|
||||
const wasFreshInit = !mapInstance
|
||||
initMap()
|
||||
mapInstance?.invalidateSize()
|
||||
renderMarkers()
|
||||
renderMarkers({skipRecenter: wasFreshInit})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user