Rework entry types: merge hotel into stay, transport with modes, auto-transport

- Type set is now activity/stay/transport/flight/rental/note; hotel, travel
  and immigration are removed with idempotent startup data migrations
  (hotel->stay, travel->transport, immigration->activity with flag prefix)
- Transport entries carry an optional mode (train/bus/ferry/taxi/drive/other)
  that drives the chip/map icon; route stops expose transport_mode
- Creating a stay auto-creates a bridging transport to its neighbouring
  stays unless a transport/flight already covers the gap (one-shot)
- Summary: transports count replaces hotels/travelLegs
This commit is contained in:
2026-07-19 17:47:21 +07:00
parent b066e7b885
commit d393e16ae1
17 changed files with 469 additions and 62 deletions
+4 -4
View File
@@ -2,7 +2,7 @@
// per-leg km labels, and a leg-by-leg list. Graceful empty state when the
// trip has no located entries yet. Uses the /route response from tctx.route.
import { el } from '../dom.js';
import { typeInfo } from '../format.js';
import { typeInfo, entryIcon } from '../format.js';
export function renderMap(tctx) {
const route = tctx.route || { stops: [], legs: [], totalKm: 0 };
@@ -65,7 +65,7 @@ function initMap(mapDiv, route, stops) {
const info = typeInfo(stop.type);
L.marker(points[i], { icon: numberedIcon(L, i + 1, info.color) })
.addTo(map)
.bindPopup(popupHtml(stop, info));
.bindPopup(popupHtml(stop, info, entryIcon(stop)));
});
// One polyline per measured leg, styled by mode (air = dashed blue, ground =
@@ -128,9 +128,9 @@ function kmLabel(L, km) {
}
// Built from server-provided fields; escape to keep the popup injection-safe.
function popupHtml(stop, info) {
function popupHtml(stop, info, icon) {
const isAirport = stop.kind === 'airport' && stop.code;
const heading = isAirport ? `${info.icon} ${esc(stop.code)}` : `${info.icon} ${esc(stop.title)}`;
const heading = isAirport ? `${icon} ${esc(stop.code)}` : `${icon} ${esc(stop.title)}`;
const sub = isAirport
? `${esc(info.label)} · ${esc(stop.date)}${stop.title ? ` · ${esc(stop.title)}` : ''}`
: `${esc(info.label)} · ${esc(stop.date)}`;