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" ;
2025-08-04 17:45:44 +02:00
import { useRef } from "react" ;
2025-08-28 18:27:07 +02:00
import { useReactToPrint } from "react-to-print" ;
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" ;
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 ;
} ) {
2025-08-28 18:27:07 +02:00
const contentRef = useRef < HTMLDivElement > ( null ) ;
const reactToPrintFn = useReactToPrint ( {
contentRef ,
//print: async (target) => {console.log("Printing...", target.contentDocument);},
} ) ;
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
2025-08-29 16:18:32 +02:00
< Button className = "print:hidden" onClick = { ( ) = > reactToPrintFn ( ) } >
2025-08-28 18:27:07 +02:00
Stampa
< / Button >
< / div >
< div ref = { contentRef } >
2026-03-04 19:12:01 +01:00
< Card className = "p-4 print:border-none print:shadow-none" >
< Receipt data = { data } / >
< / Card >
2025-08-28 18:27:07 +02:00
< / div >
< / div >
< / div >
) ;
2025-08-04 17:45:44 +02:00
}
interface Item {
2025-08-28 18:27:07 +02:00
description : string ;
price : number ;
discount : number ;
2025-08-04 17:45:44 +02:00
}
export interface PurchaseData {
2025-08-28 18:27:07 +02:00
paymentId : string ;
date : Date ;
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
clienteNome : string ;
clienteIndirizzo : string ;
paymentMethod : string ;
items : Item [ ] ;
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 total = data . items . reduce (
( acc , item ) = > acc + item . price * ( 1 - item . discount ) ,
0 ,
) ;
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-04 19:12:01 +01:00
< p className = "text-muted-foreground text-sm" > ID Pagamento < / p >
< p className = "text-sm" > { data . paymentId } < / p >
< / 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 >
< th className = "py-2 text-right" > Prezzo < / th >
< th className = "py-2 text-right" > Sconto < / th >
< th className = "py-2 text-right" > Importo < / th >
< / tr >
< / thead >
< tbody >
{ data . items . map ( ( item ) = > (
< tr className = "border-b" key = { item . description } >
< td className = "py-2" > { item . description } < / td >
< td className = "py-2 text-right" >
{ formatCurrency ( item . price ) }
< / td >
< td className = "py-2 text-right" >
{ item . discount > 0
? ` - ${ ( item . discount * 100 ) . toFixed ( 0 ) } % `
: "" }
< / td >
< td className = "py-2 text-right" >
{ formatCurrency ( item . price * ( 1 - item . discount ) ) }
< / td >
< / tr >
) ) }
< / 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 >
< span > { formatCurrency ( total ) } < / 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 >
< span > { formatCurrency ( total * 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
}