Investment Diversification Budgeting Tool

Total Investment Budget

Define Asset Classes & Target Allocations

Total Allocated: 0%

Your Asset Allocation Plan

No asset classes added yet.

Define your total budget and add asset allocations on the first tab. Ensure total allocation is 100% to see the summary.

Define your total budget and add asset allocations on the first tab.

"; placeholder.style.display = 'block'; warningMsg.style.display = 'none'; contentDiv.style.display = 'none'; pdfBtn.style.display = 'none'; return; } if (totalPercent !== 100) { placeholder.style.display = 'none'; warningMsg.style.display = 'block'; contentDiv.style.display = 'none'; pdfBtn.style.display = 'none'; return; } placeholder.style.display = 'none'; warningMsg.style.display = 'none'; contentDiv.style.display = 'block'; pdfBtn.style.display = 'inline-block'; summaryTotalBudgetEl.textContent = formatC(appData.totalBudget); summaryTableBody.innerHTML = ''; const pieChartData = { labels: [], data: [], colors: [] }; const barChartData = { labels: [], data: [], colors: [] }; let totalAllocatedAmountCheck = 0; appData.assetAllocations.forEach((asset, index) => { const allocatedAmount = (appData.totalBudget * asset.targetPercentage) / 100; totalAllocatedAmountCheck += allocatedAmount; const row = summaryTableBody.insertRow(); row.insertCell().textContent = asset.name; const percCell = row.insertCell(); percCell.textContent = `${asset.targetPercentage.toFixed(2)}%`; percCell.classList.add('percentage-cell'); const amountCell = row.insertCell(); amountCell.textContent = formatC(allocatedAmount); amountCell.classList.add('amount-cell'); row.insertCell().textContent = asset.notes || '-'; pieChartData.labels.push(asset.name); pieChartData.data.push(asset.targetPercentage); pieChartData.colors.push(chartColors[index % chartColors.length]); barChartData.labels.push(asset.name); barChartData.data.push(allocatedAmount); barChartData.colors.push(chartColors[index % chartColors.length]); }); // console.log("Total allocated check:", totalAllocatedAmountCheck); // For debugging renderPieChart(pieChartData); renderBarChart(barChartData); } function renderPieChart(chartData) { const canvas = document.getElementById('idt-allocation-pie-chart'); if(!canvas) { console.error("Pie chart canvas missing"); return;} const ctx = canvas.getContext('2d'); if (allocationPieChart) allocationPieChart.destroy(); if (chartData.labels.length === 0) { ctx.clearRect(0,0,canvas.width, canvas.height); ctx.font = "14px Arial"; ctx.textAlign="center"; ctx.fillText("No allocation data for chart.", canvas.width/2, canvas.height/2); return; } allocationPieChart = new Chart(ctx, { type: 'pie', data: { labels: chartData.labels, datasets: [{ label: 'Target Allocation %', data: chartData.data, backgroundColor: chartData.colors, borderColor: '#fff', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom' }, tooltip: { callbacks: { label: c => `${c.label}: ${c.raw.toFixed(2)}%` } } } } }); } function renderBarChart(chartData) { const canvas = document.getElementById('idt-allocation-bar-chart'); if(!canvas) { console.error("Bar chart canvas missing"); return;} const ctx = canvas.getContext('2d'); if (allocationBarChart) allocationBarChart.destroy(); if (chartData.labels.length === 0) { ctx.clearRect(0,0,canvas.width, canvas.height); ctx.font = "14px Arial"; ctx.textAlign="center"; ctx.fillText("No allocation data for chart.", canvas.width/2, canvas.height/2); return; } allocationBarChart = new Chart(ctx, { type: 'bar', data: { labels: chartData.labels, datasets: [{ label: `Allocated Amount (${currencySymbol})`, data: chartData.data, backgroundColor: chartData.colors }] }, options: { responsive: true, maintainAspectRatio: false, indexAxis: 'y', scales: { x: { beginAtZero: true, ticks: { callback: v => formatC(v) } } }, plugins: { legend: { display: false }, tooltip: { callbacks: { label: c => `${c.dataset.label}: ${formatC(c.raw)}` } } } } }); } const pdfBtnElm = document.getElementById('idt-download-pdf-btn'); if(pdfBtnElm) { pdfBtnElm.addEventListener('click', async () => { if (appData.assetAllocations.length === 0 || appData.totalBudget <= 0 || updateTotalAllocationSummary() !== 100) { alert("Please set a budget and ensure asset allocations sum to 100% before downloading PDF."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); let y = 15; const m = 14; const pw = doc.internal.pageSize.getWidth(); const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const textColor = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim(); doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text("Investment Diversification Plan", pw / 2, y, { align: 'center' }); y += 8; doc.setFontSize(10); doc.setTextColor(textColor); doc.text(`Report Date: ${new Date().toLocaleDateString()} | Currency: ${currencySymbol}`, pw / 2, y, { align: 'center' }); y += 10; doc.text(`Total Investment Budget: ${formatC(appData.totalBudget)}`, m, y); y += 10; function addPdfSection(title) { if (y > 260 && doc.getNumberOfPages() > 0) { doc.addPage(); y = 20;} else if (y > 260) {y=20;} doc.setFontSize(14); doc.setTextColor(primaryColor); doc.text(title, m, y); y += 7; doc.setFontSize(10); doc.setTextColor(textColor); } addPdfSection("Asset Allocation Plan"); const head = [['Asset Class', 'Target Allocation (%)', 'Allocated Amount', 'Notes']]; const body = appData.assetAllocations.map(asset => { const allocatedAmount = (appData.totalBudget * asset.targetPercentage) / 100; return [asset.name, `${asset.targetPercentage.toFixed(2)}%`, formatC(allocatedAmount), asset.notes || '-']; }); doc.autoTable({ startY: y, head: head, body: body, theme: 'grid', headStyles:{fillColor: primaryColor, textColor:'#fff'}, styles:{fontSize:9, cellPadding:1.5}, didDrawPage: data => y = data.cursor.y }); y = doc.lastAutoTable.finalY + 10; const pieChartCanvas = document.getElementById('idt-allocation-pie-chart'); const barChartCanvas = document.getElementById('idt-allocation-bar-chart'); let chartStartY = y; if (allocationPieChart && pieChartCanvas && appData.assetAllocations.length > 0) { if (chartStartY > 180 && doc.getNumberOfPages() > 0) { doc.addPage(); chartStartY = 20; } else if (chartStartY > 180) {chartStartY=20;} doc.setFontSize(12); doc.text("Allocation Percentage Chart:", m, chartStartY); chartStartY += 5; try { const imgData = await html2canvas(pieChartCanvas, {backgroundColor: '#FFFFFF', scale:1.5}); doc.addImage(imgData.toDataURL('image/png'), 'PNG', m, chartStartY, 80, 80); // Adjust size } catch(e) { console.error("Error adding pie chart to PDF", e); } } if (allocationBarChart && barChartCanvas && appData.assetAllocations.length > 0) { const xPosChart2 = (allocationPieChart && pieChartCanvas && appData.assetAllocations.length > 0) ? m + 90 : m; let yPosChart2 = (allocationPieChart && pieChartCanvas && appData.assetAllocations.length > 0) ? chartStartY -5 : chartStartY; if ((!allocationPieChart && yPosChart2 > 180) || (allocationPieChart && yPosChart2 < 20 && xPosChart2 === m)){ if (doc.getNumberOfPages() > 0 && yPosChart2 > 180) doc.addPage(); yPosChart2 = 20; } else if (yPosChart2 < 20) {yPosChart2 = 20;} doc.setFontSize(12); doc.text("Monetary Allocation Chart:", xPosChart2, yPosChart2); yPosChart2 += 5; try { const imgData2 = await html2canvas(barChartCanvas, {backgroundColor: '#FFFFFF', scale:1.5}); doc.addImage(imgData2.toDataURL('image/png'), 'PNG', xPosChart2, yPosChart2, 90, 70); // Adjust size } catch(e) { console.error("Error adding bar chart to PDF", e); } } doc.save('Investment_Diversification_Plan.pdf'); }); } else { console.warn("PDF Download button not found."); } loadData(); updateTabDisplay(); } catch (e) { console.error("CRITICAL ERROR initializing Investment Diversification Tool:", e); const mainDiv = document.getElementById('investmentDiversificationTool'); if (mainDiv) { mainDiv.innerHTML = "

A critical error occurred. Please check browser console (F12).

"; } } });
Scroll to Top