When a user adds a new packing category, the first item is seeded
with name '...' because the server rejects empty names. That string
was rendered as a real value in the input, forcing users to delete
the dots before typing. Now we detect the sentinel, show it as a
faint placeholder in the display span, and start the edit input
empty (with '...' as the HTML placeholder).
- Budget table column alignment: the NAME data cell had
`display: flex` directly on the <td>, which pulled it out of the
table-layout and desynced the column widths between data rows and the
AddItemRow. Moved the flex wrapper into a <div> inside the cell.
Closes#759
- Packing list: template-apply and bulk-import handlers called
`window.location.reload()` to refresh the list, which re-rendered the
whole trip loading screen. Both flows now merge the returned items
into the trip store instead. Closes#760
- Journey timeline: move-up / move-down arrows were rendered on
skeleton suggestions — skeletons are places from the linked trip and
don't participate in sort order. Skip canReorder when
entry.type === 'skeleton'. Closes#763
- Journey public view: the synthetic `[Trip Photos]` and `Gallery`
entries produced by syncTripPhotos were leaking into the public
timeline and map. The owner view already strips these in
JourneyDetailPage — apply the same filter on JourneyPublicPage.
Gallery photos still come from every entry so a shared gallery keeps
showing the trip-synced photos. Closes#764
- Journey thumbnails: public gallery grid was loading the original
asset for every tile. `photoUrl()` now takes an optional kind and the
grid requests `thumbnail`; the lightbox still opens the original.
Synology thumbnail default bumped from `sm` (240px) to `m` (320px)
because `sm` looked pixelated on retina. Closes#761
- PackingListPanel accepts inlineHeader prop (default true) to keep its
legacy title and inline import button; ListsContainer passes
inlineHeader={false} since the toolbar now owns those controls
- ReservationModal tests look for the renamed 'Car' button (was 'Rental Car')
- Budget total-budget test asserts against the split integer/decimal
spans that replaced the single text node
Trip planner now has a consistent rounded toolbar across bookings, lists,
budget and files. Each panel shows title, inline filter pills (with
counts where useful) and an accent action button on the right. Moved
per-tab controls into the toolbar — lists import, todo add, budget
currency/add-category, files trash/filters — and dropped the redundant
in-panel headers.
Budget sidebar redesigned: total-budget card with indigo-ringed avatars
and coloured split bar; settlement flows as paired avatar cards;
by-category donut rebuilt in SVG with per-category gradients. Both cards
now follow dark/light mode via a widgetTheme helper.
Todo: add-new-task is a portalled modal on desktop, the add-task input
bar is gone; new SORT BY section in the sidebar; inline category
creation in the task editor.
Reservations: pending / confirmed sections remember their collapsed
state per trip (localStorage).
Misc: per-trip connections toggle moved into the day-plan sidebar,
booking endpoints fixed to show on map for trains/cruises/cars as well,
label localStorage persistence, RESMODAL test updated to the new
airport-select flow.
i18n: the new booking / map / todo / budget strings are translated into
all 15 supported languages.
- Add paddingBottom: var(--bottom-nav-h) to all mobile overlays that were
clipping content behind the bottom navbar: EntryEditor, SystemNoticeModal,
JourneyPage create modal, TodoListPanel sheets, TripPlannerPage
PlaceInspector, PackingListPanel bag modal, both PhotoLightboxes,
FileManager viewer, and shared Modal primitive
- Replace single-notice mobile bottom sheet with a 3-slot horizontal strip
so adjacent notices are physically present during drag
- Add live-follow swipe left/right to navigate between notices with
spring-back when under threshold and flushSync to eliminate blink on commit
- Add live-follow swipe down to dismiss all notices with spring-back;
backdrop tap also triggers the slide-down animation
- Normalize notice height with useLayoutEffect minHeight on strip and
align-items: stretch so all slots are always the tallest notice height
- Pin CTA button at consistent Y across notices via flex-1 + mt-auto;
always render invisible Not now placeholder to equalise CTA section height
- Move pager dots/counter below CTA buttons
Use position:fixed with calculated coordinates instead of
position:absolute so the dropdown escapes the overflow:hidden
container. Also adds a backdrop to close on outside click.
- Add quantity field to packing items (persisted, visible per item)
- Bags are now renamable (click to edit in sidebar)
- Bags support multiple user assignments with avatar display
- New packing_bag_members table for multi-user bag ownership
- Save current packing list as reusable template
- Add bag members API endpoint (PUT /bags/:bagId/members)
- Migration 74: quantity on packing_items, user_id on packing_bags, packing_bag_members table
- Import textarea now shows line numbers to distinguish wrapped lines from actual new lines
- CSV parser respects double-quoted values (e.g. "Shirt, blue" stays as one field)
Fixes#133
Packing list bulk import:
- Import button in packing list header opens a modal
- Paste items or load CSV/TXT file
- Format: Category, Name, Weight (g), Bag, checked/unchecked
- Bags are auto-created if they don't exist
- Server endpoint POST /packing/import with transaction
i18n sync:
- Added all missing translation keys to fr, es, nl, ru, zh, ar
- All 8 language files now have matching key sets
- Includes memories, vacay weekdays, packing import, settlement,
GPX import, blur booking codes, transport timeline keys