From 817689001c563a45f0ddcf157ac75b35ed138801 Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Thu, 31 Jul 2025 18:54:24 -0400 Subject: [PATCH] New invoice bug fix --- src/app/dashboard/invoices/[id]/page.tsx | 19 ++++- src/app/dashboard/invoices/new/page.tsx | 7 ++ src/components/ui/button.tsx | 2 +- src/components/ui/input.tsx | 2 +- src/lib/email-templates/invoice-email.ts | 79 ++++++++++--------- .../email-templates/password-reset-email.ts | 47 ++++++----- 6 files changed, 90 insertions(+), 66 deletions(-) create mode 100644 src/app/dashboard/invoices/new/page.tsx diff --git a/src/app/dashboard/invoices/[id]/page.tsx b/src/app/dashboard/invoices/[id]/page.tsx index bbffb55..3064583 100644 --- a/src/app/dashboard/invoices/[id]/page.tsx +++ b/src/app/dashboard/invoices/[id]/page.tsx @@ -3,7 +3,7 @@ import { DollarSign, Edit, Loader2, Trash2 } from "lucide-react"; import Link from "next/link"; import { notFound, useParams, useRouter } from "next/navigation"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { toast } from "sonner"; import { StatusBadge, type StatusType } from "~/components/data/status-badge"; import { PageHeader } from "~/components/layout/page-header"; @@ -505,7 +505,24 @@ function InvoiceViewContent({ invoiceId }: { invoiceId: string }) { export default function InvoiceViewPage() { const params = useParams(); + const router = useRouter(); const id = params.id as string; + // Handle /invoices/new route - redirect to dedicated new page + useEffect(() => { + if (id === "new") { + router.replace("/dashboard/invoices/new"); + } + }, [id, router]); + + // Don't render anything if we're redirecting + if (id === "new") { + return ( +
+ +
+ ); + } + return ; } diff --git a/src/app/dashboard/invoices/new/page.tsx b/src/app/dashboard/invoices/new/page.tsx new file mode 100644 index 0000000..e9eca4f --- /dev/null +++ b/src/app/dashboard/invoices/new/page.tsx @@ -0,0 +1,7 @@ +"use client"; + +import InvoiceForm from "~/components/forms/invoice-form"; + +export default function NewInvoicePage() { + return ; +} diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 42c99ea..ed46c35 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -16,7 +16,7 @@ const buttonVariants = cva( destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: - "border border-border/40 bg-background/60 shadow-sm backdrop-blur-sm hover:bg-accent/50 hover:text-foreground-foreground hover:border-border/60 transition-colors duration-150", + "border border-border/40 bg-background/60 shadow-sm hover:bg-accent/50 hover:text-foreground-foreground hover:border-border/60 transition-colors duration-150", secondary: "bg-secondary text-muted-foreground-foreground shadow-xs hover:bg-secondary/80", ghost: diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 6aacab1..4669c8a 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) { type={type} data-slot="input" className={cn( - "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground bg-background/50 text-foreground border-border/40 flex h-10 w-full min-w-0 border px-3 py-2 text-sm shadow-sm backdrop-blur-sm transition-all duration-200 outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", + "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground bg-background/50 text-foreground border-border/40 flex h-10 w-full min-w-0 border px-3 py-2 text-sm shadow-sm transition-all duration-200 outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", "focus-visible:border-ring focus-visible:bg-background/80 focus-visible:ring-ring/20 focus-visible:ring-[3px]", "hover:border-border/60 hover:bg-background/60", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", diff --git a/src/lib/email-templates/invoice-email.ts b/src/lib/email-templates/invoice-email.ts index e3c5255..7fa1257 100644 --- a/src/lib/email-templates/invoice-email.ts +++ b/src/lib/email-templates/invoice-email.ts @@ -106,9 +106,9 @@ export function generateInvoiceEmailTemplate({ } body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; line-height: 1.6; - color: #1f2937; + color: #0f0f0f; background-color: #f9fafb; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; @@ -118,14 +118,14 @@ export function generateInvoiceEmailTemplate({ max-width: 600px; margin: 0 auto; background-color: #ffffff; - border-radius: 12px; + border-radius: 0; overflow: hidden; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .header { - background: linear-gradient(135deg, #16a34a 0%, #15803d 100%); + background: #0f0f0f; padding: 32px 24px; text-align: center; color: white; @@ -135,15 +135,15 @@ export function generateInvoiceEmailTemplate({ font-size: 28px; font-weight: bold; margin-bottom: 8px; - letter-spacing: -0.5px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + letter-spacing: 0.5px; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .header-subtitle { font-size: 16px; - opacity: 0.9; + opacity: 0.8; font-weight: normal; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .content { @@ -154,21 +154,21 @@ export function generateInvoiceEmailTemplate({ font-size: 16px; font-weight: bold; margin-bottom: 24px; - color: #374151; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + color: #0f0f0f; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .message { font-size: 15px; line-height: 1.7; margin-bottom: 32px; - color: #4b5563; + color: #374151; } .invoice-card { - background-color: #f8fafc; - border: 1px solid #e2e8f0; - border-radius: 12px; + background-color: #f9fafb; + border: 1px solid #e5e7eb; + border-radius: 0; padding: 16px; margin: 24px 0; } @@ -180,9 +180,9 @@ export function generateInvoiceEmailTemplate({ .invoice-number { font-size: 24px; font-weight: bold; - color: #16a34a; + color: #0f0f0f; margin-bottom: 8px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .invoice-date { @@ -243,9 +243,9 @@ export function generateInvoiceEmailTemplate({ .business-name { font-size: 16px; font-weight: bold; - color: #1f2937; + color: #0f0f0f; margin-bottom: 8px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .business-details { @@ -268,8 +268,8 @@ export function generateInvoiceEmailTemplate({ text-align: center; margin: 32px 0; padding: 24px; - background-color: #f8fafc; - border-radius: 8px; + background-color: #f9fafb; + border-radius: 0; } .cta-text { @@ -279,9 +279,9 @@ export function generateInvoiceEmailTemplate({ } .attachment-notice { - background-color: #f0fdf4; - border: 1px solid #bbf7d0; - border-radius: 8px; + background-color: #f9fafb; + border: 1px solid #e5e7eb; + border-radius: 0; padding: 16px; margin: 20px 0; display: flex; @@ -292,16 +292,16 @@ export function generateInvoiceEmailTemplate({ .attachment-icon { width: 20px; height: 20px; - background-color: #16a34a; - border-radius: 50%; + background-color: #374151; + border-radius: 0; flex-shrink: 0; } .attachment-text { font-size: 14px; - color: #166534; + color: #374151; font-weight: bold; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .signature { @@ -313,9 +313,9 @@ export function generateInvoiceEmailTemplate({ .signature-name { font-size: 16px; font-weight: bold; - color: #1f2937; + color: #0f0f0f; margin-bottom: 4px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } .signature-email { @@ -333,18 +333,19 @@ export function generateInvoiceEmailTemplate({ .footer-brand { font-size: 18px; font-weight: bold; - color: #16a34a; + color: #0f0f0f; margin: 0 auto 8px; display: block; text-align: center; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; + letter-spacing: 0.5px; } .footer-text { font-size: 12px; - color: #9ca3af; + color: #6b7280; line-height: 1.5; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + font-family: ui-monospace, 'Geist Mono', 'Courier New', monospace; } /* Email client specific fixes */ @@ -370,8 +371,8 @@ export function generateInvoiceEmailTemplate({ /* Apple Mail attachment preview fix */ .attachment-notice { - border: 2px dashed #bbf7d0 !important; - background-color: #f0fdf4 !important; + border: 1px solid #e5e7eb !important; + background-color: #f9fafb !important; } @media (max-width: 600px) { @@ -414,7 +415,7 @@ export function generateInvoiceEmailTemplate({
${getTimeOfDayGreeting()},

I hope this email finds you well. Please find attached invoice #${invoice.invoiceNumber} for the services provided. The invoice details are summarized below for your reference.

- ${customMessage ? `
${customMessage}
` : ""} + ${customMessage ? `
${customMessage}
` : ""} ${customContent ? `
${customContent}
` : ""} @@ -451,7 +452,7 @@ export function generateInvoiceEmailTemplate({ - +
Total${formatCurrency(total)}${formatCurrency(total)}
diff --git a/src/lib/email-templates/password-reset-email.ts b/src/lib/email-templates/password-reset-email.ts index d9b25d9..02fd491 100644 --- a/src/lib/email-templates/password-reset-email.ts +++ b/src/lib/email-templates/password-reset-email.ts @@ -27,10 +27,10 @@ export function generatePasswordResetEmailTemplate({ Password Reset - beenvoice