"use client"; import html2canvas from "html2canvas-pro"; import jsPDF from "jspdf"; import { useEffect, useRef, useState } from "react"; import toast from "react-hot-toast"; import { useReactToPrint } from "react-to-print"; import z from "zod"; 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"; import { formatCurrency } from "~/lib/utils"; import type { Annunci } from "~/schemas/public/Annunci"; import { api } from "~/utils/api"; import { IconMatrix } from "./IconComponents"; import { GoogleMapsIcon, LogoSvg, WhatsAppIcon } from "./svgs"; import { Input } from "./ui/input"; import { Label } from "./ui/label"; import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; export function SchedaAnnuncioStampabile({ data }: { data: Annunci }) { const [inputEmail, setInputEmail] = useState(""); const [openPopover, setOpenPopover] = useState(false); const contentRef = useRef(null); const reactToPrintFn = useReactToPrint({ contentRef, //print: async (target) => {console.log("Printing...", target.contentDocument);}, }); 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({ contentRef, print: async (target) => { try { const htmlContent = target.contentDocument?.documentElement; 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); htmlContent.querySelectorAll(".print\\:border-none").forEach((el) => { el.classList.remove("border"); }); htmlContent.querySelectorAll(".print\\:shadow-none").forEach((el) => { el.classList.remove("shadow-sm"); }); 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]"); }); const canvas = await html2canvas(htmlContent, { //scale: 2, useCORS: true, logging: false, backgroundColor: "#ffffff", }); const imgData = canvas.toDataURL("image/png"); 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, to: inputEmail, codice: data.codice, numero: data.numero, nominativo: data.locatore, indirizzo: `${data.indirizzo}, ${data.civico} ${data.comune} ${data.cap} (${data.provincia})`, }); setInputEmail(""); } catch (e) { toast.error( `Errore durante l'invio dell'email: ${(e as Error).message}`, { id: "send-scheda-annuncio-email", }, ); console.error("Error during print:", e); setInputEmail(""); } }, }); return (

Scheda Annuncio Stampabile

setInputEmail(e.target.value)} onKeyDown={(e) => { if ( e.key === "Enter" && z.safeParse(z.email(), inputEmail).success ) { sendEmail(); } }} type="email" />
); } function SchedaAnnuncio({ data }: { data: Annunci }) { 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"; const [navigationUrl, setNavigationUrl] = useState( 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]); return (

Arcenia Srl

{companyAddress}

{/* Property Header */}

{data.titolo_it || "Immobile in Affitto"}

Riferimento: {data.codice}

{" "} Contatti (mandare un messaggio WhatsApp prima di chiamare)

{data.locatore}

{data.numero &&

Tel. {data.numero}

}
{/* Property Details Grid */}
{/* Location Details */}

Indirizzo

{data.indirizzo}, {data.civico} {data.comune} {data.cap} ( {data.provincia})

{navigationUrl && ( Apri in Google Maps )}
{/* Property Characteristics */} {/*

🏠 Caratteristiche

{data.mq && (

mq: {data.mq} mq

)} {data.numero_vani && (

Locali:{" "} {data.numero_vani}

)} {data.numero_camere && (

Camere:{" "} {data.numero_camere}

)} {data.numero_bagni && (

Bagni:{" "} {data.numero_bagni}

)}
*/}
{/* Pricing Information */}
{data.tipo && (

Tipologia

Affitto {data.tipo}

)} {data.prezzo && (

Canone Mensile

{formatCurrency(data.prezzo / 100)}

)} {(data.disponibile_da || data.consegna) && (

Disponibile da

{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, })}

)}
{/* Additional Features */}

Dotazioni e Servizi

{data.caratteristiche && filteredCaratteristiche(data.caratteristiche).map((item) => { if (!item.value) return null; return (
{item.text}: {item.value}
); })}
{/* Description */} {data.desc_it && ( <>

Descrizione

)}

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

{footer}

Documento generato in data: {new Date().toLocaleDateString("it-IT")}

); }