From 915ec103fcfa3fb85329d6e55f9a7cd4cf62e2e9 Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Tue, 28 Apr 2026 01:06:45 -0400 Subject: [PATCH] feat: add email message field to invoices and update related components --- drizzle/0007_invoice_email_message.sql | 2 + drizzle/meta/_journal.json | 7 + src/app/dashboard/invoices/[id]/send/page.tsx | 64 +++- src/components/forms/email-composer.tsx | 15 +- src/components/forms/email-preview.tsx | 2 - src/components/forms/invoice-form.tsx | 227 +++++++++--- src/components/forms/invoice/types.ts | 1 + src/components/forms/send-email-dialog.tsx | 1 - src/lib/email-templates/invoice-email.ts | 34 -- src/lib/pdf-export.tsx | 328 ++++-------------- src/server/api/routers/email.ts | 17 +- src/server/api/routers/invoices.ts | 11 + src/server/api/routers/settings.ts | 3 + src/server/db/migrate.ts | 3 + src/server/db/schema.ts | 1 + src/types/invoice.ts | 1 + 16 files changed, 361 insertions(+), 356 deletions(-) create mode 100644 drizzle/0007_invoice_email_message.sql diff --git a/drizzle/0007_invoice_email_message.sql b/drizzle/0007_invoice_email_message.sql new file mode 100644 index 0000000..86d8beb --- /dev/null +++ b/drizzle/0007_invoice_email_message.sql @@ -0,0 +1,2 @@ +ALTER TABLE "beenvoice_invoice" +ADD COLUMN "emailMessage" varchar(2000); diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 317af68..bf28b9e 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -50,6 +50,13 @@ "when": 1777338000000, "tag": "0006_pdf_generation_settings", "breakpoints": true + }, + { + "idx": 7, + "version": "7", + "when": 1777339000000, + "tag": "0007_invoice_email_message", + "breakpoints": true } ] } diff --git a/src/app/dashboard/invoices/[id]/send/page.tsx b/src/app/dashboard/invoices/[id]/send/page.tsx index a961040..e25b09f 100644 --- a/src/app/dashboard/invoices/[id]/send/page.tsx +++ b/src/app/dashboard/invoices/[id]/send/page.tsx @@ -54,6 +54,16 @@ function SendEmailPageSkeleton() { ); } +function plainTextToHtml(value: string) { + return value + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'") + .replace(/\n/g, "
"); +} + export default function SendEmailPage() { const params = useParams(); const router = useRouter(); @@ -158,7 +168,7 @@ export default function SendEmailPage() { totalAmount: invoiceData.totalAmount, taxRate: invoiceData.taxRate, currency: invoiceData.currency, - notes: invoiceData.notes, + emailMessage: invoiceData.emailMessage, client: invoiceData.client ? { name: invoiceData.client.name, @@ -197,6 +207,9 @@ export default function SendEmailPage() { const defaultContent = ``; setEmailContent(defaultContent); + setCustomMessage( + invoice.emailMessage ? plainTextToHtml(invoice.emailMessage) : "", + ); setIsInitialized(true); }, [invoice, isInitialized]); @@ -556,7 +569,7 @@ export default function SendEmailPage() { {/* Confirmation Dialog */} - + Send Invoice Email? @@ -582,6 +595,53 @@ export default function SendEmailPage() { )} +
+ + + + + Edit Email Note + + + + + + + + + + + Email Preview + + + + + + +