@@ -5,7 +5,7 @@ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "
55import { fetchAsBase64 } from "@/lib/utils"
66import { SettingsMap } from "@/models/settings"
77import { Currency , User } from "@/prisma/client"
8- import { FileDown , Save , TextSelect , X } from "lucide-react"
8+ import { FileDown , Loader2 , Save , TextSelect , X } from "lucide-react"
99import { useRouter } from "next/navigation"
1010import { startTransition , useMemo , useReducer , useState } from "react"
1111import {
@@ -83,6 +83,8 @@ export function InvoiceGenerator({
8383 const [ isTemplateDialogOpen , setIsTemplateDialogOpen ] = useState ( false )
8484 const [ newTemplateName , setNewTemplateName ] = useState ( "" )
8585 const [ formData , dispatch ] = useReducer ( invoiceFormReducer , templates [ 0 ] . formData )
86+ const [ isPdfLoading , setIsPdfLoading ] = useState ( false )
87+ const [ isSavingTransaction , setIsSavingTransaction ] = useState ( false )
8688
8789 const router = useRouter ( )
8890
@@ -97,12 +99,13 @@ export function InvoiceGenerator({
9799
98100 const handleGeneratePDF = async ( e : React . FormEvent ) => {
99101 e . preventDefault ( )
100-
101- if ( formData . businessLogo ) {
102- formData . businessLogo = await fetchAsBase64 ( formData . businessLogo )
103- }
102+ setIsPdfLoading ( true )
104103
105104 try {
105+ if ( formData . businessLogo ) {
106+ formData . businessLogo = await fetchAsBase64 ( formData . businessLogo )
107+ }
108+
106109 const pdfBuffer = await generateInvoicePDF ( formData )
107110
108111 // Create a blob from the buffer
@@ -126,6 +129,8 @@ export function InvoiceGenerator({
126129 } catch ( error ) {
127130 console . error ( "Error generating PDF:" , error )
128131 alert ( "Failed to generate PDF. Please try again." )
132+ } finally {
133+ setIsPdfLoading ( false )
129134 }
130135 }
131136
@@ -179,12 +184,13 @@ export function InvoiceGenerator({
179184 // Accept optional event, prevent default only if present
180185 const handleSaveAsTransaction = async ( e ?: React . FormEvent ) => {
181186 if ( e ) e . preventDefault ( )
182-
183- if ( formData . businessLogo ) {
184- formData . businessLogo = await fetchAsBase64 ( formData . businessLogo )
185- }
187+ setIsSavingTransaction ( true )
186188
187189 try {
190+ if ( formData . businessLogo ) {
191+ formData . businessLogo = await fetchAsBase64 ( formData . businessLogo )
192+ }
193+
188194 const result = await saveInvoiceAsTransactionAction ( formData )
189195 if ( result . success && result . data ?. id ) {
190196 console . log ( "SUCCESS! REDIRECTING TO TRANSACTION" , result . data ?. id )
@@ -197,6 +203,8 @@ export function InvoiceGenerator({
197203 } catch ( error ) {
198204 console . error ( "Error saving as transaction:" , error )
199205 alert ( "Failed to save as transaction. Please try again." )
206+ } finally {
207+ setIsSavingTransaction ( false )
200208 }
201209 }
202210
@@ -235,17 +243,35 @@ export function InvoiceGenerator({
235243
236244 { /* Generate PDF Button */ }
237245 < div className = "flex flex-col gap-4" >
238- < Button onClick = { handleGeneratePDF } >
239- < FileDown />
240- Download PDF
246+ < Button onClick = { handleGeneratePDF } disabled = { isPdfLoading } >
247+ { isPdfLoading ? (
248+ < >
249+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
250+ Generating...
251+ </ >
252+ ) : (
253+ < >
254+ < FileDown className = "mr-2" />
255+ Download PDF
256+ </ >
257+ ) }
241258 </ Button >
242259 < Button variant = "secondary" onClick = { ( ) => setIsTemplateDialogOpen ( true ) } >
243260 < TextSelect />
244261 Make a Template
245262 </ Button >
246- < Button variant = "secondary" onClick = { handleSaveAsTransaction } >
247- < Save />
248- Save as Transaction
263+ < Button variant = "secondary" onClick = { handleSaveAsTransaction } disabled = { isSavingTransaction } >
264+ { isSavingTransaction ? (
265+ < >
266+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
267+ Saving...
268+ </ >
269+ ) : (
270+ < >
271+ < Save className = "mr-2" />
272+ Save as Transaction
273+ </ >
274+ ) }
249275 </ Button >
250276 </ div >
251277 </ div >
0 commit comments