`;
}
};
// C.1 & C.2: Event Handling
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const targetTab = parseInt(tab.dataset.tab, 10);
if (targetTab <= currentTab || (targetTab === currentTab + 1 && (currentTab === 1 ? calculatorState.dailyGoal > 0 : true))) {
currentTab = targetTab;
if (currentTab === 3) runCalculations();
updateTabVisibility();
} else {
alert('Please complete the current step before proceeding.');
}
});
});
prevBtn.addEventListener('click', () => handleNavigation(-1));
nextBtn.addEventListener('click', () => handleNavigation(1));
dailyCaloriesInput.addEventListener('input', (e) => {
const value = parseInt(e.target.value, 10) || 0;
calculatorState.dailyGoal = value;
if (value > 0) {
weeklyGoalDisplay.classList.remove('hidden');
weeklyGoalValue.textContent = (value * 7).toLocaleString();
} else {
weeklyGoalDisplay.classList.add('hidden');
}
});
cheatMealCaloriesInput.addEventListener('input', (e) => {
calculatorState.cheatMeal = parseInt(e.target.value, 10) || 0;
});
// ** NEW PDF Download Functionality - "Medical Report" Style **
downloadPdfBtn.addEventListener('click', () => {
const { jsPDF } = window.jspdf;
const pdf = new jsPDF('p', 'mm', 'a4');
const pageW = pdf.internal.pageSize.getWidth();
const pageH = pdf.internal.pageSize.getHeight();
const margin = 15;
let y = 0;
// --- PDF Styling ---
const primaryColor = '#0d47a1'; // A deep blue
const secondaryColor = '#42a5f5'; // A lighter blue
const textColor = '#333333';
const lightTextColor = '#666666';
const borderColor = '#e0e0e0';
// --- Header ---
pdf.setFillColor(primaryColor);
pdf.rect(0, 0, pageW, 30, 'F');
pdf.setFontSize(22);
pdf.setFont('helvetica', 'bold');
pdf.setTextColor('#FFFFFF');
pdf.text('Calorie Balance Report', pageW / 2, 18, { align: 'center' });
y = 40;
// --- Input Data Section ---
pdf.setFontSize(14);
pdf.setFont('helvetica', 'bold');
pdf.setTextColor(textColor);
pdf.text('Baseline Information', margin, y);
y += 8;
pdf.setFontSize(11);
pdf.setFont('helvetica', 'normal');
pdf.text(`Daily Calorie Goal:`, margin, y);
pdf.text(`${calculatorState.dailyGoal.toLocaleString()} kcal`, pageW - margin, y, { align: 'right' });
y += 7;
pdf.text(`Cheat Meal Intake:`, margin, y);
pdf.text(`${calculatorState.cheatMeal.toLocaleString()} kcal`, pageW - margin, y, { align: 'right' });
y += 10;
pdf.setDrawColor(borderColor);
pdf.line(margin, y, pageW - margin, y);
y += 12;
// --- Analysis Section ---
pdf.setFontSize(14);
pdf.setFont('helvetica', 'bold');
pdf.text('Caloric Impact Analysis', margin, y);
y += 10;
const boxWidth = (pageW - margin * 4) / 3;
pdf.setFillColor('#f5f5f5');
pdf.roundedRect(margin, y, boxWidth, 25, 3, 3, 'F');
pdf.roundedRect(margin * 2 + boxWidth, y, boxWidth, 25, 3, 3, 'F');
pdf.roundedRect(margin * 3 + boxWidth * 2, y, boxWidth, 25, 3, 3, 'F');
pdf.setFontSize(10);
pdf.setTextColor(lightTextColor);
pdf.text('Weekly Goal', margin + boxWidth/2, y + 7, {align: 'center'});
pdf.text('Cheat Meal Surplus', margin * 2 + boxWidth * 1.5, y + 7, {align: 'center'});
pdf.text('Adjusted Weekly Total', margin * 3 + boxWidth * 2.5, y + 7, {align: 'center'});
pdf.setFontSize(16);
pdf.setFont('helvetica', 'bold');
pdf.setTextColor(textColor);
pdf.text(`${calculatorState.weeklyGoal.toLocaleString()}`, margin + boxWidth/2, y + 18, {align: 'center'});
pdf.setTextColor('#d32f2f'); // Red for surplus
pdf.text(`+${calculatorState.surplus.toLocaleString()}`, margin * 2 + boxWidth * 1.5, y + 18, {align: 'center'});
pdf.setTextColor('#388e3c'); // Green for new total
pdf.text(`${calculatorState.newTotal.toLocaleString()}`, margin * 3 + boxWidth * 2.5, y + 18, {align: 'center'});
y += 40;
// --- Recommendations Section ---
pdf.setFontSize(14);
pdf.setFont('helvetica', 'bold');
pdf.setTextColor(textColor);
pdf.text('Balance & Compensation Plan', margin, y);
y += 5;
if (calculatorState.surplus > 0) {
const reductionPerDay = Math.round(calculatorState.surplus / 6);
// --- Dietary Adjustment ---
pdf.setFontSize(12);
pdf.setFont('helvetica', 'bold');
pdf.setTextColor(secondaryColor);
pdf.text('1. Dietary Adjustment', margin, y+=5);
pdf.setFontSize(10);
pdf.setFont('helvetica', 'normal');
pdf.setTextColor(textColor);
pdf.text(`To balance the surplus over 6 days, reduce daily intake by ${reductionPerDay.toLocaleString()} kcal.`, margin, y+=6);
pdf.text(`Your new temporary daily target would be ${(calculatorState.dailyGoal - reductionPerDay).toLocaleString()} kcal.`, margin, y+=6);
y += 10;
// --- Exercise Plan ---
pdf.setFontSize(12);
pdf.setFont('helvetica', 'bold');
pdf.setTextColor(secondaryColor);
pdf.text('2. Activity Compensation', margin, y);
y+=6;
pdf.setFontSize(10);
pdf.text(`Alternatively, burn the ${calculatorState.surplus.toLocaleString()} kcal surplus with one of the following activities:`, margin, y);
y+=8;
// Table Header
pdf.setFillColor('#eeeeee');
pdf.rect(margin, y, pageW - (margin * 2), 8, 'F');
pdf.setFontSize(10);
pdf.setFont('helvetica', 'bold');
pdf.text('Activity', margin + 5, y + 6);
pdf.text('Estimated Duration', pageW - margin - 5, y + 6, { align: 'right' });
y += 8;
// Table Rows
pdf.setFont('helvetica', 'normal');
exercises.forEach((ex, index) => {
const timeInMinutes = Math.round((calculatorState.surplus / ex.kcalPerHour) * 60);
if (index % 2 !== 0) { // alternate row color
pdf.setFillColor('#f9f9f9');
pdf.rect(margin, y, pageW - (margin * 2), 8, 'F');
}
pdf.text(`${ex.icon} ${ex.name}`, margin + 5, y + 6);
pdf.text(`${timeInMinutes} minutes`, pageW - margin - 5, y + 6, { align: 'right' });
y += 8;
});
} else {
// No surplus message
pdf.setFontSize(12);
pdf.setFont('helvetica', 'normal');
pdf.setTextColor('#388e3c');
pdf.text('Congratulations! Your cheat meal did not result in a calorie surplus.', margin, y+=5);
pdf.text('No compensation plan is needed. Keep up the great work!', margin, y+=7);
}
// --- Footer ---
const finalY = pageH - 15;
pdf.setDrawColor(borderColor);
pdf.line(margin, finalY, pageW - margin, finalY);
pdf.setFontSize(8);
pdf.setTextColor(lightTextColor);
pdf.text('This report is for informational purposes only and not a substitute for professional medical advice.', pageW / 2, finalY + 5, { align: 'center' });
pdf.text(`Generated on ${new Date().toLocaleDateString()}`, pageW - margin, finalY + 10, { align: 'right' });
pdf.text('Cheat Meal Calorie Balance Calculator', margin, finalY + 10);
// --- Save PDF ---
pdf.save('Calorie-Balance-Report.pdf');
});
// Initial setup
updateTabVisibility();
});
