Add multi-day entries and area stay blocks

Entries gain an optional inclusive end_date (backfilled via migration): flights and travel longer than 24h show a continuation marker on following days, and a new stay entry type marks a time frame in one area (e.g. 3 days Venice) rendered as continuous bands across the calendar weeks. Stays feed the map route as stops; the route summary gains stays count and a chronological areas list with day spans. 49 API tests.
This commit is contained in:
2026-07-19 00:30:14 +07:00
parent 1d86c68665
commit 154f56a0a0
14 changed files with 416 additions and 26 deletions
+12
View File
@@ -34,6 +34,7 @@ export function renderSummary(tctx) {
tile('🚗', s.travelLegs, 'Travel legs'),
tile('📍', s.activities, 'Activities'),
s.rentals > 0 ? tile('🚙', s.rentals, s.rentals === 1 ? 'Rental' : 'Rentals') : null,
s.stays > 0 ? tile('🏙️', s.stays, s.stays === 1 ? 'Stay' : 'Stays') : null,
);
section.appendChild(tiles);
@@ -71,6 +72,17 @@ export function renderSummary(tctx) {
if (breakdown.childElementCount) kmBlock.appendChild(breakdown);
section.appendChild(kmBlock);
const areas = s.areas || [];
if (areas.length) {
const areaBlock = el('div', { class: 'loc-block' }, el('h3', {}, 'Areas'));
const ul = el('ul', { class: 'area-list' });
for (const a of areas) {
ul.appendChild(el('li', {}, `🏙️ ${a.name}${a.days} ${a.days === 1 ? 'day' : 'days'}`));
}
areaBlock.appendChild(ul);
section.appendChild(areaBlock);
}
const locations = s.locations || [];
const locBlock = el('div', { class: 'loc-block' }, el('h3', {}, 'Locations in order'));
if (!locations.length) {