feat: enhance map interface with arrivals overlay and nearby stops display

This commit is contained in:
2026-06-01 17:25:25 +08:00
parent 385dd6af3c
commit c6704c9f70
2 changed files with 145 additions and 1 deletions
+94
View File
@@ -175,6 +175,93 @@ button:hover {
margin-bottom: 0.8rem;
}
.map-wrap {
position: relative;
margin-bottom: 0.8rem;
}
.map-wrap .map-panel {
margin-bottom: 0;
}
.map-arrivals-overlay {
position: absolute;
right: 0.7rem;
bottom: 0.7rem;
width: min(320px, calc(100% - 1.4rem));
padding: 0.62rem 0.72rem;
background: rgba(31, 26, 19, 0.84);
color: #f8edd5;
border: 1px solid rgba(251, 219, 180, 0.35);
border-radius: 12px;
backdrop-filter: blur(4px);
box-shadow: 0 10px 20px rgba(17, 13, 9, 0.25);
}
.map-arrivals-overlay h3 {
font-size: 0.94rem;
margin-bottom: 0.2rem;
}
.map-overlay-stop {
margin: 0 0 0.45rem;
font-size: 0.78rem;
color: #e8cfab;
}
.map-arrivals-list {
margin: 0;
padding: 0;
list-style: none;
display: grid;
gap: 0.34rem;
}
.map-arrivals-list li {
display: grid;
grid-template-columns: auto auto;
justify-content: space-between;
gap: 0.15rem 0.6rem;
align-items: baseline;
font-size: 0.83rem;
}
.map-arrivals-list li strong {
color: #ffd79f;
}
.map-arrivals-list li small {
grid-column: 1 / -1;
color: #f1ddbe;
font-size: 0.74rem;
}
.map-overlay-empty {
margin: 0;
font-size: 0.8rem;
color: #ead8bb;
}
.map-overlay-fallback-list {
margin: 0.45rem 0 0;
padding: 0;
list-style: none;
display: grid;
gap: 0.3rem;
}
.map-overlay-fallback-list li {
display: flex;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
font-size: 0.8rem;
}
.map-overlay-fallback-list li strong {
color: #ffd79f;
}
.map-hint {
margin: 0 0 0.8rem;
color: var(--ink-soft);
@@ -361,6 +448,13 @@ button:hover {
height: min(50vh, 340px);
}
.map-arrivals-overlay {
right: 0.5rem;
left: 0.5rem;
width: auto;
bottom: 0.5rem;
}
.panel {
padding: 0.85rem;
}
+51 -1
View File
@@ -25,6 +25,17 @@
let nearbyStopMarkers = [];
let isMapClickPicking = false;
$: mapArrivals =
selectedStop && arrivalsStopCode === selectedStop.code
? services.slice(0, 4).map((service) => ({
serviceNo: service?.ServiceNo || "?",
next: minutesUntil(service?.NextBus?.EstimatedArrival),
following: minutesUntil(service?.NextBus2?.EstimatedArrival)
}))
: [];
$: overlayNearbyStops = nearbyStops.slice(0, 3);
function setStatus(text, state = "") {
statusText = text;
statusState = state;
@@ -446,7 +457,46 @@
<p class="map-hint">Tip: tap anywhere on the map to check the nearest stop and refresh arrivals around that point.</p>
<div class="map-panel" bind:this={mapContainer}></div>
<div class="map-wrap">
<div class="map-panel" bind:this={mapContainer}></div>
<aside class="map-arrivals-overlay" aria-live="polite">
<h3>Arrivals</h3>
<p class="map-overlay-stop">
{#if selectedStop}
{selectedStop.code} - {selectedStop.description}
{:else}
No stop selected
{/if}
</p>
{#if loadingArrivals}
<p class="map-overlay-empty">Loading arrivals...</p>
{:else if mapArrivals.length > 0}
<ul class="map-arrivals-list">
{#each mapArrivals as item}
<li>
<strong>{item.serviceNo}</strong>
<span>{item.next}</span>
<small>Then {item.following}</small>
</li>
{/each}
</ul>
{:else if overlayNearbyStops.length > 0}
<p class="map-overlay-empty">Nearby stops</p>
<ul class="map-overlay-fallback-list">
{#each overlayNearbyStops as stop}
<li>
<strong>{stop.code}</strong>
<span>{formatDistance(stop.distanceMeters)}</span>
</li>
{/each}
</ul>
{:else}
<p class="map-overlay-empty">Waiting for location to load stops...</p>
{/if}
</aside>
</div>
<div class="stop-meta">
<div class="meta-item">