diff --git a/frontend/components/Campaigns.tsx b/frontend/components/Campaigns.tsx index c018733..c6c4c55 100755 --- a/frontend/components/Campaigns.tsx +++ b/frontend/components/Campaigns.tsx @@ -1055,6 +1055,7 @@ const ProofDetailView: React.FC<{ }; const [selectedVersionIndex, setSelectedVersionIndex] = useState(getInitialVersionIndex); + const [isExporting, setIsExporting] = useState(false); const fileInputRef = useRef(null); const handleUploadClick = () => { @@ -1132,6 +1133,69 @@ const ProofDetailView: React.FC<{ } }; + const handleDownloadReport = async () => { + setIsExporting(true); + + const reportRootEl = document.createElement('div'); + reportRootEl.style.position = 'absolute'; + reportRootEl.style.left = '-9999px'; + reportRootEl.style.top = '0px'; + reportRootEl.style.zIndex = '-1'; + document.body.appendChild(reportRootEl); + + const reactRoot = ReactDOM.createRoot(reportRootEl); + + try { + const proofForReport = { + ...proof, + versions: [selectedVersion], + }; + + reactRoot.render(); + + await new Promise(resolve => setTimeout(resolve, 1000)); + + const { default: jspdf } = await import('jspdf'); + const { default: html2canvas } = await import('html2canvas'); + + const reportContent = reportRootEl.children[0] as HTMLElement; + if (!reportContent) throw new Error("PDF report element not found"); + + const canvas = await html2canvas(reportContent, { scale: 2, useCORS: true }); + + const imgData = canvas.toDataURL('image/png'); + const pdf = new jspdf('p', 'mm', 'a4', true); + const pdfWidth = pdf.internal.pageSize.getWidth(); + const pdfHeight = pdf.internal.pageSize.getHeight(); + const ratio = canvas.width / pdfWidth; + const pagedCanvasHeight = canvas.height / ratio; + + let heightLeft = pagedCanvasHeight; + let position = 0; + + pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, pagedCanvasHeight, undefined, 'FAST'); + heightLeft -= pdfHeight; + + while (heightLeft > 0) { + position -= pdfHeight; + pdf.addPage(); + pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, pagedCanvasHeight, undefined, 'FAST'); + heightLeft -= pdfHeight; + } + + const fileName = `${campaignName} - ${proof.proofName} V${selectedVersion.version} Report`; + pdf.save(`${fileName.replace(/[^a-zA-Z0-9]/g, '_')}.pdf`); + + } catch (error) { + console.error("Failed to generate PDF:", error); + alert("Sorry, there was an error creating the PDF. Please try again."); + } finally { + reactRoot.unmount(); + document.body.removeChild(reportRootEl); + setIsExporting(false); + } + }; + if (!selectedVersion) { return (
@@ -1196,7 +1260,25 @@ const ProofDetailView: React.FC<{ title={`Download Version ${selectedVersion.version}`} > - Download + Download Asset + +