';
downloadPdfBtn.style.display = 'block'; // Show PDF button
// Store data for PDF generation
resultsAreaDiv.dataset.inputs = JSON.stringify({
payType: payType,
hourlyRate: hourlyRate,
annualSalary: annualSalary,
standardHoursPerDay: standardHoursPerDay,
leaveDurationType: leaveDurationType,
leaveDurationValue: leaveDurationValue,
sickPayRatePercent: sickPayRatePercent,
sickLeaveBalanceAvailableHours: sickLeaveBalanceAvailableHoursInput, // Store raw input or NaN
accrualRateInfo: accrualRateInfo
});
resultsAreaDiv.dataset.calculations = JSON.stringify({
effectiveRegularHourlyRate: effectiveRegularHourlyRate,
totalSickLeaveHours: totalSickLeaveHours,
sickLeaveHourlyPayRate: sickLeaveHourlyPayRate,
totalSickLeavePay: totalSickLeavePay,
remainingSickLeaveBalanceHours: remainingSickLeaveBalanceHours // Store raw value or null
});
}
// Event listener for calculate button
calculateBtn.addEventListener('click', calculateAndDisplay);
// Trigger calculation when switching TO the results tab
document.getElementById('results').addEventListener('transitionend', function() {
if (this.classList.contains('active')) {
calculateAndDisplay();
}
});
// Initial state setup for pay type
if (payTypeHourlyRadio.checked) {
hourlyPayInputDiv.style.display = 'block';
salaryPayInputDiv.style.display = 'none';
} else {
hourlyPayInputDiv.style.display = 'none';
salaryPayInputDiv.style.display = 'block';
}
// Initial state setup for leave duration type
if (leaveDurationHoursRadio.checked) {
leaveDurationValueLabel.textContent = 'Sick Leave Duration Value (Hours):';
} else {
leaveDurationValueLabel.textContent = 'Sick Leave Duration Value (Days):';
}
// --- PDF Generation ---
downloadPdfBtn.addEventListener('click', function() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const inputs = JSON.parse(resultsAreaDiv.dataset.inputs || '{}');
const calculations = JSON.parse(resultsAreaDiv.dataset.calculations || '{}');
if (!inputs || !calculations || calculations.totalSickLeavePay === undefined) {
alert("No results to download. Please calculate first.");
return;
}
// --- PDF Styling (Matching CSS color scheme) ---
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim();
const textColor = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim();
const outputBackgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--output-background').trim();
const white = '#ffffff';
const green = '#27ae60'; // Match green for total pay
doc.setFontSize(18);
doc.setTextColor(primaryColor);
doc.text("Sick Leave Pay Calculation", 14, 22);
doc.setFontSize(12);
doc.setTextColor(textColor);
let yPos = 35;
// Inputs Section in PDF
doc.text("Inputs Provided:", 14, yPos);
yPos += 7;
doc.setFontSize(10);
const inputsTableBody = [
['Employee Pay Type', inputs.payType.charAt(0).toUpperCase() + inputs.payType.slice(1)],
];
if (inputs.payType === 'hourly') {
inputsTableBody.push(['Regular Hourly Rate', formatCurrency(inputs.hourlyRate) + '/hour']);
} else {
inputsTableBody.push(['Regular Annual Salary', formatCurrency(inputs.annualSalary)]);
}
inputsTableBody.push(['Standard Work Hours Per Day', inputs.standardHoursPerDay.toFixed(2) + ' hours']);
inputsTableBody.push(['Sick Leave Duration', `${inputs.leaveDurationValue.toFixed(2)} ${inputs.leaveDurationType}`]);
inputsTableBody.push(['', '']); // Separator
inputsTableBody.push(['Pay Rate For Sick Leave', inputs.sickPayRatePercent.toFixed(2) + '%']);
// Only add optional inputs if they were entered
if (!isNaN(inputs.sickLeaveBalanceAvailableHours)) {
inputsTableBody.push(['Sick Leave Balance Available (Before)', `${inputs.sickLeaveBalanceAvailableHours.toFixed(2)} hours`]);
}
if (inputs.accrualRateInfo) {
inputsTableBody.push(['Accrual Rate Info', inputs.accrualRateInfo]);
}
doc.autoTable({
startY: yPos + 5,
head: [['Description', 'Value']],
body: inputsTableBody,
theme: 'grid',
styles: {
textColor: textColor.substring(1),
lineColor: '#cccccc',
lineWidth: 0.1,
cellPadding: 3
},
headStyles: {
fillColor: primaryColor.substring(1),
textColor: white.substring(1),
fontStyle: 'bold'
},
bodyStyles: {
fillColor: outputBackgroundColor.substring(1),
textColor: textColor.substring(1)
},
alternateRowStyles: {
fillColor: white.substring(1)
},
margin: { top: yPos + 5 }
});
const inputsTableFinalY = doc.autoTable.previous.finalY || yPos + 5;
// Calculated Items Section in PDF
yPos = inputsTableFinalY + 15; // Space after inputs table
doc.setFontSize(12);
doc.setTextColor(primaryColor);
doc.text("Calculated Items:", 14, yPos);
const calculationsTableBody = [
['Effective Regular Hourly Rate', formatCurrency(calculations.effectiveRegularHourlyRate) + '/hour'],
['Total Sick Leave Hours Taken', calculations.totalSickLeaveHours.toFixed(2) + ' hours'],
['Sick Leave Hourly Pay Rate', formatCurrency(calculations.sickLeaveHourlyPayRate) + '/hour'],
];
doc.autoTable({
startY: yPos + 5,
head: [['Calculation', 'Value']],
body: calculationsTableBody,
theme: 'grid',
styles: {
textColor: textColor.substring(1),
lineColor: '#cccccc',
lineWidth: 0.1,
cellPadding: 3
},
headStyles: {
fillColor: primaryColor.substring(1),
textColor: white.substring(1),
fontStyle: 'bold'
},
bodyStyles: {
fillColor: outputBackgroundColor.substring(1),
textColor: textColor.substring(1)
},
alternateRowStyles: {
fillColor: white.substring(1)
},
margin: { top: yPos + 5 }
});
const calculationsTableFinalY = doc.autoTable.previous.finalY || yPos + 5;
// Total Pay and Balance in PDF
yPos = calculationsTableFinalY + 15; // Space after calculations table
doc.setFontSize(14);
doc.setTextColor(green); // Total pay in green
doc.text(`Total Sick Leave Pay: ${formatCurrency(calculations.totalSickLeavePay)}`, 14, yPos);
if (calculations.remainingSickLeaveBalanceHours !== null) {
yPos += 10; // Space before balance
doc.setFontSize(10);
doc.setTextColor('#555');
doc.text(`Remaining Sick Leave Balance: ${calculations.remainingSickLeaveBalanceHours.toFixed(2)} hours`, 14, yPos);
}
doc.save('sick_leave_pay_calculation.pdf');
});
});