Conversation
added 2 commits
September 22, 2026 22:52
Add an options dialog to the payments Export button so ops can pick which columns ship (card last-four off by default) and whether the export covers the current filter or all payments, with a live row count shown before download. - src/lib/csv.ts: DEFAULT_EXPORT_COLUMNS, parseExportColumns() (server-side allowlist for the client-supplied columns param), exportFilename() gains an optional scope token. - src/app/api/payments/export/route.ts: validates columns/scope, 400s on an empty column list, reuses the existing query builder (filterPayments/sortPayments) for both scopes. - src/app/payments/export-dialog.tsx (new): column checkboxes, scope radios, live count via GET /api/payments, Download disabled at zero columns. - src/app/payments/page.tsx: wire the dialog in place of the plain Export link. - src/lib/csv.test.ts: cover column subset+order, last-four excluded by default, and an empty selection. Verified: npm test (31/31 passing); manual browser pass confirming default columns, scope-driven row count, and Download's disabled state; route sanity-checked via curl for the no-params/backward-compat, all-scope, and empty-columns cases.
Covers what the merchant console does, its tech stack, how src/ is organized, and the payments export flow end to end. Copied into public/ as well so it can be served by the dev server for viewing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Ops can now click Export on
/paymentsand get an options dialog instead of an immediate download: pick which columns ship (card last-four is off by default), choose between the current filter or every payment, and see the row count before downloading. Deselecting every column disables Download instead of producing an empty file. (Two unrelated files also ride along in this branch —docs/architecture-overview.htmland its copy underpublic/— a codebase-orientation doc from earlier investigation, not part of this ticket.)How I verified it
npm test:Route, via curl against the running dev server:
scope/columnsparams → same plain filename and full column set as before (payments-2026-09-23.csv).columns=id,amount&scope=all→ 2-column CSV covering every payment, regardless of the on-screen filter.columns=(empty) →400with{"message":"Select at least one column to export."}.status=disputed&scope=filtered→payments-disputed-2026-09-23.csv.status=disputedwith noscopeparam → old plain filename, unchanged (backward compatible).Dialog, checked by hand in the browser on
/payments:status=disputedactive, toggled scope from "Current filter" to "All payments" and watched the row count go from 33 to 1,658.Acceptance criteria
Deliberately not done
exportFilename(date, scope)token logic or the export route's scope-branching — the ticket's DoD only calls for a unit test on the column serializer, so those two got manual/curl verification only, not a test file.pageSizeallowlist entry added toparseFilters— the dialog's count fetch acceptsGET /api/payments's default page of rows and reads only.total, rather than requesting a smaller page.