You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As a homeowner about to send a report to my bank, I want to edit the report's wording — the table's descriptive text and the whole cover letter — directly in the preview before exporting so that I can correct or tailor anything the generated text got wrong without leaving the wizard or hand-editing a PDF.
Part of the Bank Report Wizard — Refinement Round 2 mini-epic. Source: direct user verification of the merged wizard. Scope decomposed and approved during mini-epic planning.
Priority: Must Have Blocked by: #1898 (report table refinements), #1899 (settings step + report language) Blocks: #1901 (AI generation)
Settled decisions (do not re-litigate): Step 5 is an HTML edit surface with on-demand PDF — there is no live side-by-side PDF pane. "Letterhead" means the full cover letter: sender, recipient, reference, subject, and body blocks are all editable. Amounts and totals stay read-only because they are derived.
Acceptance Criteria
1. Editable report content in Step 5
Given I reach Step 5 "Preview & Export", when it renders, then it shows the full report content as editable HTML rather than only a rendered PDF frame.
Given invoices excluded in Step 3, when the editable table renders, then they are absent from it — the editable content reflects the Step-3 selection and line exclusions exactly.
Given the "include cover letter" option is on, when Step 5 renders, then the complete cover letter is shown with separately editable fields for sender, recipient, reference, subject, and body.
Given the "include cover letter" option is off, when Step 5 renders, then no cover-letter fields are shown and no cover letter is exported.
Given the editable surface, when I use only a keyboard, then every editable field is reachable, has an accessible label, and shows a visible focus indicator; the surface works at desktop, tablet, and mobile viewports.
Given the editable surface, when it renders, then it uses design tokens and existing shared components — no hardcoded colours, spacing, radii, or font sizes — and renders correctly in dark mode.
2. What is editable vs. read-only
Given any wording/text field in Step 5 (usage text, attachments note, and every cover-letter block), when I click into it, then I can edit it freely.
Given any amount cell (per-invoice invoice amount and allocated amount), when I attempt to edit it, then it is read-only — it cannot be typed into, and it is visually and programmatically marked as non-editable.
Given any total or subtotal cell, when I attempt to edit it, then it is read-only, and its value continues to be derived from the Step-3 selection and exclusions.
Given read-only amounts, when the report is exported, then the exported figures are byte-for-byte the derived values — no user input path can alter a number.
3. Baseline, regeneration, and warning
Given I first arrive at Step 5, when the editable content renders, then it is populated from a generated baseline (the same content the report would produce today, in the language chosen in Step 4).
Given I have made edits and I go back and change something in Steps 1–4 (report type, source, invoice/line selection, report language, or the export toggles), when I return to Step 5, then the baseline is regenerated and my edits are cleared.
Given I have unsaved edits and I attempt a Step 1–4 change that would regenerate the baseline, when I trigger it, then I am shown an explicit confirmation warning that my edits will be lost, and I can cancel to keep them.
Given I have made no edits, when I change something in Steps 1–4, then no warning is shown (the warning only appears when there is something to lose).
Given I confirm the regeneration, when Step 5 re-renders, then the content matches a freshly generated baseline with no residue of the discarded edits.
Given edits are modelled as overrides on a generated baseline, when a field is untouched, then it continues to track the baseline (it is not silently frozen at the first render).
4. On-demand PDF
Given Step 5, when it renders, then there is no continuously regenerating background PDF and no live PDF pane — the PDF is produced only on demand.
Given Step 5, when I trigger the "Preview PDF" action, then a PDF is generated from the currently edited content and shown to me.
Given I have edited content, when I download the report, then the produced PDF reflects every edit I made.
Given I have edited content, when I upload to Paperless, then the uploaded PDF reflects every edit I made.
Given a PDF generation failure, when it occurs, then the error is surfaced to me clearly and my edited content is preserved.
5. Translations
Given every new user-facing string (labels, the regeneration warning, the Preview PDF action, read-only affordances), when it renders, then it comes from t() and resolves in both en and de.
Persisting edited reports server-side, saving drafts, or re-opening a previously edited report.
Rich-text formatting controls (bold/italic/lists) in the editable fields — plain wording edits only unless the dev-team-lead's spec establishes otherwise.
Editing amounts, totals, or the invoice selection from Step 5 — selection stays in Step 3.
PDF pipeline: client/src/lib/reportPdf/ — today overviewPdf.ts / coverLetterPdf.ts build content directly from the report response. This story inserts an intermediate, editable content model between the response and the PDF builders; the builders must consume that model so preview and every export path share one source.
Derived-amount contract facts still apply: allocatedAmount is negative for lineKind: 'refund-adjustment' (never re-negate), and report.totalAmount is not the grand total once invoices are excluded — the included total comes from merge.ts.
Testing: extend realRender.test.ts to assert that an edited baseline reaches the rendered PDF and that excluded rows stay out of the totals. Any "preview renders" assertion must check rendered content, not a src attribute.
As a homeowner about to send a report to my bank, I want to edit the report's wording — the table's descriptive text and the whole cover letter — directly in the preview before exporting so that I can correct or tailor anything the generated text got wrong without leaving the wizard or hand-editing a PDF.
Part of the Bank Report Wizard — Refinement Round 2 mini-epic. Source: direct user verification of the merged wizard. Scope decomposed and approved during mini-epic planning.
Priority: Must Have
Blocked by: #1898 (report table refinements), #1899 (settings step + report language)
Blocks: #1901 (AI generation)
Settled decisions (do not re-litigate): Step 5 is an HTML edit surface with on-demand PDF — there is no live side-by-side PDF pane. "Letterhead" means the full cover letter: sender, recipient, reference, subject, and body blocks are all editable. Amounts and totals stay read-only because they are derived.
Acceptance Criteria
1. Editable report content in Step 5
2. What is editable vs. read-only
3. Baseline, regeneration, and warning
4. On-demand PDF
blob:URL was assigned (the CSP regression class from Bank report wizard follow-up: blob: CSP for preview, status chip sizing, expandable invoice rows & deposit budget source #1891 must not reappear).5. Translations
t()and resolves in bothenandde.Out of scope
Notes
client/src/pages/ReportWizardPage/,client/src/components/reports/ReportPdfPreview.tsx,ReportInvoiceList.tsx.client/src/lib/reportPdf/— todayoverviewPdf.ts/coverLetterPdf.tsbuild content directly from the report response. This story inserts an intermediate, editable content model between the response and the PDF builders; the builders must consume that model so preview and every export path share one source.allocatedAmountis negative forlineKind: 'refund-adjustment'(never re-negate), andreport.totalAmountis not the grand total once invoices are excluded — the included total comes frommerge.ts.realRender.test.tsto assert that an edited baseline reaches the rendered PDF and that excluded rows stay out of the totals. Any "preview renders" assertion must check rendered content, not asrcattribute.