New Projected Annual Spending (on these items): $${newProjectedAnnual.toFixed(2)}
`;
let tableHTML = `
Detailed Cutback Plan:
| Expense | Original Annual ($) | Cutback Plan | New Annual ($) | Annual Saving ($) |
`;
if (dsca_dailyExpenses.length === 0) {
tableHTML += `| No expenses defined. |
`;
} else {
dsca_dailyExpenses.forEach(exp => {
const current = dsca_calculateItemCosts(exp);
const newCalcItem = { costPerOccurrence: exp.newCostPerOccurrence, occurrencesPerDay: exp.newOccurrencesPerDay, daysPerWeek: exp.newDaysPerWeek };
const newCosts = dsca_calculateItemCosts(newCalcItem);
const savedAnnual = current.annual - newCosts.annual;
let cutbackDesc = `Cost: $${exp.costPerOccurrence.toFixed(2)} -> $${exp.newCostPerOccurrence.toFixed(2)}. `;
cutbackDesc += `Freq: ${exp.occurrencesPerDay}x/day, ${exp.daysPerWeek}d/wk -> ${exp.newOccurrencesPerDay}x/day, ${exp.newDaysPerWeek}d/wk.`;
tableHTML += `
| ${exp.name} | ${current.annual.toFixed(2)} |
${cutbackDesc} |
${newCosts.annual.toFixed(2)} | ${savedAnnual.toFixed(2)} |
`;
});
}
tableHTML += '
';
detailsContainer.innerHTML = tableHTML;
}
function dsca_generatePdf() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
let yPos = 20;
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();
doc.setFontSize(20); doc.setTextColor(primaryColor);
doc.text("Daily Spending Cutback Analysis", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' });
yPos += 15;
let totalCurrentAnnual = 0, totalSavedAnnual = 0;
dsca_dailyExpenses.forEach(exp => {
const current = dsca_calculateItemCosts(exp);
const newCalcItem = { costPerOccurrence: exp.newCostPerOccurrence, occurrencesPerDay: exp.newOccurrencesPerDay, daysPerWeek: exp.newDaysPerWeek };
const newCosts = dsca_calculateItemCosts(newCalcItem);
totalCurrentAnnual += current.annual;
totalSavedAnnual += (current.annual - newCosts.annual);
});
const newProjectedAnnual = totalCurrentAnnual - totalSavedAnnual;
doc.setFontSize(14); doc.setTextColor(primaryColor);
doc.text("Overall Savings Summary", 14, yPos); yPos += 8;
doc.setFontSize(11); doc.setTextColor(textColor);
doc.text(`Total Current Annual Spending (on listed items): $${totalCurrentAnnual.toFixed(2)}`, 14, yPos); yPos += 7;
doc.setTextColor(accentColor);
doc.text(`Total Projected Annual Savings: $${totalSavedAnnual.toFixed(2)}`, 14, yPos); yPos += 7;
doc.setTextColor(textColor);
doc.text(`New Projected Annual Spending (on listed items): $${newProjectedAnnual.toFixed(2)}`, 14, yPos); yPos += 10;
if (dsca_dailyExpenses.length > 0) {
if (yPos > 250) { doc.addPage(); yPos = 20; }
doc.setFontSize(14); doc.setTextColor(primaryColor);
doc.text("Detailed Cutback Plan", 14, yPos); yPos += 8;
const tableBody = dsca_dailyExpenses.map(exp => {
const current = dsca_calculateItemCosts(exp);
const newCalcItem = { costPerOccurrence: exp.newCostPerOccurrence, occurrencesPerDay: exp.newOccurrencesPerDay, daysPerWeek: exp.newDaysPerWeek };
const newCosts = dsca_calculateItemCosts(newCalcItem);
const savedAnnual = current.annual - newCosts.annual;
let cutbackDesc = `Cost: $${exp.costPerOccurrence.toFixed(2)} -> $${exp.newCostPerOccurrence.toFixed(2)}. `;
cutbackDesc += `Freq: ${exp.occurrencesPerDay}x/day, ${exp.daysPerWeek}d/wk -> ${exp.newOccurrencesPerDay}x/day, ${exp.newDaysPerWeek}d/wk.`;
return [exp.name, `$${current.annual.toFixed(2)}`, cutbackDesc, `$${newCosts.annual.toFixed(2)}`, `$${savedAnnual.toFixed(2)}`];
});
doc.autoTable({
startY: yPos,
head: [['Expense', 'Original Annual ($)', 'Cutback Plan', 'New Annual ($)', 'Annual Saving ($)']],
body: tableBody, theme: 'grid',
headStyles: { fillColor: primaryColor, textColor: '#ffffff' },
styles: { fontSize: 8, cellPadding: 1.5 },
columnStyles: { 2: { cellWidth: 'wrap', overflow: 'linebreak', minCellWidth: 50 } },
didDrawPage: (data) => { yPos = data.cursor.y; }
});
} else {
doc.setFontSize(11); doc.text("No detailed cutback items defined.", 14, yPos);
}
doc.save('daily_spending_cutback_analysis.pdf');
}
// Initialize
document.addEventListener('DOMContentLoaded', () => {
dsca_showTab(0);
dsca_renderDailyExpensesTable();
dsca_updateTotalCurrentSpendingDisplay();
// Demo data
dsca_dailyExpenses.push({id: 'exp_001', name: 'Takeout Coffee', costPerOccurrence: 4.00, occurrencesPerDay: 1, daysPerWeek: 5, newCostPerOccurrence: 4.00, newOccurrencesPerDay: 1, newDaysPerWeek: 2});
dsca_dailyExpenses.push({id: 'exp_002', name: 'Lunch at Work', costPerOccurrence: 12.00, occurrencesPerDay: 1, daysPerWeek: 3, newCostPerOccurrence: 8.00, newOccurrencesPerDay: 1, newDaysPerWeek: 1});
dsca_renderDailyExpensesTable();
dsca_updateTotalCurrentSpendingDisplay();
});