Currency Risk Dashboard Currency Risk Dashboard Dashboard Data Configuration Overall Currency Exposure Total Notional Exposure $0.00 Total Potential Gain/Loss $0.00 Number of Open Positions 0 Positions Breakdown Currency Pair Notional ($) Spot Rate Forward Rate Maturity Date Potential P&L ($) Download Dashboard as PDF Manage Currency Positions Currency Pair (e.g., USD/EUR): Notional Amount ($): Current Spot Rate: Target/Forward Rate: Maturity Date: Clear Form Add Position Existing Positions Currency Pair Notional ($) Spot Rate Forward Rate Maturity Date Actions Previous Next Number of Open Positions ${displayOpenPositionsCount.textContent} Positions Breakdown Currency Pair Notional ($) Spot Rate Forward Rate Maturity Date Potential P&L ($) ${positionsHtml} `; // Append to body temporarily to render for html2canvas document.body.appendChild(pdfContentWrapper); try { const canvas = await html2canvas(pdfContentWrapper, { scale: 2, // Increase scale for better resolution useCORS: true, // Required if images are from different origin (though we don't use images here) logging: false // Disable logging for cleaner console }); const imgData = canvas.toDataURL('image/png'); const pdf = new window.jspdf.jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' }); const imgWidth = 210; // A4 width in mm const pageHeight = 297; // A4 height in mm const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 0; pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; while (heightLeft >= 0) { position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } pdf.save('Currency_Risk_Dashboard.pdf'); } catch (error) { console.error('Error generating PDF:', error); // Provide a user-friendly message if PDF generation fails // Using alert as a fallback for critical error, as per instructions. // In a real production environment, a custom modal would be preferred. alert('Failed to generate PDF. Please try again.'); } finally { // Remove the temporary wrapper document.body.removeChild(pdfContentWrapper); } } // --- Event Listeners --- // Tab switching if (dashboardTabBtn) { dashboardTabBtn.addEventListener('click', function() { switchTab('dashboard'); }); } if (dataConfigTabBtn) { dataConfigTabBtn.addEventListener('click', function() { switchTab('dataConfig'); }); } // Navigation buttons if (prevTabBtn) { prevTabBtn.addEventListener('click', function() { if (currentActiveTab === 'dataConfig') { switchTab('dashboard'); } }); } if (nextTabBtn) { nextTabBtn.addEventListener('click', function() { if (currentActiveTab === 'dashboard') { switchTab('dataConfig'); } }); } // Add/Update Position button if (addUpdatePositionBtn) { addUpdatePositionBtn.addEventListener('click', addUpdatePosition); } // Clear Form button if (clearFormBtn) { clearFormBtn.addEventListener('click', clearPositionForm); } // PDF download button if (downloadPdfBtn) { downloadPdfBtn.addEventListener('click', downloadPdf); } // --- Initial Load --- clearPositionForm(); // Initialize form renderDashboard(); // Render dashboard with initial data renderExistingPositionsTable(); // Render existing positions in config tab switchTab('dashboard'); // Ensure dashboard tab is active on load });