2025-08-29 18:18:37 +02:00
|
|
|
"use client";
|
|
|
|
|
|
2025-11-19 17:18:28 +01:00
|
|
|
import html2canvas from "html2canvas-pro";
|
|
|
|
|
import jsPDF from "jspdf";
|
2025-10-16 10:28:24 +02:00
|
|
|
import { useEffect, useRef, useState } from "react";
|
2025-11-20 11:59:24 +01:00
|
|
|
import toast from "react-hot-toast";
|
2025-08-29 18:18:37 +02:00
|
|
|
import { useReactToPrint } from "react-to-print";
|
2025-11-20 11:59:24 +01:00
|
|
|
import z from "zod";
|
2025-08-29 18:18:37 +02:00
|
|
|
import { Button } from "~/components/ui/button";
|
|
|
|
|
import { Card } from "~/components/ui/card";
|
|
|
|
|
import { filteredCaratteristiche } from "~/hooks/schedaAnnuncioUtils";
|
|
|
|
|
import { it } from "~/i18n/it";
|
|
|
|
|
import { handleConsegna } from "~/lib/annuncio_details";
|
|
|
|
|
import { replaceWithBr } from "~/lib/newlineToBr";
|
2025-09-10 15:42:45 +02:00
|
|
|
import { formatCurrency } from "~/lib/utils";
|
2025-08-29 18:18:37 +02:00
|
|
|
import type { Annunci } from "~/schemas/public/Annunci";
|
2025-11-19 17:18:28 +01:00
|
|
|
import { api } from "~/utils/api";
|
2025-08-29 18:18:37 +02:00
|
|
|
import { IconMatrix } from "./IconComponents";
|
2025-10-16 10:28:24 +02:00
|
|
|
import { GoogleMapsIcon, LogoSvg, WhatsAppIcon } from "./svgs";
|
2025-11-20 11:59:24 +01:00
|
|
|
import { Input } from "./ui/input";
|
|
|
|
|
import { Label } from "./ui/label";
|
|
|
|
|
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
|
2025-08-29 18:18:37 +02:00
|
|
|
|
|
|
|
|
export function SchedaAnnuncioStampabile({ data }: { data: Annunci }) {
|
2025-11-20 11:59:24 +01:00
|
|
|
const [inputEmail, setInputEmail] = useState<string>("");
|
|
|
|
|
const [openPopover, setOpenPopover] = useState<boolean>(false);
|
2025-08-29 18:18:37 +02:00
|
|
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const reactToPrintFn = useReactToPrint({
|
|
|
|
|
contentRef,
|
|
|
|
|
//print: async (target) => {console.log("Printing...", target.contentDocument);},
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-20 11:59:24 +01:00
|
|
|
const { mutate } = api.comunicazioni.sendSchedaAnnuncioEmail.useMutation({
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
toast.success("Email inviata con successo!", {
|
|
|
|
|
id: "send-scheda-annuncio-email",
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
onError: (error) => {
|
|
|
|
|
toast.error(`Errore durante l'invio dell'email: ${error.message}`, {
|
|
|
|
|
id: "send-scheda-annuncio-email",
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const sendEmail = useReactToPrint({
|
2025-11-19 17:18:28 +01:00
|
|
|
contentRef,
|
|
|
|
|
print: async (target) => {
|
|
|
|
|
try {
|
|
|
|
|
const htmlContent = target.contentDocument?.documentElement;
|
2025-11-20 11:59:24 +01:00
|
|
|
if (!htmlContent) {
|
|
|
|
|
toast.error("Impossibile generare il contenuto per la stampa.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!data || !inputEmail || !data.locatore || !data.numero) {
|
|
|
|
|
toast.error("Dati annuncio o indirizzo email mancanti.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
toast.loading("Invio email in corso...", {
|
|
|
|
|
id: "send-scheda-annuncio-email",
|
|
|
|
|
});
|
|
|
|
|
setOpenPopover(false);
|
2025-11-19 17:18:28 +01:00
|
|
|
htmlContent.querySelectorAll(".print\\:border-none").forEach((el) => {
|
|
|
|
|
el.classList.remove("border");
|
|
|
|
|
});
|
|
|
|
|
htmlContent.querySelectorAll(".print\\:shadow-none").forEach((el) => {
|
|
|
|
|
el.classList.remove("shadow-sm");
|
|
|
|
|
});
|
2025-11-20 11:59:24 +01:00
|
|
|
htmlContent.querySelectorAll("#navigationLink").forEach((el) => {
|
|
|
|
|
el.classList.remove("flex");
|
|
|
|
|
el.classList.add("hidden");
|
|
|
|
|
});
|
|
|
|
|
htmlContent.querySelectorAll("#mainLogoSvg text").forEach((el) => {
|
|
|
|
|
el.classList.remove("font-sans");
|
|
|
|
|
el.classList.add("font-[system-ui]");
|
|
|
|
|
});
|
2025-11-19 17:18:28 +01:00
|
|
|
const canvas = await html2canvas(htmlContent, {
|
|
|
|
|
//scale: 2,
|
|
|
|
|
useCORS: true,
|
|
|
|
|
logging: false,
|
|
|
|
|
backgroundColor: "#ffffff",
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-20 11:59:24 +01:00
|
|
|
const imgData = canvas.toDataURL("image/png");
|
2025-11-19 17:18:28 +01:00
|
|
|
const pdf = new jsPDF("p", "mm", "a4");
|
|
|
|
|
|
|
|
|
|
// A4 dimensions in mm
|
|
|
|
|
const pdfWidth = pdf.internal.pageSize.getWidth();
|
|
|
|
|
const pdfHeight = pdf.internal.pageSize.getHeight();
|
|
|
|
|
|
|
|
|
|
// Define margins (in mm)
|
|
|
|
|
const marginTop = 5;
|
|
|
|
|
const marginRight = 5;
|
|
|
|
|
const marginBottom = 5;
|
|
|
|
|
const marginLeft = 5;
|
|
|
|
|
|
|
|
|
|
// Calculate available space
|
|
|
|
|
const availableWidth = pdfWidth - marginLeft - marginRight;
|
|
|
|
|
const availableHeight = pdfHeight - marginTop - marginBottom;
|
|
|
|
|
|
|
|
|
|
// Calculate image dimensions
|
|
|
|
|
const imgProps = pdf.getImageProperties(imgData);
|
|
|
|
|
const imgWidth = imgProps.width;
|
|
|
|
|
const imgHeight = imgProps.height;
|
|
|
|
|
|
|
|
|
|
// Calculate how the image should fit with margins
|
|
|
|
|
const ratio = availableWidth / imgWidth;
|
|
|
|
|
const scaledHeight = imgHeight * ratio;
|
|
|
|
|
|
|
|
|
|
// Check if content needs multiple pages
|
|
|
|
|
if (scaledHeight <= availableHeight) {
|
|
|
|
|
// Single page - content fits
|
|
|
|
|
pdf.addImage(
|
|
|
|
|
imgData,
|
|
|
|
|
"PNG",
|
|
|
|
|
marginLeft,
|
|
|
|
|
marginTop,
|
|
|
|
|
availableWidth,
|
|
|
|
|
scaledHeight,
|
|
|
|
|
undefined,
|
|
|
|
|
"FAST",
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
// Multiple pages needed
|
|
|
|
|
let heightLeft = scaledHeight;
|
|
|
|
|
let position = marginTop;
|
|
|
|
|
|
|
|
|
|
// Add first page
|
|
|
|
|
pdf.addImage(
|
|
|
|
|
imgData,
|
|
|
|
|
"PNG",
|
|
|
|
|
marginLeft,
|
|
|
|
|
position,
|
|
|
|
|
availableWidth,
|
|
|
|
|
scaledHeight,
|
|
|
|
|
undefined,
|
|
|
|
|
"FAST",
|
|
|
|
|
);
|
|
|
|
|
heightLeft -= availableHeight;
|
|
|
|
|
|
|
|
|
|
// Add remaining pages
|
|
|
|
|
while (heightLeft > 0) {
|
|
|
|
|
position = marginTop - (scaledHeight - heightLeft);
|
|
|
|
|
pdf.addPage();
|
|
|
|
|
pdf.addImage(
|
|
|
|
|
imgData,
|
|
|
|
|
"PNG",
|
|
|
|
|
marginLeft,
|
|
|
|
|
position,
|
|
|
|
|
availableWidth,
|
|
|
|
|
scaledHeight,
|
|
|
|
|
undefined,
|
|
|
|
|
"FAST",
|
|
|
|
|
);
|
|
|
|
|
heightLeft -= availableHeight;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const pdfBase64 = pdf.output("dataurlstring");
|
|
|
|
|
|
|
|
|
|
mutate({
|
|
|
|
|
pdf: pdfBase64,
|
2025-11-20 11:59:24 +01:00
|
|
|
to: inputEmail,
|
2025-11-19 17:18:28 +01:00
|
|
|
codice: data.codice,
|
2025-11-20 11:59:24 +01:00
|
|
|
numero: data.numero,
|
|
|
|
|
nominativo: data.locatore,
|
|
|
|
|
indirizzo: `${data.indirizzo}, ${data.civico} ${data.comune} ${data.cap} (${data.provincia})`,
|
2025-11-19 17:18:28 +01:00
|
|
|
});
|
2025-11-20 11:59:24 +01:00
|
|
|
setInputEmail("");
|
2025-11-19 17:18:28 +01:00
|
|
|
} catch (e) {
|
2025-11-20 11:59:24 +01:00
|
|
|
toast.error(
|
|
|
|
|
`Errore durante l'invio dell'email: ${(e as Error).message}`,
|
|
|
|
|
{
|
|
|
|
|
id: "send-scheda-annuncio-email",
|
|
|
|
|
},
|
|
|
|
|
);
|
2025-11-19 17:18:28 +01:00
|
|
|
console.error("Error during print:", e);
|
2025-11-20 11:59:24 +01:00
|
|
|
setInputEmail("");
|
2025-11-19 17:18:28 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-29 18:18:37 +02:00
|
|
|
return (
|
2025-09-01 11:37:43 +02:00
|
|
|
<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">Scheda Annuncio Stampabile</h1>
|
2025-11-20 11:59:24 +01:00
|
|
|
<div className="flex gap-2">
|
|
|
|
|
<Button className="print:hidden" onClick={() => reactToPrintFn()}>
|
|
|
|
|
Stampa Scheda
|
|
|
|
|
</Button>
|
|
|
|
|
<Popover onOpenChange={setOpenPopover} open={openPopover}>
|
|
|
|
|
<PopoverTrigger asChild>
|
|
|
|
|
<Button className="print:hidden" variant="outline">
|
|
|
|
|
Invia tramite email
|
|
|
|
|
</Button>
|
|
|
|
|
</PopoverTrigger>
|
|
|
|
|
<PopoverContent className="flex w-80 flex-col gap-4 print:hidden">
|
|
|
|
|
<Label htmlFor="indirizzo">Indirizzo Email</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="indirizzo"
|
|
|
|
|
onChange={(e) => setInputEmail(e.target.value)}
|
|
|
|
|
onKeyDown={(e) => {
|
|
|
|
|
if (
|
|
|
|
|
e.key === "Enter" &&
|
|
|
|
|
z.safeParse(z.email(), inputEmail).success
|
|
|
|
|
) {
|
|
|
|
|
sendEmail();
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
type="email"
|
|
|
|
|
/>
|
|
|
|
|
<Button
|
|
|
|
|
disabled={
|
|
|
|
|
z.safeParse(z.email(), inputEmail).success === false
|
|
|
|
|
}
|
|
|
|
|
onClick={sendEmail}
|
|
|
|
|
>
|
|
|
|
|
Invia
|
|
|
|
|
</Button>
|
|
|
|
|
</PopoverContent>
|
|
|
|
|
</Popover>
|
|
|
|
|
</div>
|
2025-09-01 11:37:43 +02:00
|
|
|
</div>
|
|
|
|
|
<div ref={contentRef}>
|
|
|
|
|
<SchedaAnnuncio data={data} />
|
2025-08-29 18:18:37 +02:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-09-01 11:37:43 +02:00
|
|
|
</div>
|
2025-08-29 18:18:37 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-19 17:18:28 +01:00
|
|
|
export function SchedaAnnuncio({ data }: { data: Annunci }) {
|
2025-08-29 18:18:37 +02:00
|
|
|
const companyAddress =
|
|
|
|
|
"Via Beata Giovanna, 1 a Bassano del Grappa (VI)\nTel. +39 0424529869\nEmail: arca@infoalloggi.it";
|
|
|
|
|
|
|
|
|
|
const footer =
|
|
|
|
|
"Arcenia Srl. | Tel. +39 0424529869 | Email: arca@infoalloggi.it";
|
2025-10-16 10:28:24 +02:00
|
|
|
|
|
|
|
|
const [navigationUrl, setNavigationUrl] = useState<string | undefined>(
|
|
|
|
|
undefined,
|
|
|
|
|
);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!data) return;
|
|
|
|
|
if (typeof window === "undefined") return;
|
|
|
|
|
if (
|
|
|
|
|
navigator.userAgent.toUpperCase().includes("MAC") ||
|
|
|
|
|
navigator.userAgent.toUpperCase().includes("IPAD") ||
|
|
|
|
|
navigator.userAgent.toUpperCase().includes("IPHONE") ||
|
|
|
|
|
navigator.userAgent.toUpperCase().includes("IOS") ||
|
|
|
|
|
navigator.userAgent.toUpperCase().includes("IPOD")
|
|
|
|
|
) {
|
|
|
|
|
setNavigationUrl(
|
|
|
|
|
`maps://www.google.com/maps/dir/?api=1&travelmode=driving&layer=traffic&destination=${data.lat},${data.lon}`,
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
setNavigationUrl(
|
|
|
|
|
`https://www.google.com/maps/dir/?api=1&travelmode=driving&layer=traffic&destination=${data.lat},${data.lon}`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}, [data]);
|
|
|
|
|
|
2025-08-29 18:18:37 +02:00
|
|
|
return (
|
|
|
|
|
<Card className="p-4 print:border-none print:shadow-none">
|
2025-10-16 10:28:24 +02:00
|
|
|
<div className="space-y-8">
|
2025-08-29 18:18:37 +02:00
|
|
|
<div className="flex items-start justify-between">
|
|
|
|
|
<div>
|
2025-11-14 17:21:21 +01:00
|
|
|
<LogoSvg className="h-10 w-auto" />
|
2025-08-29 18:18:37 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="relative">
|
2025-10-10 16:18:43 +02:00
|
|
|
<p className="text-right font-semibold text-lg">Arcenia Srl</p>
|
|
|
|
|
<p className="whitespace-pre-line text-right text-sm">
|
2025-08-29 18:18:37 +02:00
|
|
|
{companyAddress}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{/* Property Header */}
|
|
|
|
|
<div className="space-y-2 text-center">
|
2025-10-10 16:18:43 +02:00
|
|
|
<h2 className="font-bold text-primary text-xl">
|
2025-08-29 18:18:37 +02:00
|
|
|
{data.titolo_it || "Immobile in Affitto"}
|
|
|
|
|
</h2>
|
|
|
|
|
<p className="text-lg text-muted-foreground">
|
|
|
|
|
Riferimento: <strong>{data.codice}</strong>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
2025-10-16 10:28:24 +02:00
|
|
|
<div className="rounded-lg bg-primary/5 p-4 outline-2 outline-green-500">
|
|
|
|
|
<h3 className="mb-2 inline-flex items-center gap-2 font-semibold text-lg text-primary">
|
|
|
|
|
<WhatsAppIcon className="size-6 fill-green-500 stroke-green-500" />{" "}
|
|
|
|
|
Contatti
|
|
|
|
|
<span className="text-base">
|
|
|
|
|
(mandare un messaggio WhatsApp prima di chiamare)
|
|
|
|
|
</span>
|
|
|
|
|
</h3>
|
|
|
|
|
<div className="space-y-1">
|
|
|
|
|
<p>{data.locatore}</p>
|
|
|
|
|
{data.numero && <p className="font-semibold">Tel. {data.numero}</p>}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-29 18:18:37 +02:00
|
|
|
|
|
|
|
|
{/* Property Details Grid */}
|
2025-10-16 10:28:24 +02:00
|
|
|
<div className="grid grid-cols-1 gap-6 pb-1">
|
2025-08-29 18:18:37 +02:00
|
|
|
{/* Location Details */}
|
|
|
|
|
<div className="space-y-3">
|
2025-10-16 10:28:24 +02:00
|
|
|
<h3 className="border-b pb-1 font-semibold text-lg">Indirizzo</h3>
|
|
|
|
|
<div className="flex items-center gap-8">
|
|
|
|
|
<p className="font-semibold">
|
|
|
|
|
{data.indirizzo}, {data.civico} {data.comune} {data.cap} (
|
2025-08-29 18:18:37 +02:00
|
|
|
{data.provincia})
|
|
|
|
|
</p>
|
2025-10-16 10:28:24 +02:00
|
|
|
{navigationUrl && (
|
|
|
|
|
<a
|
|
|
|
|
className="flex items-center gap-2 text-blue-600 underline underline-offset-2"
|
|
|
|
|
href={navigationUrl}
|
2025-11-20 11:59:24 +01:00
|
|
|
id="navigationLink"
|
2025-10-16 10:28:24 +02:00
|
|
|
rel="noreferrer"
|
|
|
|
|
target="_blank"
|
|
|
|
|
>
|
|
|
|
|
<span>Apri in Google Maps</span>
|
|
|
|
|
<GoogleMapsIcon className="size-6" />
|
|
|
|
|
</a>
|
2025-08-29 18:18:37 +02:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Property Characteristics */}
|
2025-10-16 10:28:24 +02:00
|
|
|
{/* <div className="space-y-3">
|
2025-10-10 16:18:43 +02:00
|
|
|
<h3 className="border-b pb-1 font-semibold text-lg">
|
2025-08-29 18:18:37 +02:00
|
|
|
🏠 Caratteristiche
|
|
|
|
|
</h3>
|
|
|
|
|
<div className="space-y-2 text-sm">
|
|
|
|
|
{data.mq && (
|
|
|
|
|
<p>
|
|
|
|
|
<span className="font-medium">mq:</span> {data.mq} mq
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
{data.numero_vani && (
|
|
|
|
|
<p>
|
|
|
|
|
<span className="font-medium">Locali:</span>{" "}
|
|
|
|
|
{data.numero_vani}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
{data.numero_camere && (
|
|
|
|
|
<p>
|
|
|
|
|
<span className="font-medium">Camere:</span>{" "}
|
|
|
|
|
{data.numero_camere}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
{data.numero_bagni && (
|
|
|
|
|
<p>
|
|
|
|
|
<span className="font-medium">Bagni:</span>{" "}
|
|
|
|
|
{data.numero_bagni}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-10-16 10:28:24 +02:00
|
|
|
</div> */}
|
2025-08-29 18:18:37 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Pricing Information */}
|
|
|
|
|
|
|
|
|
|
<div className="space-y-3">
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="grid grid-cols-3 gap-4 text-sm">
|
2025-08-29 18:18:37 +02:00
|
|
|
{data.tipo && (
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="rounded bg-gray-50 p-3">
|
2025-08-29 18:18:37 +02:00
|
|
|
<p className="font-medium text-primary">Tipologia</p>
|
2025-10-10 16:18:43 +02:00
|
|
|
<p className="font-bold text-xl">Affitto {data.tipo}</p>
|
2025-08-29 18:18:37 +02:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{data.prezzo && (
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="rounded bg-gray-50 p-3">
|
2025-08-29 18:18:37 +02:00
|
|
|
<p className="font-medium text-primary">Canone Mensile</p>
|
2025-10-10 16:18:43 +02:00
|
|
|
<p className="font-bold text-xl">
|
2025-09-10 15:42:45 +02:00
|
|
|
{formatCurrency(data.prezzo / 100)}
|
2025-08-29 18:18:37 +02:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{(data.disponibile_da || data.consegna) && (
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="rounded bg-gray-50 p-3">
|
2025-08-29 18:18:37 +02:00
|
|
|
<p className="font-medium text-primary">Disponibile da</p>
|
2025-10-10 16:18:43 +02:00
|
|
|
<p className="font-bold text-xl">
|
2025-08-29 18:18:37 +02:00
|
|
|
{data.disponibile_da
|
|
|
|
|
? new Date(data.disponibile_da).toLocaleDateString()
|
|
|
|
|
: data.consegna &&
|
|
|
|
|
handleConsegna({
|
|
|
|
|
aggiornamento: it.card.in_aggiornamento,
|
|
|
|
|
consegna: data.consegna,
|
|
|
|
|
consegna_da: it.card.consegna_da,
|
|
|
|
|
mesi: it.preferenze.mesi,
|
|
|
|
|
subito: it.card.consegna_subito,
|
|
|
|
|
})}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Additional Features */}
|
|
|
|
|
|
|
|
|
|
<div className="space-y-3">
|
2025-10-10 16:18:43 +02:00
|
|
|
<h3 className="border-b pb-1 font-semibold text-lg">
|
2025-10-16 10:28:24 +02:00
|
|
|
Dotazioni e Servizi
|
2025-08-29 18:18:37 +02:00
|
|
|
</h3>
|
|
|
|
|
<div className="grid grid-cols-4 gap-2 text-sm">
|
|
|
|
|
{data.caratteristiche &&
|
2025-10-28 11:55:01 +01:00
|
|
|
filteredCaratteristiche(data.caratteristiche).map((item) => {
|
|
|
|
|
if (!item.value) return null;
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className="flex items-center justify-start gap-2"
|
|
|
|
|
key={item.text}
|
|
|
|
|
>
|
2025-11-03 10:59:45 +01:00
|
|
|
<span>
|
2025-10-28 11:55:01 +01:00
|
|
|
<IconMatrix type={item.icon} />
|
|
|
|
|
</span>
|
|
|
|
|
<span>
|
|
|
|
|
{item.text}: {item.value}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2025-08-29 18:18:37 +02:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-10-16 10:28:24 +02:00
|
|
|
|
2025-08-29 18:18:37 +02:00
|
|
|
{/* Description */}
|
|
|
|
|
{data.desc_it && (
|
|
|
|
|
<>
|
|
|
|
|
<div className="space-y-3">
|
2025-10-10 16:18:43 +02:00
|
|
|
<h3 className="border-b pb-1 font-semibold text-lg">
|
2025-10-16 10:28:24 +02:00
|
|
|
Descrizione
|
2025-08-29 18:18:37 +02:00
|
|
|
</h3>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="text-justify text-sm leading-relaxed">
|
2025-08-29 18:18:37 +02:00
|
|
|
<p
|
|
|
|
|
dangerouslySetInnerHTML={{
|
|
|
|
|
__html: replaceWithBr(data.desc_it),
|
|
|
|
|
}}
|
|
|
|
|
></p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
2025-10-28 12:44:26 +01:00
|
|
|
<div className="mx-auto max-w-2xl pt-2 text-center text-muted-foreground text-xs">
|
|
|
|
|
<p>
|
|
|
|
|
Informazione strettamente riservata ed indirizzata all'Utente
|
|
|
|
|
Arca-Infoalloggi nel rispetto dell' Art. F. Precisazione dei Tuoi
|
|
|
|
|
Obblighi e responsabilità delle Condizioni Generali di Contratto
|
|
|
|
|
(CGC) accettate
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
2025-10-10 16:18:43 +02:00
|
|
|
<div className="pt-2 text-center text-muted-foreground text-xs">
|
2025-08-29 18:18:37 +02:00
|
|
|
<p>{footer}</p>
|
|
|
|
|
<p className="mt-1">
|
|
|
|
|
Documento generato in data: {new Date().toLocaleDateString("it-IT")}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
|
|
|
|
}
|