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:
@@ -38,6 +38,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
var roundTripKm = document.getElementById('roundTripKm');
|
||||
var roundTripBtn = document.getElementById('roundTripBtn');
|
||||
var roundTripNoRepeat = document.getElementById('roundTripNoRepeat');
|
||||
var roundTripDir = document.getElementById('roundTripDir');
|
||||
var roundTripScenic = document.getElementById('roundTripScenic');
|
||||
var roundTripIsochrone = document.getElementById('roundTripIsochrone');
|
||||
var isochroneMinutes = document.getElementById('isochroneMinutes');
|
||||
if (zoomInBtn && zoomOutBtn) {
|
||||
zoomInBtn.addEventListener('click', function() {
|
||||
map.zoomIn();
|
||||
@@ -156,6 +160,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
roundTripKm.addEventListener('change', function(){
|
||||
var v = parseInt(roundTripKm.value, 10);
|
||||
if (!isNaN(v)) localStorage.setItem('freemoto-roundtrip-km', String(v));
|
||||
if (roundTripToggle && roundTripToggle.checked && typeof window.createRoundTrip === 'function') {
|
||||
window.createRoundTrip();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (roundTripBtn) {
|
||||
@@ -174,6 +181,54 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
}
|
||||
|
||||
// Direction preference persistence and live update
|
||||
if (roundTripDir) {
|
||||
var savedDir = localStorage.getItem('freemoto-roundtrip-dir') || 'any';
|
||||
roundTripDir.value = savedDir;
|
||||
roundTripDir.addEventListener('change', function(){
|
||||
localStorage.setItem('freemoto-roundtrip-dir', roundTripDir.value);
|
||||
if (roundTripToggle && roundTripToggle.checked && typeof window.createRoundTrip === 'function') {
|
||||
// Regenerate the round trip to reflect new direction
|
||||
window.createRoundTrip();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Scenic optimizer toggle
|
||||
if (roundTripScenic) {
|
||||
var savedScenic = localStorage.getItem('freemoto-roundtrip-scenic') === '1';
|
||||
roundTripScenic.checked = savedScenic;
|
||||
roundTripScenic.addEventListener('change', function(){
|
||||
localStorage.setItem('freemoto-roundtrip-scenic', roundTripScenic.checked ? '1' : '0');
|
||||
if (roundTripToggle && roundTripToggle.checked && typeof window.createRoundTrip === 'function') {
|
||||
window.createRoundTrip();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Isochrone toggle and minutes
|
||||
if (roundTripIsochrone) {
|
||||
var savedIso = localStorage.getItem('freemoto-roundtrip-isochrone') === '1';
|
||||
roundTripIsochrone.checked = savedIso;
|
||||
roundTripIsochrone.addEventListener('change', function(){
|
||||
localStorage.setItem('freemoto-roundtrip-isochrone', roundTripIsochrone.checked ? '1' : '0');
|
||||
if (roundTripToggle && roundTripToggle.checked && typeof window.createRoundTrip === 'function') {
|
||||
window.createRoundTrip();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (isochroneMinutes) {
|
||||
var savedMin = parseInt(localStorage.getItem('freemoto-isochrone-minutes') || '60', 10);
|
||||
if (!isNaN(savedMin)) isochroneMinutes.value = savedMin;
|
||||
isochroneMinutes.addEventListener('change', function(){
|
||||
var v = parseInt(isochroneMinutes.value, 10);
|
||||
if (!isNaN(v)) localStorage.setItem('freemoto-isochrone-minutes', String(v));
|
||||
if (roundTripToggle && roundTripToggle.checked && typeof window.createRoundTrip === 'function') {
|
||||
window.createRoundTrip();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Swap start/end like Google Maps
|
||||
(function(){
|
||||
var swapBtn = document.getElementById('swapBtn');
|
||||
|
||||
Reference in New Issue
Block a user