diff --git a/components/doctor/detailDoctor/List.js b/components/doctor/detailDoctor/List.js
index 031d1f5..b304633 100644
--- a/components/doctor/detailDoctor/List.js
+++ b/components/doctor/detailDoctor/List.js
@@ -7,11 +7,38 @@ 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 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(
@@ -43,18 +70,35 @@ function List({ hiddenRef, data, qrReady }) {
try {
await waitForImages(element);
- const canvas = await html2canvas(element, {
- backgroundColor: "#ffffff",
- useCORS: true,
- scale: 2,
- imageTimeout: 15000,
- });
+ let imgData;
+ let pxWidth;
+ let pxHeight;
- const imgData = canvas.toDataURL("image/png");
+ try {
+ const fontEmbedCSS = await getVazirEmbedCss();
+ imgData = await toPng(element, {
+ pixelRatio: 2,
+ backgroundColor: "#ffffff",
+ style: { opacity: "1" },
+ fontEmbedCSS,
+ });
+ 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;
+ }
const imgWidth = 210;
- const pxPerMm = canvas.width / imgWidth;
- const imgHeight = canvas.height / pxPerMm;
+ const pxPerMm = pxWidth / imgWidth;
+ const imgHeight = pxHeight / pxPerMm;
const pdf = new jsPDF({
orientation: "portrait",
diff --git a/components/doctor/poster/QrImg.js b/components/doctor/poster/QrImg.js
index 2f774e3..fa68529 100644
--- a/components/doctor/poster/QrImg.js
+++ b/components/doctor/poster/QrImg.js
@@ -1,32 +1,31 @@
-import { useState, useEffect } from "react";
+import { useRef, useEffect } from "react";
import QRCode from "qrcode";
import { getStateInfoClient } from "@/lib/getStateInfoClient";
export default function QrImg({ onReady, size = 168 }) {
- const [qrCodeData, setQrCodeData] = useState("");
+ const canvasRef = useRef(null);
useEffect(() => {
const { fullUrl } = getStateInfoClient();
- if (fullUrl) {
- QRCode.toDataURL(fullUrl, { margin: 1, width: size * 2 }).then((url) => {
- setQrCodeData(url);
- onReady?.();
- });
+ if (fullUrl && canvasRef.current) {
+ QRCode.toCanvas(
+ canvasRef.current,
+ fullUrl,
+ { width: size, margin: 1, color: { dark: "#0B2A4A", light: "#ffffff" } },
+ () => onReady?.()
+ );
} else {
onReady?.();
}
}, [onReady, size]);
- return qrCodeData ? (
-
- ) : (
-
+
{city.slogan}
)} {/* hero */} -+
کد نظام پزشکی:{" "}
{data.medical_system_code}
@@ -186,20 +188,20 @@ function Poster({ data, onQrReady }) {
{shownServices.length > 0 && (
+
{address}