Charity Donation Planner

Charity Donation Planner

Donation Summary

Total Goal

$0.00

Total Donated

$0.00

Remaining

$0.00

Editable Donation Plan

Charity Name
Goal
Donated

Go to the "Data Configuration" tab to add charities and generate your plan.

1. Add Charity to Plan

$

Current Charities

2. Log a Donation

$

No charities added. Go to the Configuration tab to add some.

"; } else { charities.forEach(createDashboardItem); } recalculateTotals(); showTab("cdp-tab-dashboard"); } /** * Creates an editable item row on the dashboard */ function createDashboardItem(charity) { const itemEl = document.createElement("div"); itemEl.className = "cdp-dash-item"; itemEl.dataset.id = charity.id; itemEl.innerHTML = `
$
$
`; dashboardList.appendChild(itemEl); } /** * Handles clicks on dashboard list (for remove) */ function handleDashboardClick(e) { if (e.target.dataset.action === "remove") { const itemEl = e.target.closest(".cdp-dash-item"); if (itemEl) { // Remove from dashboard itemEl.remove(); // Remove from master array charities = charities.filter(c => c.id !== itemEl.dataset.id); // Update config tab lists updateConfigLists(); // Update dashboard totals recalculateTotals(); } } } /** * Calculates and displays totals from the *dashboard's editable fields* */ function recalculateTotals() { let totalGoal = 0; let totalDonated = 0; const goalInputs = dashboardList.querySelectorAll(".cdp-dash-goal"); goalInputs.forEach((input) => { totalGoal += parseFloat(input.value) || 0; }); const donatedInputs = dashboardList.querySelectorAll(".cdp-dash-donated"); donatedInputs.forEach((input) => { totalDonated += parseFloat(input.value) || 0; }); const totalRemaining = totalGoal - totalDonated; totalGoalEl.textContent = `$${totalGoal.toFixed(2)}`; totalDonatedEl.textContent = `$${totalDonated.toFixed(2)}`; totalRemainingEl.textContent = `$${totalRemaining.toFixed(2)}`; return { totalGoal, totalDonated, totalRemaining }; } /** * Generates a PDF report from the dashboard data */ function downloadPDF() { if ( typeof window.jspdf === "undefined" || typeof window.jspdf.jsPDF.autoTable === "undefined" ) { alert("Error: PDF library could not be loaded. Please try again."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF("p", "pt", "a4"); const margin = 40; const tableHead = [["Charity", "Goal", "Donated", "Remaining"]]; const tableBody = []; // Get data *from the dashboard* const dashItems = dashboardList.querySelectorAll(".cdp-dash-item"); dashItems.forEach((item) => { const name = item.querySelector(".cdp-dash-name").value; const goal = parseFloat(item.querySelector(".cdp-dash-goal").value) || 0; const donated = parseFloat(item.querySelector(".cdp-dash-donated").value) || 0; const remaining = goal - donated; tableBody.push([ name, `$${goal.toFixed(2)}`, `$${donated.toFixed(2)}`, `$${remaining.toFixed(2)}` ]); }); const totals = recalculateTotals(); // Get fresh totals doc.setFontSize(18); doc.text("Charity Donation Plan", margin, margin); doc.autoTable({ startY: margin + 20, head: tableHead, body: tableBody, theme: "striped", headStyles: { fillColor: [0, 115, 230], textColor: [255, 255, 255], }, columnStyles: { 1: { halign: 'right' }, 2: { halign: 'right' }, 3: { halign: 'right' }, }, // Add footer row for totals didDrawPage: function (data) { let finalY = data.table.finalY + 20; doc.setFontSize(12); doc.setFont(undefined, "bold"); doc.text("Total Goal:", margin, finalY); doc.text(`$${totals.totalGoal.toFixed(2)}`, data.settings.margin.left + 150, finalY); doc.text("Total Donated:", margin, finalY + 20); doc.text(`$${totals.totalDonated.toFixed(2)}`, data.settings.margin.left + 150, finalY + 20); doc.text("Total Remaining:", margin, finalY + 40); doc.text(`$${totals.totalRemaining.toFixed(2)}`, data.settings.margin.left + 150, finalY + 40); }, }); doc.save("Charity_Donation_Plan.pdf"); } /** * Helper to escape HTML */ function escapeHTML(str) { if (!str) return ""; return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // --- 3. INITIALIZATION & EVENT LISTENERS --- // Tab Listeners tabButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); navButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); // Config Tab Listeners if (addCharityForm) { addCharityForm.addEventListener("submit", handleAddCharity); } if (logDonationForm) { logDonationForm.addEventListener("submit", handleLogDonation); } if (configCharityList) { configCharityList.addEventListener("click", handleConfigListClick); } if (generateBtn) { generateBtn.addEventListener("click", handleGenerateDashboard); } // Dashboard Tab Listeners if (recalculateBtn) { recalculateBtn.addEventListener("click", recalculateTotals); } if (pdfBtn) { pdfBtn.addEventListener("click", downloadPDF); } if (dashboardList) { dashboardList.addEventListener("click", handleDashboardClick); } // Initial State logDate.valueAsDate = new Date(); // Set date to today // Load sample data charities = [ { id: 'charity-1', name: 'St. Jude Children\'s Research Hospital', category: 'Health', goal: 500, donated: 50 }, { id: 'charity-2', name: 'ASPCA', category: 'Animals', goal: 250, donated: 0 } ]; updateConfigLists(); handleGenerateDashboard(); showTab("cdp-tab-dashboard"); });