на ios, при клике на Save qr, выдает ошибку: "the operation is insecure ", но если нажать на андроиде, то pdf-файл скачается
"use client";
import { UserInfoBlock } from "@/src/entites/UserInfoBlock";
import api from "@/src/shared/api/api";
import { defaultToastStyles } from "@/src/shared/model/defaultStyles/defaultStyles";
import { copyTextToClipboard } from "@/src/shared/model/functions/copyToClipboard";
import { useUserStore } from "@/src/shared/store/store";
import { Button, IButtonSize } from "@/src/shared/ui/Button/Button";
import { useQuery } from "@tanstack/react-query";
import html2canvas from "html2canvas";
import { jsPDF } from "jspdf";
import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import { QrImageSave } from "../QrImageSave/QrImageSave";
import styles from "./Qr.module.scss";
export const Qr = () => {
const printRef = useRef(null);
const [qrSrc, setQrSrc] = useState<string | null>(null);
const userId = useUserStore((state) => state.data.id);
const userName = useUserStore((state) => state.data.name);
const userAvatar = useUserStore((state) => state.data.avatar);
const userGoal = useUserStore((state) => state.data.goal);
const qrLink = `https://saluttipe.site/qr_code/user/${userId}`;
const { data } = useQuery({
queryKey: ["qr"],
queryFn: async () => {
const response = await api.get("profile/me/qr-code/", {
responseType: "blob",
});
return response.data;
},
});
useEffect(() => {
if (data) {
const qrUrl = URL.createObjectURL(data);
setQrSrc(qrUrl);
return () => URL.revokeObjectURL(qrUrl);
}
}, [data]);
const handleDownloadPdf = async () => {
try {
const element = printRef.current;
if (!element) {
return null;
}
const canvas = await html2canvas(element);
const data = canvas.toDataURL("image/png");
const pdf = new jsPDF({
orientation: "portrait",
unit: "px",
format: "a4",
});
const imgProperties = pdf.getImageProperties(data)
const pdfWidth = pdf.internal.pageSize.getWidth()
const pdfHeight = (imgProperties.height * pdfWidth) / imgProperties.width;
pdf.addImage(data, "PNG", 0, 0, pdfWidth, pdfHeight);
pdf.save("examplepdf.pdf");
} catch {
toast.error("Something went wrong", {
style: defaultToastStyles,
});
}
};
if (!qrSrc) return <></>;
return (
<UserInfoBlock
blockName="Your QR code"
className={styles.userInfoBlockStyles}
>
<div className={styles.qrBox}>
<Image src={qrSrc} alt="QR Code" width={238} height={238} />
</div>
<div style={{ position: "absolute", top: "-9999px" }} ref={printRef}>
<QrImageSave
qrSrc={qrSrc}
userName={userName}
userAvatar={userAvatar}
userGoal={userGoal}
/>
</div>
<div className={styles.qrActions}>
<Button
size={IButtonSize.ROUND}
className={styles.qrActionButton}
onClick={handleDownloadPdf}
>
Save QR
</Button>
<Button
size={IButtonSize.ROUND}
className={styles.qrActionButton}
onClick={() => copyTextToClipboard(qrLink)}
>
Save link
</Button>
</div>
</UserInfoBlock>
);
};
import qrTipLogo from "@/public/qrTipLogo.png";
import Image from "next/image";
import { RefObject } from "react";
import styles from "./QrImageSave.module.scss";
interface QrImageProps {
qrSrc: string;
userName: string;
refElement?: RefObject<HTMLDivElement>;
userAvatar: string;
userGoal: string;
}
export const QrImageSave = ({
qrSrc,
userName,
refElement,
userAvatar,
userGoal,
}: QrImageProps) => {
return (
<div ref={refElement} className={styles.qrDownloadContainer}>
<div className={styles.userInfo}>
<Image
src={userAvatar}
alt="QR Code"
width={258}
height={258}
className={styles.userAvatar}
/>
<div className={styles.userInfoMain}>
<p className={styles.userName}>{userName}</p>
<p className={styles.goalText}>
I'm saving up for <span className={styles.goal}>{userGoal}</span>
</p>
</div>
</div>
<div className={styles.qrCode}>
<p className={styles.mainText}>
Scan this QR code to leave a{" "}
<span className={styles.tipText}>tip</span>
</p>
<div className={styles.qrBox}>
<Image src={qrSrc} alt="QR Code" width={238} height={238} />
</div>
</div>
<p className={styles.footerText}>
Thank you, we look forward to seeing you again
</p>
<Image
src={qrTipLogo}
alt="tipLogo"
width={150}
height={105}
className={styles.qrTipLogo}
/>
</div>
);
};