import { doctorTitle } from "@/helper"; // Icons import CopyBlueD from "@/components/icons/CopyBlueD"; import DownloadBlue from "@/components/icons/DownloadBlue"; import WhatsappBlueD from "@/components/icons/WhatsappBlueD"; import TelegramBlueD from "@/components/icons/TelegramBlueD"; import LinkedingBlueD from "@/components/icons/LinkedingBlueD"; // Packages import { useState } from "react"; import { toPng } from "html-to-image"; import html2canvas from "html2canvas"; import jsPDF from "jspdf"; import { Button } from "@mui/material"; import { toast } from "react-toastify"; const A4_WIDTH_MM = 210; const A4_HEIGHT_MM = 297; const VAZIR_WEIGHTS = [ [400, "Vazirmatn-RD-FD-Regular.ttf"], [500, "Vazirmatn-RD-FD-Medium.ttf"], [600, "Vazirmatn-RD-FD-SemiBold.ttf"], [700, "Vazirmatn-RD-FD-Bold.ttf"], [800, "Vazirmatn-RD-FD-ExtraBold.ttf"], ]; let vazirEmbedCssPromise; const getVazirEmbedCss = () => { vazirEmbedCssPromise ??= Promise.all( VAZIR_WEIGHTS.map(async ([weight, file]) => { const res = await fetch(`/fonts/vazir/${file}`); const blob = await res.blob(); const dataUrl = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob); }); return `@font-face{font-family:vazir;src:url(${dataUrl});font-weight:${weight};}`; }) ).then((faces) => faces.join("\n")); return vazirEmbedCssPromise; }; const waitForImages = async (element) => { const imgs = Array.from(element.querySelectorAll("img")); await Promise.all( imgs.map((img) => { if (img.complete && img.naturalWidth !== 0) { return img.decode?.().catch(() => {}) ?? Promise.resolve(); } return new Promise((resolve) => { img.onload = () => resolve(); img.onerror = () => resolve(); }); }) ); }; function List({ hiddenRef, data, qrReady }) { const [downloading, setDownloading] = useState(false); const handleDownloadPDF = async () => { const element = hiddenRef.current; if (!element || downloading) return; if (!qrReady) { toast.info("در حال آماده‌سازی پوستر، لحظه‌ای صبر کنید..."); return; } setDownloading(true); try { await waitForImages(element); let imgData; let pxWidth; let pxHeight; try { const fontEmbedCSS = await getVazirEmbedCss(); const options = { pixelRatio: 2, backgroundColor: "#ffffff", style: { opacity: "1" }, fontEmbedCSS, }; imgData = await toPng(element, options); pxWidth = element.offsetWidth * 2; pxHeight = element.offsetHeight * 2; } catch { const canvas = await html2canvas(element, { backgroundColor: "#ffffff", useCORS: true, scale: 2, imageTimeout: 15000, }); imgData = canvas.toDataURL("image/png"); pxWidth = canvas.width; pxHeight = canvas.height; } // کاغذ همیشه A4 است، نه اندازه‌ای که از نسبت تصویر درمی‌آید: خروجی قبلی // ۲۱۰×۲۶۲٫۵ میلی‌متر بود و روی هیچ پرینتری A4 حساب نمی‌شد. const pdf = new jsPDF({ orientation: "portrait", unit: "mm", format: "a4" }); // پوستر خودش نسبت A4 دارد، پس عملاً کل صفحه را پر می‌کند. این محاسبه تور // ایمنی است تا اگر ابعاد پوستر روزی عوض شد، تصویر از کاغذ بیرون نزند. let width = A4_WIDTH_MM; let height = (pxHeight / pxWidth) * width; if (height > A4_HEIGHT_MM) { height = A4_HEIGHT_MM; width = (pxWidth / pxHeight) * height; } pdf.addImage( imgData, "PNG", (A4_WIDTH_MM - width) / 2, (A4_HEIGHT_MM - height) / 2, width, height, ); const safeName = (data?.name ?? "doctor").replace(/[\\/:*?"<>|]+/g, "-"); pdf.save(`poster-${safeName}.pdf`); } catch { toast.error("ساخت پوستر ناموفق بود، دوباره تلاش کنید"); } finally { setDownloading(false); } }; const getShareUrl = () => typeof window !== "undefined" ? window.location.href : ""; const getShareText = () => data?.name ? `معرفی ${doctorTitle(data.name)} در نوبت 724` : "معرفی پزشک در نوبت 724"; const openShareWindow = (url) => { if (typeof window !== "undefined") { window.open(url, "_blank", "noopener,noreferrer"); } }; const handleWhatsapp = () => { const text = encodeURIComponent(`${getShareText()}\n${getShareUrl()}`); openShareWindow(`https://wa.me/?text=${text}`); }; const handleTelegram = () => { const url = encodeURIComponent(getShareUrl()); const text = encodeURIComponent(getShareText()); openShareWindow(`https://t.me/share/url?url=${url}&text=${text}`); }; const handleLinkedin = () => { const url = encodeURIComponent(getShareUrl()); openShareWindow( `https://www.linkedin.com/sharing/share-offsite/?url=${url}` ); }; const handleCopyLink = async () => { try { await navigator.clipboard.writeText(getShareUrl()); toast.success("لینک کپی شد"); } catch { toast.error("کپی لینک ناموفق بود"); } }; const listIcons = [ { name: "واتساپ", icon: , onClick: handleWhatsapp }, { name: "تلگرام", icon: , onClick: handleTelegram }, { name: "لینکدین", icon: , onClick: handleLinkedin }, { name: "کپی لینک", icon: , onClick: handleCopyLink }, { name: "دانلود", icon: , onClick: handleDownloadPDF, disabled: downloading, }, ]; return ( <>
    {listIcons.map((item, idx) => (
  • {item.name}
  • ))}
); } export default List;