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:
@@ -7,6 +7,7 @@ import { api } from '../api.js';
|
||||
import { el, clear, mount, toast } from '../dom.js';
|
||||
import {
|
||||
ENTRY_TYPE_LIST,
|
||||
TRANSPORT_MODES,
|
||||
splitModeLabel,
|
||||
typeInfo,
|
||||
formatDate,
|
||||
@@ -183,6 +184,7 @@ export function openDayEditor(tctx, date) {
|
||||
fields.start.value = entry.start_time || '';
|
||||
fields.end.value = entry.end_time || '';
|
||||
fields.endDate.value = entry.end_date || '';
|
||||
fields.mode.value = entry.transport_mode || '';
|
||||
fields.cost.prefill(entry);
|
||||
// Flight segments (load() triggers the flight-route onChange -> UI sync).
|
||||
fields.flightRoute.load(Array.isArray(entry.segments) ? entry.segments : []);
|
||||
@@ -223,6 +225,18 @@ export function openDayEditor(tctx, date) {
|
||||
locWrap.append(locInput, locResults, locSelected);
|
||||
const locationField = el('label', { class: 'field' }, el('span', { class: 'field-label' }, 'Location'), locWrap);
|
||||
|
||||
// ----- Transport mode (shown only for transport entries) -----
|
||||
// Declared before the flight/rental subsections below: their onChange
|
||||
// callbacks can call syncTypeUI() during construction (see the TDZ note
|
||||
// below it), so anything syncTypeUI touches must already exist.
|
||||
const modeSelect = el(
|
||||
'select',
|
||||
{ class: 'input' },
|
||||
el('option', { value: '' }, '—'),
|
||||
...TRANSPORT_MODES.map((m) => el('option', { value: m.value }, `${m.icon} ${m.label}`)),
|
||||
);
|
||||
const modeField = el('label', { class: 'field' }, el('span', { class: 'field-label' }, 'Mode'), modeSelect);
|
||||
|
||||
// ----- Flight route subsection (shown only for flight entries) -----
|
||||
// The sub-modules fire onChange during construction (load of initial
|
||||
// state), before the section elements below exist — gate until wired.
|
||||
@@ -253,6 +267,7 @@ export function openDayEditor(tctx, date) {
|
||||
const type = typeSelect.value;
|
||||
flightSection.style.display = type === 'flight' ? '' : 'none';
|
||||
rentalSection.style.display = type === 'rental' ? '' : 'none';
|
||||
modeField.style.display = type === 'transport' ? '' : 'none';
|
||||
locationField.style.display = type === 'flight' && flightRoute.hasSegments() ? 'none' : '';
|
||||
// Stays emphasise an end date ("until"); other types call it "End date".
|
||||
endDateLabel.textContent = type === 'stay' ? 'Until' : 'End date';
|
||||
@@ -267,7 +282,7 @@ export function openDayEditor(tctx, date) {
|
||||
|
||||
fields = {
|
||||
type: typeSelect, title: titleInput, details: detailsInput, start: startInput, end: endInput,
|
||||
endDate: endDateInput,
|
||||
endDate: endDateInput, mode: modeSelect,
|
||||
locInput, locResults, locSelected,
|
||||
cost: costForm, flightRoute, rentalDetails,
|
||||
};
|
||||
@@ -334,6 +349,10 @@ export function openDayEditor(tctx, date) {
|
||||
payload.rental = null;
|
||||
}
|
||||
|
||||
// Transport mode (transport entries only). Clear it otherwise so
|
||||
// changing an entry's type away from transport drops any prior mode.
|
||||
payload.transport_mode = typeSelect.value === 'transport' ? (modeSelect.value || null) : null;
|
||||
|
||||
// end_date must be on/after the effective start date (rental may have
|
||||
// moved payload.date to the pickup date above).
|
||||
if (payload.end_date && payload.end_date < payload.date) {
|
||||
@@ -383,6 +402,7 @@ export function openDayEditor(tctx, date) {
|
||||
'div',
|
||||
{ class: 'form-row' },
|
||||
el('label', { class: 'field' }, el('span', { class: 'field-label' }, 'Type'), typeSelect),
|
||||
modeField,
|
||||
el('label', { class: 'field field-grow' }, el('span', { class: 'field-label' }, 'Title'), titleInput),
|
||||
),
|
||||
el('label', { class: 'field' }, el('span', { class: 'field-label' }, 'Details'), detailsInput),
|
||||
|
||||
Reference in New Issue
Block a user