Skip to content

Add-ons screen

/p/{token}/addons is a read-only status overview of a guest’s requested add-ons. Each card reflects the live state of the pre_checkin_submissions row.

States

For early check-in:

payment_captured_atpayment_statusCard
set✓ Confirmed, charged $X
nullcanceledUnable to accommodate, hold released
nullanything elsePending Bill’s decision

For late check-out:

payment_captured_at + late_checkout_chosen_timelate_checkout_decisionCard
both set✓ Confirmed, departure {time}
decline (or payment_status=canceled)Unable to accommodate
neither“Pick your time” → links to /forms/late-checkout?b=N

The late-checkout tier picker UI itself still lives at the legacy /forms/late-checkout?b={id} route. Folding it into the portal is a fast-follow once we see how guests use the status page.

No-requests fallback

If the booking has no pre_checkin_submissions row at all, OR the row has addon_early_checkin=0 AND addon_late_checkout=0, the page shows a friendly “you haven’t requested any add-ons yet” with a button to the pre-check-in form where requests are made.

How the picker URL gets here

The M4d workflow phase (runLateCheckoutAvailabilityCheck at D-3 15:00Z) emails the guest with the tier-picker link. As of P12.M6 that link is /p/{token}/addons (was previously /forms/late-checkout?b=N). Landing on the portal page shows the picker card, which links onward to the actual picker form for the time selection.

Source

  • Route: src/routes/portal.ts handleAddonsScreen + renderEarlyCheckinCard / renderLateCheckoutCard
  • Tests: test/routes/portal.test.ts — 5 M5 cases covering no-requests, early-confirmed, early-declined, late-awaiting-picker, late-confirmed