2025-08-04 17:45:44 +02:00
"use client" ;
import { format } from "date-fns" ;
import { it } from "date-fns/locale" ;
2025-08-28 18:27:07 +02:00
import Image from "next/image" ;
2026-03-08 01:02:57 +01:00
import toast from "react-hot-toast" ;
2025-08-28 18:27:07 +02:00
import { Button } from "~/components/ui/button" ;
import { Card } from "~/components/ui/card" ;
2025-08-04 17:45:44 +02:00
import { PaymentMethodToString , type PaymentType } from "~/i18n/stripe" ;
2025-08-28 18:27:07 +02:00
import { formatCurrency } from "~/lib/utils" ;
2026-03-08 01:02:57 +01:00
import type { OrdiniOrdineId } from "~/schemas/public/Ordini" ;
import { api } from "~/utils/api" ;
2025-08-04 17:45:44 +02:00
2026-03-04 19:12:01 +01:00
export function ReceiptGenerator ( {
data ,
raw ,
} : {
data : PurchaseData ;
raw : boolean ;
} ) {
2026-03-08 01:02:57 +01:00
const { mutate : generatePdf } =
api . pagamenti . getRicevutaCortesiaPdf . useMutation ( {
onMutate : ( ) = > {
toast . loading ( "Generazione PDF in corso..." , {
id : "generate-pdf" ,
} ) ;
} ,
onSuccess : ( res ) = > {
toast . success ( "PDF generato con successo!" , {
id : "generate-pdf" ,
} ) ;
const blob = new Blob ( [ res as unknown as ArrayBuffer ] , {
type : "application/pdf" ,
} ) ;
const url = window . URL . createObjectURL ( blob ) ;
const link = document . createElement ( "a" ) ;
link . href = url ;
link . download = ` ricevuta-cortesia- ${ format ( data . date , "yyyy-MM-dd" ) } .pdf ` ;
document . body . appendChild ( link ) ;
link . click ( ) ;
link . remove ( ) ;
window . URL . revokeObjectURL ( url ) ;
} ,
onError : ( error ) = > {
toast . error ( ` Errore durante la generazione del PDF: ${ error . message } ` , {
id : "generate-pdf" ,
} ) ;
} ,
} ) ;
2026-03-04 19:12:01 +01:00
if ( raw ) {
return < Receipt data = { data } / > ;
}
2025-08-28 18:27:07 +02:00
return (
< div className = "mx-auto max-w-4xl" >
< div className = "space-y-6" >
< div className = "flex items-center justify-between" >
2025-10-10 16:18:43 +02:00
< h1 className = "font-bold text-2xl" > Ricevuta di cortesia < / h1 >
2025-08-04 17:45:44 +02:00
2026-03-08 01:02:57 +01:00
< Button onClick = { ( ) = > generatePdf ( { ordineId : data.ordineId } ) } >
2025-08-28 18:27:07 +02:00
Stampa
< / Button >
< / div >
2026-03-08 01:02:57 +01:00
< div >
< Card className = "p-4" >
2026-03-04 19:12:01 +01:00
< Receipt data = { data } / >
< / Card >
2025-08-28 18:27:07 +02:00
< / div >
< / div >
< / div >
) ;
2025-08-04 17:45:44 +02:00
}
2026-03-08 01:22:03 +01:00
export type PurchaseData = {
2026-03-08 01:02:57 +01:00
ordineId : OrdiniOrdineId ;
2025-08-28 18:27:07 +02:00
date : Date ;
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
clienteNome : string ;
clienteIndirizzo : string ;
paymentMethod : string ;
2026-03-08 01:22:03 +01:00
packName : string ;
sconto : number ;
amount_cent : number ;
} ;
2025-08-04 17:45:44 +02:00
interface ReceiptProps {
2025-08-28 18:27:07 +02:00
data : PurchaseData ;
2025-08-04 17:45:44 +02:00
}
function Receipt ( { data } : ReceiptProps ) {
2025-08-28 18:27:07 +02:00
const companyName = "Arcenia S.r.l." ;
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const companyAddress =
"Via Beata Giovanna 1\nBassano del Grappa (VI) 36061\nItalia" ;
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
const note =
2026-03-04 19:12:01 +01:00
"La presente è non costituisce ricevuta o fattura fiscale ai sensi dell'Art.21, DPR 633/72.\nSeguirà fattura elettronica direttamente al tuo indirizzo di posta." ;
2025-08-28 18:27:07 +02:00
const footer =
"Arcenia Srl. | Tel. +39 0424529869 | Email: arca@infoalloggi.it" ;
return (
2026-03-04 19:12:01 +01:00
< div className = "space-y-6" >
< div className = "flex items-start justify-between" >
< div >
< h1 className = "font-bold text-2xl" > { companyName } < / h1 >
< p className = "whitespace-pre-line text-sm" > { companyAddress } < / p >
2025-08-28 18:27:07 +02:00
< / div >
2026-03-04 19:12:01 +01:00
< div className = "relative size-24" >
< Image
alt = { ` ${ companyName } logo ` }
className = "object-contain"
fill
src = { "/favicon/favicon.png" }
/ >
2025-08-28 18:27:07 +02:00
< / div >
2026-03-04 19:12:01 +01:00
< / div >
< div className = "border-b pb-4" >
< h2 className = "text-center font-semibold text-xl" >
Ricevuta di cortesia
< / h2 >
< div className = "mt-2 flex justify-between" >
2025-08-28 18:27:07 +02:00
< div >
2026-03-08 01:02:57 +01:00
< p className = "text-muted-foreground text-sm" > ID Ordine < / p >
< p className = "text-sm" > { data . ordineId } < / p >
2026-03-04 19:12:01 +01:00
< / div >
< div className = "text-right" >
< p className = "text-muted-foreground text-sm" > Data < / p >
< p className = "font-medium" >
{ format ( data . date , "PPP" , {
locale : it ,
} ) }
< / p >
< p className = "text-sm" >
{ format ( data . date , "p" , {
locale : it ,
} ) }
2025-08-28 18:27:07 +02:00
< / p >
< / div >
< / div >
2026-03-04 19:12:01 +01:00
< / div >
< div className = "grid grid-cols-2 gap-6" >
2025-08-28 18:27:07 +02:00
< div >
2026-03-04 19:12:01 +01:00
< h3 className = "mb-1 font-semibold" > Intestatario : < / h3 >
< p className = "font-medium" > { data . clienteNome } < / p >
< p className = "whitespace-pre-line text-sm" > { data . clienteIndirizzo } < / p >
2025-08-28 18:27:07 +02:00
< / div >
2026-03-04 19:12:01 +01:00
< / div >
< div >
< table className = "w-full" >
< thead >
< tr className = "border-b" >
< th className = "py-2 text-left" > Descrizione < / th >
2026-03-08 01:22:03 +01:00
< th className = "py-2 text-right" > Sconto applicato < / th >
2026-03-04 19:12:01 +01:00
< th className = "py-2 text-right" > Importo < / th >
< / tr >
< / thead >
< tbody >
2026-03-08 01:22:03 +01:00
< tr className = "border-b" >
< td className = "py-2" > { data . packName } < / td >
< td className = "py-2 text-right" >
{ data . sconto > 0 && ` ${ data . sconto } % ` }
< / td >
< td className = "py-2 text-right" >
{ formatCurrency ( data . amount_cent / 100 ) }
< / td >
< / tr >
2026-03-04 19:12:01 +01:00
< / tbody >
< / table >
< / div >
< div className = "flex justify-end" >
< div className = "w-64" >
< div className = "mt-1 flex justify-between pt-2 font-bold" >
< span > Totale : < / span >
2026-03-08 01:22:03 +01:00
< span > { formatCurrency ( data . amount_cent / 100 ) } < / span >
2025-08-28 18:27:07 +02:00
< / div >
2026-03-04 19:12:01 +01:00
< div className = "flex justify-between py-1" >
< span > di cui IVA ( 22 % ) : < / span >
2026-03-08 01:22:03 +01:00
< span > { formatCurrency ( ( data . amount_cent / 100 ) * 0.22 ) } < / span >
2025-08-28 18:27:07 +02:00
< / div >
< / div >
2026-03-04 19:12:01 +01:00
< / div >
< div className = "border-t pt-4" >
< div className = "flex justify-between" >
< div >
< h3 className = "mb-1 font-semibold" > Metodo di pagamento < / h3 >
< p > { PaymentMethodToString ( data . paymentMethod as PaymentType ) } < / p >
< / div >
< div className = "text-right" >
< h3 className = "mb-1 font-semibold" > Status pagamento < / h3 >
< p className = "font-medium text-green-600" > Pagato < / p >
< / div >
2025-08-28 18:27:07 +02:00
< / div >
2026-03-04 19:12:01 +01:00
< / div >
< div className = "border-t pt-4" >
< h3 className = "mb-1 font-semibold" > Note < / h3 >
< p className = "whitespace-pre-line text-sm" > { note } < / p >
< / div >
2025-08-04 17:45:44 +02:00
2026-03-04 19:12:01 +01:00
< div className = "pt-6 text-center text-muted-foreground text-sm" >
< p > { footer } < / p >
2025-08-28 18:27:07 +02:00
< / div >
2026-03-04 19:12:01 +01:00
< / div >
2025-08-28 18:27:07 +02:00
) ;
2025-08-04 17:45:44 +02:00
}