feat: download invoices
This commit is contained in:
parent
d16945a9e2
commit
c7867ab05e
2 changed files with 58 additions and 1 deletions
|
|
@ -22,6 +22,8 @@ interface Charge {
|
|||
refunded: boolean;
|
||||
amount_refunded: number;
|
||||
description: string | null;
|
||||
receipt_url: string | null;
|
||||
invoice_pdf: string | null;
|
||||
}
|
||||
|
||||
const useCharges = () => {
|
||||
|
|
@ -124,6 +126,7 @@ const ChargesModal: FC<{ close: () => void }> = ({ close }) => {
|
|||
<th className="p-[8px]">{t('date', 'Date')}</th>
|
||||
<th className="p-[8px]">{t('amount', 'Amount')}</th>
|
||||
<th className="p-[8px]">{t('status', 'Status')}</th>
|
||||
<th className="p-[8px] w-[50px]" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -178,6 +181,34 @@ const ChargesModal: FC<{ close: () => void }> = ({ close }) => {
|
|||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="p-[8px]">
|
||||
{(charge.invoice_pdf || charge.receipt_url) && (
|
||||
<a
|
||||
href={charge.invoice_pdf || charge.receipt_url!}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="inline-flex items-center justify-center w-[28px] h-[28px] rounded-[4px] hover:bg-tableBorder transition-colors"
|
||||
title={charge.invoice_pdf ? t('download_invoice', 'Download Invoice') : t('view_receipt', 'View Receipt')}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="16"
|
||||
height="16"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
||||
<polyline points="7 10 12 15 17 10" />
|
||||
<line x1="12" y1="15" x2="12" y2="3" />
|
||||
</svg>
|
||||
</a>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
|
|
|||
|
|
@ -856,7 +856,7 @@ export class StripeService {
|
|||
limit: 100,
|
||||
});
|
||||
|
||||
return charges.data
|
||||
const chargeList = charges.data
|
||||
.filter((f) => f.status === 'succeeded')
|
||||
.map((charge) => ({
|
||||
id: charge.id,
|
||||
|
|
@ -867,7 +867,33 @@ export class StripeService {
|
|||
refunded: charge.refunded,
|
||||
amount_refunded: charge.amount_refunded,
|
||||
description: charge.description,
|
||||
receipt_url: charge.receipt_url || null,
|
||||
invoice: (charge as any).invoice || null,
|
||||
}));
|
||||
|
||||
const invoiceIds = chargeList
|
||||
.map((c) => c.invoice)
|
||||
.filter((id): id is string => !!id && typeof id === 'string');
|
||||
|
||||
const invoicePdfMap: Record<string, string> = {};
|
||||
for (const invoiceId of invoiceIds) {
|
||||
try {
|
||||
const inv = await stripe.invoices.retrieve(invoiceId);
|
||||
if (inv.invoice_pdf) {
|
||||
invoicePdfMap[invoiceId] = inv.invoice_pdf;
|
||||
}
|
||||
} catch {
|
||||
// ignore if invoice can't be fetched
|
||||
}
|
||||
}
|
||||
|
||||
return chargeList.map((charge) => ({
|
||||
...charge,
|
||||
invoice_pdf:
|
||||
charge.invoice && invoicePdfMap[charge.invoice as string]
|
||||
? invoicePdfMap[charge.invoice as string]
|
||||
: null,
|
||||
}));
|
||||
}
|
||||
|
||||
async refundCharges(organizationId: string, chargeIds: string[]) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue