Monthly Passive Income Tracker

Income Streams for

Monthly Summary for

Total Gross Passive Income: $0.00

Total Passive Income Expenses: $0.00


Total Net Passive Income: $0.00

Monthly Passive Income Summary

Notes:

  • This tracker reflects self-reported income and expenses for the specified month.
  • "Passive" income often requires upfront effort and may need ongoing management.
  • This tool is for personal tracking and record-keeping; it does not constitute financial advice.
  • For detailed financial analysis or advice, please consult with a qualified financial professional.

No income streams tracked for this month.

`; let tableHtml = `

Income Stream Details

`; incomeStreams.forEach(stream => { tableHtml += ``; }); tableHtml += `
Source Name Category Gross Income ($) Expenses ($) Net Income ($)
${escapeHtml(stream.name)} ${escapeHtml(stream.category)} ${stream.grossIncome.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})} ${stream.expenses.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})} ${stream.netIncome.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})}

`; return tableHtml; } downloadPdfBtn?.addEventListener('click', function () { const { jsPDF } = window.jspdf; const pdfOutputArea = document.getElementById('pitPdfOutputArea'); const pdfStreamsSection = document.getElementById('pitPdfStreamsSection'); const pdfSummaryClone = document.getElementById('pitPdfSummarySectionClone'); if (incomeStreams.length === 0) { alert('Please add at least one income stream to download a summary.'); return; } // Populate PDF-specific sections pdfStreamsSection.innerHTML = generateStreamsTableForPdf(); pdfSummaryClone.innerHTML = document.getElementById('pitSummaryOutput').innerHTML; // Clone current summary document.getElementById('pitPdfTitle').textContent = `Monthly Passive Income Summary for ${streamsHeaderMonthYearEl.textContent}`; html2canvas(pdfOutputArea, { scale: 1.5, useCORS: true, backgroundColor: '#ffffff', windowWidth: pdfOutputArea.scrollWidth }) .then(canvas => { const imgData = canvas.toDataURL('image/jpeg', 0.9); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const margin = 40; let contentWidth = pdfWidth - 2 * margin; const canvasWidth = canvas.width; const canvasHeight = canvas.height; const ratio = canvasWidth / canvasHeight; let imgWidth = contentWidth; let imgHeight = imgWidth / ratio; if (imgHeight > pdfHeight - 2 * margin) { imgHeight = pdfHeight - 2 * margin; imgWidth = imgHeight * ratio; if (imgWidth > contentWidth) { imgWidth = contentWidth; imgHeight = imgWidth / ratio; } } const x = (pdfWidth - imgWidth) / 2; pdf.addImage(imgData, 'JPEG', x, margin, imgWidth, imgHeight, undefined, 'MEDIUM'); pdf.save(`Passive_Income_Summary_${streamsHeaderMonthYearEl.textContent.replace(/\s+/g, '_')}.pdf`); }) .catch(err => { console.error("Error generating PDF:", err); alert("Error generating PDF. See console for details."); }); }); // --- Utility --- function escapeHtml(unsafe) { if (typeof unsafe !== 'string') return unsafe === undefined || unsafe === null ? '' : String(unsafe); return unsafe.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); } // --- Initial Setup --- addStream(); // Start with one empty stream row updateHeaderDates(); // Set initial header dates calculateAndDisplayTotals(); // Initial calculation });
Scroll to Top