fix(billing): real invoice download with error handling#211
Merged
Conversation
# Conflicts: # src/shared/api/client.ts
Contributor
|
real invoice download with proper auth and error handling is a solid upgrade over a stubbed button. rebased on latest main and combined it cleanly with the terms api additions in client.ts. thanks! |
4 tasks
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.
Closes #191
Title:
fix(billing): real invoice download with error handling
Body:
Summary
link.href = '#'with a real fetch � Blob � object URL downloadoverflow-x-auto/min-w-[640px]to fix mobile overflowHow the download works
handleDownloadInvoicecalls the newdownloadInvoice(id)function inclient.ts,which issues an authenticated
GET /billing/invoices/:id/downloadand returns aBlob.The component then:
URL.createObjectURL(blob)<a>element and calls.click()URL.revokeObjectURL(url)to release the Blob from memoryThe download filename is derived from
invoice.invoiceNumberwinon-
[a-zA-Z0-9\-_]characters replaced, so it is never influenced by anunsanitized server-provided value.
Loading & error handling
downloadingId: string | null� disables and shows a spinnerfetched; all other rows stay interactive
downloadErrors: Record<string, string>� shows a `role="alerbelow the failing row; cleared on the next successful attempt
Responsive fix
The six-column grid is now wrapped in
overflow-x-autowithmin-w-[640px]on theinner container � the table scrolls horizontally on narrow viewp
overflowing.
Tests & coverage
18 tests across 6 describe blocks:
Errormessage shown, non-Errorfallback, per-row isolation,no object URL calls on failure
row affected
overflow-x-autowrapper andmin-w-constraint verifiedCoverage for
InvoicesTab.tsx: **100% statements / branches / fSecurity note
/[^a-zA-Z0-9\-_]/g� no raw server string reacheslink.download