From 6357d95f0ec4e14bc168aa73200cc7000a3747d6 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 16:58:36 +0000 Subject: [PATCH] Add CSV export functionality to invoices page - Added Download icon from lucide-react to imports - Implemented handleExportCSV function that: - Exports filtered invoice data as CSV - Respects current search and status filters - Formats dates as YYYY-MM-DD - Quotes customer names to handle commas - Shows warning toast if no invoices to export - Shows success toast with count of exported invoices - Added Export button next to New Invoice button - Button uses outline style to differentiate from primary action - Filename includes current date: invoices_YYYY-MM-DD.csv Co-Authored-By: jia.wu@codeium.com --- .../src/components/Invoices/InvoiceList.js | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/components/Invoices/InvoiceList.js b/src/frontend/src/components/Invoices/InvoiceList.js index 02a95ff..ff815c5 100644 --- a/src/frontend/src/components/Invoices/InvoiceList.js +++ b/src/frontend/src/components/Invoices/InvoiceList.js @@ -9,7 +9,8 @@ import { Trash2, Calendar, Search, - Filter + Filter, + Download } from 'lucide-react'; import { format } from 'date-fns'; @@ -66,6 +67,47 @@ const InvoiceList = () => { return matchesSearch && matchesStatus; }); + const handleExportCSV = () => { + try { + if (filteredInvoices.length === 0) { + toast.warning('No invoices to export'); + return; + } + + const headers = ['Invoice Number', 'Customer Name', 'Customer Email', 'Issue Date', 'Due Date', 'Amount', 'Status']; + const csvRows = [headers.join(',')]; + + filteredInvoices.forEach(invoice => { + const row = [ + invoice.invoice_number, + `"${invoice.customer_name}"`, + invoice.customer_email || '', + format(new Date(invoice.issue_date), 'yyyy-MM-dd'), + format(new Date(invoice.due_date), 'yyyy-MM-dd'), + invoice.total_amount.toFixed(2), + invoice.status + ]; + csvRows.push(row.join(',')); + }); + + const csvContent = csvRows.join('\n'); + const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + const url = URL.createObjectURL(blob); + + link.setAttribute('href', url); + link.setAttribute('download', `invoices_${format(new Date(), 'yyyy-MM-dd')}.csv`); + link.style.visibility = 'hidden'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + toast.success(`Exported ${filteredInvoices.length} invoice(s)`); + } catch (error) { + toast.error('Failed to export invoices'); + } + }; + if (loading) { return (
@@ -85,10 +127,16 @@ const InvoiceList = () => {

Invoices

- - - New Invoice - +
+ + + + New Invoice + +
{/* Filters */}