Repository navigation
feat(plans): show the schedule preview inline in the plan modal #1153
Description
Summary
The plan schedule (laddering) preview should be visible inside the Create/Edit Purchase Plan modal and update live as the form changes. Today it sits behind a separate Preview schedule button that opens a second dialog.
Owner request: "why isn't the laddering preview fully integrated into the plans UI? I'd expect it all to be visible in the modal without having to click open preview there as well."
Why it is separate today
frontend/src/index.html:983defines<button id="preview-plan-schedule-btn">Preview schedule</button>.frontend/src/plans.ts:2393-2399callsopenPlanSchedulePreview(frontend/src/plan-schedule-preview.ts:41), which builds a wide modal dialog over the plan modal.- feat(plans): preview draft purchase schedules #880 shipped it as a no-write "leaf": a wide staircase that the plan modal had no room for, form values kept, no API writes. The atomic inline editor (editor preview/Save API, editor-managed dates) was deferred to feat(plans): plan editor hardening deferred from #631 (atomic Save, editor API, managed dates) #1057.
Plan (read-only part now; #1057 stays separate)
- Refactor
plan-schedule-preview.tsinto a reusable renderer: schedule intent (buildLocalScheduleIntent), plot (plan-schedule-plot.ts) and summary, separated from the dialog shell. No copy-paste. - Render the staircase and summary inline in the plan modal, re-rendering on every relevant form change (preset, coverage, step percent, interval, notification days, term, payment). An invalid input shows the validation message in place of the plot.
- Size the modal so the staircase fits: a wider plan modal on desktop, and horizontal scroll inside the preview area on narrow screens (320 to 1440 px checked).
- Remove the Preview schedule button and its dialog once the inline preview covers it.
- No API writes and no Save changes.
Proof: jest tests for the renderer and live updates, written test-first. Playwright checks the modal with real plans (create and edit, desktop and phone widths), with screenshots in the PR. Then two independent reviews, local verification and CI.
Default and decision point
Default: an inline read-only preview, with the button and dialog removed.
What this drops: the dialog's local draft-date editing (#882/#884): dragging dates and interval handles, per-step date inputs, and "Reset draft dates". Those edits are local to the preview, discarded on close, and never applied by Save. They come back with #1057, where editor-managed dates are actually saved. If the draft-date editing should stay in the modal before #1057 lands, say so here and the inline preview will keep it, clearly labelled as unsaved.
@IAmJSD this is the plan and default above; please object here if you disagree.
Activity
cristim commentedon Oct 19, 2026
Scope update after reading main (
2d822f39): part of this already exists.openPlanForm(frontend/src/plans.ts:1259-1273) mountsmountPlanEditorPanelinto#plan-editor-panel(index.html:823) for Create. In read-only mode that panel also shows five permanently disabled controls and a roadmap sentence. Create users therefore see two previews: the inline one plus the Preview schedule dialog.plans.ts:1367passescreate=false, so editing a plan only has the dialog.plan-editor-panel.ts:2importsbuildLocalScheduleIntentfrom the dialog module (plan-schedule-preview.ts).Restated work (default unchanged: inline read-only preview, button removed):
plan-schedule-intent.ts, using the same names as the parked feat(plans): plan editor hardening deferred from #631 (atomic Save, editor API, managed dates) #1057 branch to keep its rebase easy.Code that stays for #1057:
editableDates;plan-date-interaction.ts;lib/plan-draft-dates.ts.The parked editor branch and the panel's editable mode both use them. Only the dialog's copy of draft-date editing goes away.
This lands as two PRs to stay within the per-commit size cap: an additive one ("Part of #1153"), then the removal ("Closes #1153").
fix(plans): split the preview summary from its live region
fix(plans): hide the cleared preview region in the browser
fix(plans): make the inline schedule preview a live read-only panel (#…
test(plans): prove the Edit preview panel releases its listeners
fix(plans): cap the sticky preview, fix tab order and stack at 960px
cristim commentedon Oct 20, 2026
@IAmJSD a layout question for phones, raised in review of #1178 (PR2). At 960 px and below, the modal stacks in one column with the form first and the preview after it. That keeps the tab and reading order matching the visual order, but on a phone the preview sits below the whole form (ramp cards, accounts, advanced settings), so a user has to scroll past everything to see it.
Options:
I'll proceed with A unless you prefer B or C.
feat(plans): show the inline schedule preview in Edit and lay it out …
test(plans): restore the step-1 staircase and Escape containment checks
feat(plans): remove the Preview schedule dialog now that the preview …