diff --git a/apps/web/src/features/purchases/components/LicensesView.tsx b/apps/web/src/features/purchases/components/LicensesView.tsx index 838994948..fcfc60524 100644 --- a/apps/web/src/features/purchases/components/LicensesView.tsx +++ b/apps/web/src/features/purchases/components/LicensesView.tsx @@ -1,11 +1,12 @@ /** * LicensesView — list of user's purchased licenses with download links (v0.401 M2) + * v0.403 F1: Invoice download link */ import { useState, useEffect } from 'react'; import { marketplaceService } from '@/services/marketplaceService'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; -import { Download, FileAudio } from 'lucide-react'; +import { Download, FileAudio, FileText } from 'lucide-react'; import { EmptyState } from '@/components/ui/empty-state'; import { Skeleton } from '@/components/ui/skeleton'; @@ -72,16 +73,32 @@ export function LicensesView() { Purchased {item.order?.created_at ? new Date(item.order.created_at).toLocaleDateString() : '—'} - +
+ + +
))} diff --git a/apps/web/src/features/purchases/pages/purchases-page/PurchasesView.tsx b/apps/web/src/features/purchases/pages/purchases-page/PurchasesView.tsx index 7bb45f4a8..61ed6561d 100644 --- a/apps/web/src/features/purchases/pages/purchases-page/PurchasesView.tsx +++ b/apps/web/src/features/purchases/pages/purchases-page/PurchasesView.tsx @@ -1,5 +1,6 @@ import { RefundRequestModal } from '@/components/commerce/modals/RefundRequestModal'; import toast from '@/utils/toast'; +import { marketplaceService } from '@/services/marketplaceService'; import { usePurchasesView } from './usePurchasesView'; import { PurchasesViewHeader } from './PurchasesViewHeader'; import { PurchasesViewList } from './PurchasesViewList'; @@ -19,6 +20,15 @@ export function PurchasesView({ initialPurchases }: PurchasesViewProps = {}) { handleDownload, } = usePurchasesView(initialPurchases ?? undefined); + const handleInvoiceDownload = async (orderId: string) => { + try { + await marketplaceService.downloadInvoice(orderId); + toast.success('Invoice downloaded'); + } catch { + toast.error('Failed to download invoice'); + } + }; + if (loading) { return ; } @@ -34,6 +44,7 @@ export function PurchasesView({ initialPurchases }: PurchasesViewProps = {}) { setActiveDownloadId={setActiveDownloadId} onDownloadFormat={handleDownload} onLicense={() => toast('License document opened')} + onInvoiceDownload={handleInvoiceDownload} onRefund={setRefundOrderId} /> diff --git a/apps/web/src/features/purchases/pages/purchases-page/PurchasesViewItem.tsx b/apps/web/src/features/purchases/pages/purchases-page/PurchasesViewItem.tsx index 5ca49c3c9..d4624f4de 100644 --- a/apps/web/src/features/purchases/pages/purchases-page/PurchasesViewItem.tsx +++ b/apps/web/src/features/purchases/pages/purchases-page/PurchasesViewItem.tsx @@ -9,6 +9,7 @@ interface PurchasesViewItemProps { onToggleDownload: () => void; onDownloadFormat: (format: string) => void; onLicense: () => void; + onInvoiceDownload: (orderId: string) => void; onRefund: () => void; } @@ -20,6 +21,7 @@ export function PurchasesViewItem({ onToggleDownload, onDownloadFormat, onLicense, + onInvoiceDownload, onRefund, }: PurchasesViewItemProps) { const product = purchase.product as { title: string; coverUrl?: string; type?: string }; @@ -86,6 +88,17 @@ export function PurchasesViewItem({ License + +