feat(ui,roundtrip): modern neutral “Apple Glass” UI, scenic round trips, and isochrone guidance
Some checks failed
build-and-push / docker (push) Failing after 10m2s
Some checks failed
build-and-push / docker (push) Failing after 10m2s
- UI (neutral minimal, glass-like)
- Rewrote app shell and control panel in [app/web/static/index.html](cci:7://file:///home/pedan/freemoto/app/web/static/index.html:0:0-0:0)
- Modernized responsive styles in [app/web/static/styles.css](cci:7://file:///home/pedan/freemoto/app/web/static/styles.css:0:0-0:0)
- Proper internal scrolling for control panel, suggestions, waypoints, and directions sheet
- Improved dark mode, spacing, and visual polish
- Round Trip generation
- Direction preference (N/E/S/W) with biased waypoint bearings ([route.js](cci:7://file:///home/pedan/freemoto/app/web/static/route.js:0:0-0:0))
- Ferry avoidance by default on round trips; added strong ferry cost
- Coastal safety: reverse-geocode water check and automatic inland adjustment for generated waypoints
- New “Scenic optimizer” option: generate candidate loops, route them, score twistiness, pick the best
- Heading-change/turn-density based scoring using decoded polyline
- Isochrone-guided loops
- Backend: added `/isochrone` proxy in [app/web/main.go](cci:7://file:///home/pedan/freemoto/app/web/main.go:0:0-0:0) (derives Valhalla base from `VALHALLA_URL`)
- Frontend: optional “Use isochrone guidance” + time (minutes); sample preferred sector of polygon
- Settings persistence and live updates
- Direction, scenic, isochrone, and distance persist via localStorage
- Changing options regenerates round trips when enabled
- Docker/Build
- Confirmed multi-arch build (amd64/arm64) and push to git.ztsw.de/pedan/freemoto/freemoto-web:latest
Refs: [index.html](cci:7://file:///home/pedan/freemoto/app/web/static/index.html:0:0-0:0), [styles.css](cci:7://file:///home/pedan/freemoto/app/web/static/styles.css:0:0-0:0), [route.js](cci:7://file:///home/pedan/freemoto/app/web/static/route.js:0:0-0:0), [main.js](cci:7://file:///home/pedan/freemoto/app/web/static/main.js:0:0-0:0), [app/web/main.go](cci:7://file:///home/pedan/freemoto/app/web/main.go:0:0-0:0), [Dockerfile](cci:7://file:///home/pedan/freemoto/Dockerfile:0:0-0:0)
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
<link href="/styles.css?v=20250918" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- App Bar -->
|
||||
<!-- App Bar (Neutral minimal, glassy) -->
|
||||
<header class="appbar navbar px-3">
|
||||
<div class="container-fluid d-flex align-items-center justify-content-between">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
@@ -20,11 +20,11 @@
|
||||
<span id="summaryPill" class="badge rounded-pill text-bg-light d-none"></span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<button class="btn btn-outline-secondary btn-sm" id="clearRouteBtn" title="Clear route">Clear</button>
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="Zoom controls">
|
||||
<button class="btn btn-outline-secondary" id="zoomOutBtn" title="Zoom out">−</button>
|
||||
<button class="btn btn-outline-secondary" id="zoomInBtn" title="Zoom in">+</button>
|
||||
</div>
|
||||
<button class="btn btn-outline-secondary btn-sm" id="clearRouteBtn" title="Clear route">Clear</button>
|
||||
<button class="btn btn-outline-secondary btn-sm" id="themeToggle" title="Toggle dark mode">🌙</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,12 +33,11 @@
|
||||
<!-- Map canvas -->
|
||||
<div id="map" aria-label="Map"></div>
|
||||
|
||||
<!-- Control Drawer: overlay on mobile, sidebar on desktop -->
|
||||
<!-- Control Panel (neutral, glassy, scrollable) -->
|
||||
<aside class="nav-panel shadow">
|
||||
<div class="d-flex align-items-center justify-content-between mb-2">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge text-bg-primary">Beta</span>
|
||||
<span class="fw-semibold">Motorcycle Route Planner</span>
|
||||
<span class="fw-semibold">Planner</span>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-secondary d-none d-md-inline" onclick="resetMarkers()">Reset</button>
|
||||
</div>
|
||||
@@ -46,14 +45,12 @@
|
||||
<div id="routeInfoCard" class="alert alert-info d-none" role="alert"></div>
|
||||
<div id="nextManeuverBanner" class="alert alert-secondary py-2 px-3 d-none" role="status"></div>
|
||||
|
||||
<!-- Route inputs -->
|
||||
<!-- Route inputs (compact) -->
|
||||
<div class="section-title mb-1">Route</div>
|
||||
<div class="row g-2 align-items-stretch">
|
||||
<div class="col-12">
|
||||
<div class="input-group position-relative">
|
||||
<span class="input-group-text" title="Start" aria-label="Start">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="#0d6efd" viewBox="0 0 16 16"><path d="M8 16s6-5.686 6-10A6 6 0 1 0 2 6c0 4.314 6 10 6 10zm0-7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></svg>
|
||||
</span>
|
||||
<span class="input-group-text" title="Start" aria-label="Start">A</span>
|
||||
<input type="text" class="form-control" id="sourceInput" placeholder="Start address" autocomplete="off" />
|
||||
<button class="btn btn-outline-secondary" type="button" id="useCurrentSource" title="Use current location">📍</button>
|
||||
<div id="sourceSuggestions" class="list-group position-absolute w-100"></div>
|
||||
@@ -64,9 +61,7 @@
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="input-group position-relative">
|
||||
<span class="input-group-text" title="Destination" aria-label="Destination">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="#dc3545" viewBox="0 0 16 16"><path d="M14.778 2.222a.5.5 0 0 1 0 .707l-2.5 2.5a.5.5 0 0 1-.707 0l-2.5-2.5a.5.5 0 0 1 .707-.707L12 3.793l2.071-2.071a.5.5 0 0 1 .707 0z"/><path d="M2.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5z"/></svg>
|
||||
</span>
|
||||
<span class="input-group-text" title="Destination" aria-label="Destination">B</span>
|
||||
<input type="text" class="form-control" id="destInput" placeholder="Destination address" autocomplete="off" />
|
||||
<button class="btn btn-outline-secondary" type="button" id="useCurrentDest" title="Use current location">📍</button>
|
||||
<div id="destSuggestions" class="list-group position-absolute w-100"></div>
|
||||
@@ -96,12 +91,12 @@
|
||||
<button type="button" id="plotRouteBtn" class="btn btn-success">Plot Route</button>
|
||||
</div>
|
||||
|
||||
<!-- Options accordion -->
|
||||
<!-- Options (collapsible minimal) -->
|
||||
<div class="accordion mb-2" id="optionsAccordion">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#optionsCollapse" aria-expanded="false" aria-controls="optionsCollapse">
|
||||
Route Options
|
||||
Options
|
||||
</button>
|
||||
</h2>
|
||||
<div id="optionsCollapse" class="accordion-collapse collapse" data-bs-parent="#optionsAccordion">
|
||||
@@ -144,6 +139,43 @@
|
||||
<button type="button" id="roundTripBtn" class="btn btn-sm btn-outline-primary">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-2 align-items-center mb-2">
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="roundTripDir" class="form-label mb-0 text-muted">Direction preference</label>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<select id="roundTripDir" class="form-select form-select-sm">
|
||||
<option value="any" selected>Any</option>
|
||||
<option value="N">North</option>
|
||||
<option value="E">East</option>
|
||||
<option value="S">South</option>
|
||||
<option value="W">West</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-2 align-items-center mb-2">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="roundTripScenic">
|
||||
<label class="form-check-label" for="roundTripScenic">Scenic optimizer (twistier)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-2 align-items-center mb-2">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="roundTripIsochrone">
|
||||
<label class="form-check-label" for="roundTripIsochrone">Use isochrone guidance</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text">Time</span>
|
||||
<input type="number" min="10" max="240" step="5" id="isochroneMinutes" class="form-control" placeholder="Minutes" value="60">
|
||||
<span class="input-group-text">min</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-2 align-items-center mb-2">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-check">
|
||||
|
||||
Reference in New Issue
Block a user