From 7fffc089121fdef019f8ba1d1abc98a29645622c Mon Sep 17 00:00:00 2001 From: "Kemas M. Aryadary Rasyad" <112590882+aryadary0706@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:46:34 +0700 Subject: [PATCH] feat: implement certificate download functionality with image and PDF options --- src/Pages/internify/intern/InternCertList.tsx | 6 +- .../intern/components/CertificateAvailabe.tsx | 42 ++++++--- src/Pages/utils/DownloadImagetoDevice.ts | 85 +++++++++++++++++++ 3 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 src/Pages/utils/DownloadImagetoDevice.ts diff --git a/src/Pages/internify/intern/InternCertList.tsx b/src/Pages/internify/intern/InternCertList.tsx index b8cfc9b..46c3b68 100644 --- a/src/Pages/internify/intern/InternCertList.tsx +++ b/src/Pages/internify/intern/InternCertList.tsx @@ -52,16 +52,16 @@ export default function SertificateList() { {projects.map((item: Project) => (
navigate(`/intern/certificates/${item.slug}`, { state: { project: item } })} > {/* Thumbnail */}
-
+
{(() => { const Icon = getDynamicIcon(item.project_icon); - return ; + return ; })()}
diff --git a/src/Pages/internify/intern/components/CertificateAvailabe.tsx b/src/Pages/internify/intern/components/CertificateAvailabe.tsx index cbda7df..2df227f 100644 --- a/src/Pages/internify/intern/components/CertificateAvailabe.tsx +++ b/src/Pages/internify/intern/components/CertificateAvailabe.tsx @@ -1,8 +1,9 @@ // CertificateAvailable.tsx -import { useState } from "react"; +import { useState, useRef } from "react"; import { Download, Link, Printer } from "lucide-react"; import type { ProjectDetail } from "../../../../types/project.types"; import type { Certificate } from "../../../../types/certificate.types"; +import { downloadCertificateAsImage, downloadCertificateAsPdf } from "../../../utils/DownloadImagetoDevice"; interface CertificateAvailableProps { project: ProjectDetail | null; @@ -11,6 +12,9 @@ interface CertificateAvailableProps { export default function CertificateAvailable({ project, certificate }: CertificateAvailableProps) { const [copied, setCopied] = useState(false); + const [downloadingImg, setDownloadingImg] = useState(false); + const [downloadingPdf, setDownloadingPdf] = useState(false); + const certificateRef = useRef(null); const handleCopyLink = () => { navigator.clipboard.writeText(window.location.href); @@ -33,12 +37,24 @@ export default function CertificateAvailable({ project, certificate }: Certifica })() : "-"; - const handleDownload = () => { - const a = document.createElement("a"); - a.href = certificate.image_path; - a.download = `Sertifikat - ${certificate.certificate_no}.png`; - a.target = "_blank"; - a.click(); + const handleDownloadImage = async () => { + setDownloadingImg(true); + await downloadCertificateAsImage( + certificateRef.current, + `Sertifikat - ${certificate.certificate_no}`, + "png", + certificate.image_path + ); + setDownloadingImg(false); + }; + + const handleDownloadPdf = async () => { + setDownloadingPdf(true); + await downloadCertificateAsPdf( + certificateRef.current, + `Sertifikat - ${certificate.certificate_no}` + ); + setDownloadingPdf(false); }; return ( @@ -87,11 +103,12 @@ export default function CertificateAvailable({ project, certificate }: Certifica
{/* Unduh Sertifikat */} {/* Bagikan ke LinkedIn */} @@ -101,9 +118,12 @@ export default function CertificateAvailable({ project, certificate }: Certifica {/* Cetak & Salin Link */}
-