Cost-Cutting Challenge Planner

Cost-Cutting Challenge Planner

Challenge Setup

Current Monthly Expenses

Total Monthly Expenses: $0.00

Identify Savings & Plan

For each category, set a target monthly reduction.

Total Projected Monthly Savings: $0.00

Challenge Summary

Congratulations! You are projected to meet or exceed your goal by $${(projectedTotalSavingsOverDuration - goal).toFixed(2)}.

`; } else { goalStatus = `

You are projected to fall short of your goal by $${(goal - projectedTotalSavingsOverDuration).toFixed(2)}.

`; } } else { goalStatus = "

No savings goal set. Focus on maximizing your savings!

"; } const summaryDiv = document.getElementById('cccpChallengeSummaryOutput'); summaryDiv.innerHTML = `

${challengeName}

Challenge Duration: ${duration} month(s)

Overall Savings Goal: $${goal.toFixed(2)}


Total Current Monthly Expenses: $${totalCurrentExpenses.toFixed(2)}

Total Projected Monthly Savings: $${totalProjectedMonthlySavings.toFixed(2)}

Projected Total Savings for Challenge Duration: $${projectedTotalSavingsOverDuration.toFixed(2)}

${goalStatus} `; } function cccp_generatePdf() { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const challengeName = document.getElementById('cccpChallengeName').value || "Cost-Cutting Challenge Plan"; const duration = parseInt(document.getElementById('cccpChallengeDuration').value) || 1; const goal = parseFloat(document.getElementById('cccpSavingsGoal').value) || 0; const totalCurrentExpenses = cccp_expenses.reduce((sum, exp) => sum + exp.amount, 0); const totalProjectedMonthlySavings = cccp_expenses.reduce((sum, exp) => sum + (exp.reduction || 0), 0); const projectedTotalSavingsOverDuration = totalProjectedMonthlySavings * duration; // Colors from CSS variables const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const accentColor = getComputedStyle(document.documentElement).getPropertyValue('--accent-color').trim(); const textColor = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim(); let yPos = 20; // Title doc.setFontSize(22); doc.setTextColor(primaryColor); doc.text(challengeName, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 15; // Challenge Details doc.setFontSize(12); doc.setTextColor(textColor); doc.text(`Challenge Duration: ${duration} month(s)`, 14, yPos); yPos += 7; doc.text(`Overall Savings Goal: $${goal.toFixed(2)}`, 14, yPos); yPos += 12; // Expenses Table if (cccp_expenses.length > 0) { doc.setFontSize(16); doc.setTextColor(primaryColor); doc.text("Current Monthly Expenses", 14, yPos); yPos += 8; const expenseTableData = cccp_expenses.map(exp => [exp.category, `$${exp.amount.toFixed(2)}`]); doc.autoTable({ startY: yPos, head: [['Category', 'Amount']], body: expenseTableData, theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff' }, styles: { font: 'Arial', fontSize: 10 }, didDrawPage: function (data) { yPos = data.cursor.y; } }); yPos = doc.lastAutoTable.finalY + 10; // Update yPos after table doc.setFontSize(11); doc.setTextColor(textColor); doc.text(`Total Current Monthly Expenses: $${totalCurrentExpenses.toFixed(2)}`, 14, yPos); yPos += 10; } else { doc.setFontSize(12); doc.setTextColor(textColor); doc.text("No expenses listed.", 14, yPos); yPos += 10; } // Savings Plan Table const savingsItems = cccp_expenses.filter(exp => (exp.reduction || 0) > 0); if (savingsItems.length > 0) { doc.setFontSize(16); doc.setTextColor(primaryColor); doc.text("Savings Plan", 14, yPos); yPos += 8; const savingsTableData = savingsItems.map(exp => [ exp.category, `$${exp.amount.toFixed(2)}`, `$${(exp.reduction || 0).toFixed(2)}`, `$${(exp.amount - (exp.reduction || 0)).toFixed(2)}` ]); doc.autoTable({ startY: yPos, head: [['Category', 'Current Spending', 'Target Reduction', 'New Spending']], body: savingsTableData, theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff' }, styles: { font: 'Arial', fontSize: 10 }, didDrawPage: function (data) { yPos = data.cursor.y; } }); yPos = doc.lastAutoTable.finalY + 10; } else { yPos += 5; // Add some space if no savings items } // Summary Section doc.setFontSize(16); doc.setTextColor(primaryColor); doc.text("Challenge Projections", 14, yPos); yPos += 8; doc.setFontSize(12); doc.setTextColor(textColor); doc.text(`Total Projected Monthly Savings: $${totalProjectedMonthlySavings.toFixed(2)}`, 14, yPos); yPos += 7; doc.text(`Projected Total Savings for Duration (${duration} months): $${projectedTotalSavingsOverDuration.toFixed(2)}`, 14, yPos); yPos += 10; if (goal > 0) { if (projectedTotalSavingsOverDuration >= goal) { doc.setTextColor(accentColor); // Green for success doc.text(`Goal Status: Projected to MEET or EXCEED your goal by $${(projectedTotalSavingsOverDuration - goal).toFixed(2)}.`, 14, yPos); } else { doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--danger-color').trim()); // Red for shortfall doc.text(`Goal Status: Projected to FALL SHORT of your goal by $${(goal - projectedTotalSavingsOverDuration).toFixed(2)}.`, 14, yPos); } } else { doc.setTextColor(textColor); doc.text("Goal Status: No specific savings goal was set.", 14, yPos); } doc.save((challengeName.replace(/[^a-z0-9]/gi, '_').toLowerCase() || 'cost_cutting_plan') + '.pdf'); } // Initialize document.addEventListener('DOMContentLoaded', () => { tabs = document.querySelectorAll(".cccp-tab-content"); // Re-assign after DOM load tabButtons = document.querySelectorAll(".cccp-tab-button"); cccp_showTab(0); // Show the first tab initially // Add some default expenses for easier testing/demo cccp_addExpense('Groceries', '300'); cccp_addExpense('Subscriptions', '50'); cccp_addExpense('Dining Out', '150'); });
Scroll to Top