infoalloggi-monorepo/apps/infoalloggi/src/components/acquisto_receipt.tsx
2025-08-29 16:18:32 +02:00

187 lines
5.3 KiB
TypeScript

"use client";
import { format } from "date-fns";
import { it } from "date-fns/locale";
import Image from "next/image";
import { useRef } from "react";
import { useReactToPrint } from "react-to-print";
import { Button } from "~/components/ui/button";
import { Card } from "~/components/ui/card";
import { PaymentMethodToString, type PaymentType } from "~/i18n/stripe";
import { formatCurrency } from "~/lib/utils";
export function ReceiptGenerator({ data }: { data: PurchaseData }) {
const contentRef = useRef<HTMLDivElement>(null);
const reactToPrintFn = useReactToPrint({
contentRef,
//print: async (target) => {console.log("Printing...", target.contentDocument);},
});
return (
<div className="mx-auto max-w-4xl">
<div className="space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold">Ricevuta di cortesia</h1>
<Button className="print:hidden" onClick={() => reactToPrintFn()}>
Stampa
</Button>
</div>
<div ref={contentRef}>
<Receipt data={data} />
</div>
</div>
</div>
);
}
interface Item {
description: string;
price: number;
discount: number;
}
export interface PurchaseData {
paymentId: string;
date: Date;
clienteNome: string;
clienteIndirizzo: string;
paymentMethod: string;
items: Item[];
}
interface ReceiptProps {
data: PurchaseData;
}
function Receipt({ data }: ReceiptProps) {
const companyName = "Arcenia S.r.l.";
const companyAddress =
"Via Beata Giovanna 1\nBassano del Grappa (VI) 36061\nItalia";
const total = data.items.reduce(
(acc, item) => acc + item.price * (1 - item.discount),
0,
);
const note =
"La presente è non costituisce ricevuta o fattura fiscale.\nRiceverai la fattura elettronica direttamente al tuo indirizzo di posta.";
const footer =
"Arcenia Srl. | Tel. +39 0424529869 | Email: arca@infoalloggi.it";
return (
<Card className="p-4 print:border-none print:shadow-none">
<div className="space-y-6">
<div className="flex items-start justify-between">
<div>
<h1 className="text-2xl font-bold">{companyName}</h1>
<p className="text-sm whitespace-pre-line">{companyAddress}</p>
</div>
<div className="relative size-24">
<Image
alt={`${companyName} logo`}
className="object-contain"
fill
src={"/favicon/favicon.png"}
/>
</div>
</div>
<div className="border-b pb-4">
<h2 className="text-center text-xl font-semibold">
Ricevuta di cortesia
</h2>
<div className="mt-2 flex justify-between">
<div>
<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,
})}
</p>
</div>
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div>
<h3 className="mb-1 font-semibold">Intestatario:</h3>
<p className="font-medium">{data.clienteNome}</p>
<p className="text-sm whitespace-pre-line">
{data.clienteIndirizzo}
</p>
</div>
</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, idx) => (
<tr className="border-b" key={idx}>
<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>
</div>
<div className="flex justify-between py-1">
<span>di cui IVA (22%):</span>
<span>{formatCurrency(total * 0.22)}</span>
</div>
</div>
</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>
</div>
</div>
<div className="border-t pt-4">
<h3 className="mb-1 font-semibold">Note</h3>
<p className="text-sm whitespace-pre-line">{note}</p>
</div>
<div className="text-muted-foreground pt-6 text-center text-sm">
<p>{footer}</p>
</div>
</div>
</Card>
);
}