NFT Investment Performance Tracker

NFT Investment Performance Tracker

Manually track your NFT investments and their performance.

Add New NFT

Generated: ${new Date().toLocaleString()}

My NFT Portfolio

${tableRowsHtml}
Name/ID Collection Purchase Price Purchase Date Current Value P/L ($) Return (%) Marketplace Actions

Portfolio Summary

Total Investment: ${formatCurrency(totalInvestment)}
Total Current Portfolio Value: ${formatCurrency(totalCurrentValue)}
Total Profit/Loss: ${formatCurrency(totalProfitLoss)}
Overall Portfolio Return: ${overallReturnPercentage.toFixed(2)}%

Note: All values are based on user input. "Current Est. Value" is subjective and should be updated regularly for accuracy.

`; } async function generatePerformancePdf() { const pdfContent = document.getElementById('pdf-content'); const downloadBtn = event.target; if (!pdfContent) { console.error("PDF content area not found."); if(typeof alert === 'function') alert("Error: Could not find content to generate PDF."); return; } if (!html2canvas || !jsPDF) { console.error("html2canvas or jsPDF library not found."); if(typeof alert === 'function') alert("Error: PDF generation library not loaded."); return; } const originalButtonText = downloadBtn.textContent; downloadBtn.textContent = "Generating..."; downloadBtn.disabled = true; const pdfHeaderElement = pdfContent.querySelector('.pdf-header'); const screenHeaderElements = pdfContent.querySelectorAll('.screen-only'); if (pdfHeaderElement) pdfHeaderElement.style.display = 'block'; // Show for PDF capture screenHeaderElements.forEach(el => el.style.display = 'none'); try { const canvas = await html2canvas(pdfContent, { scale: 1.5, useCORS: true, logging: false, onclone: (doc) => { // Ensure elements are styled correctly in the cloned document for PDF const clonedHeader = doc.querySelector('.pdf-header'); if (clonedHeader) clonedHeader.style.display = 'block'; doc.querySelectorAll('.screen-only').forEach(el => el.style.display = 'none'); // Remove action buttons column from table in clone const actionsHeader = doc.querySelector('.portfolio-table th:last-child.no-print'); const actionsCells = doc.querySelectorAll('.portfolio-table td:last-child .btn-danger'); if(actionsHeader) actionsHeader.style.display = 'none'; actionsCells.forEach(cell => { if(cell.parentElement) cell.parentElement.style.display = 'none'; }); } }); // Restore display for on-screen view if (pdfHeaderElement) pdfHeaderElement.style.display = 'none'; screenHeaderElements.forEach(el => el.style.display = 'block'); const imgData = canvas.toDataURL('image/jpeg', 0.8); const pdf = new jsPDF({ orientation: 'l', // Landscape for wider table unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); const margin = 10; const contentWidth = pdfWidth - 2 * margin; let contentHeight = (imgProps.height * contentWidth) / imgProps.width; let currentPosition = margin; if (contentHeight <= pdfHeight - 2 * margin) { pdf.addImage(imgData, 'JPEG', margin, currentPosition, contentWidth, contentHeight); } else { let remainingImgHeight = imgProps.height; let sourceY = 0; const sourceWidth = imgProps.width; const pageCanvasHeight = ((pdfHeight - 2 * margin) / contentWidth) * sourceWidth; while (remainingImgHeight > 0) { const currentChunkHeight = Math.min(remainingImgHeight, pageCanvasHeight); const tempCanvas = document.createElement('canvas'); tempCanvas.width = sourceWidth; tempCanvas.height = currentChunkHeight; const tempCtx = tempCanvas.getContext('2d'); tempCtx.drawImage(canvas, 0, sourceY, sourceWidth, currentChunkHeight, 0, 0, sourceWidth, currentChunkHeight); const chunkImgData = tempCanvas.toDataURL('image/jpeg', 0.8); const chunkDisplayHeight = (currentChunkHeight * contentWidth) / sourceWidth; pdf.addImage(chunkImgData, 'JPEG', margin, currentPosition, contentWidth, chunkDisplayHeight); remainingImgHeight -= currentChunkHeight; sourceY += currentChunkHeight; if (remainingImgHeight > 0) { pdf.addPage(); currentPosition = margin; } } } pdf.save(`NFT_Portfolio_Performance.pdf`); } catch (error) { console.error("Error generating PDF:", error); if(typeof alert === 'function') alert("An error occurred while generating the PDF: " + error.message); } finally { downloadBtn.textContent = originalButtonText; downloadBtn.disabled = false; if (pdfHeaderElement) pdfHeaderElement.style.display = 'none'; screenHeaderElements.forEach(el => el.style.display = 'block'); } } // Initial render in case there's saved data later or for empty state document.addEventListener('DOMContentLoaded', renderPortfolio);
Scroll to Top