No tasks to process. Please add tasks in the "Setup Schedule" tab first.
';
return;
}
const bufferType = bufferTypeSelect ? bufferTypeSelect.value : 'percentage';
const bufferValue = bufferValueInput ? parseFloat(bufferValueInput.value) || 0 : 0;
let totalOriginalDuration = 0;
let totalBufferedDuration = 0;
const results = tasks.map(task => {
totalOriginalDuration += task.duration;
let bufferAmount = 0;
if (bufferType === 'percentage') {
bufferAmount = Math.round(task.duration * (bufferValue / 100));
} else { // fixed
bufferAmount = bufferValue;
}
const bufferedDuration = task.duration + bufferAmount;
totalBufferedDuration += bufferedDuration;
return {
...task,
bufferAmount,
bufferedDuration
};
});
resultsOutput.innerHTML = `
| Task Name |
Original (mins) |
Buffer Added (mins) |
New Duration (mins) |
${results.map(r => `
| ${r.name} |
${r.duration} |
${r.bufferAmount} |
${r.bufferedDuration} |
`).join('')}
Original Total Time
${totalOriginalDuration} mins
Buffered Total Time
${totalBufferedDuration} mins
`;
};
/**
* Handles tab switching and updates UI accordingly.
* @param {number} tabNumber - The tab to switch to (1 or 2).
*/
const switchTab = (tabNumber) => {
currentTab = tabNumber;
if (currentTab === 1) {
tabContent1.classList.remove('hidden');
tabContent2.classList.add('hidden');
tabBtn1.classList.add('active');
tabBtn2.classList.remove('active');
prevBtn.style.visibility = 'hidden';
nextBtn.style.visibility = 'visible';
} else {
tabContent1.classList.add('hidden');
tabContent2.classList.remove('hidden');
tabBtn1.classList.remove('active');
tabBtn2.classList.add('active');
prevBtn.style.visibility = 'visible';
nextBtn.style.visibility = 'hidden';
// Calculate results when switching to tab 2
calculateAndRenderResults();
}
};
/**
* Generates and triggers the download of a PDF summary.
*/
const generatePDF = () => {
if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') {
alert('PDF generation library is not loaded.');
return;
}
if (tasks.length === 0) {
alert('Cannot generate PDF. No tasks have been added.');
return;
}
const { jsPDF } = jspdf;
const doc = new jsPDF();
const bufferType = bufferTypeSelect ? bufferTypeSelect.value : 'percentage';
const bufferValue = bufferValueInput ? parseFloat(bufferValueInput.value) || 0 : 0;
// Calculate totals again for the PDF
let totalOriginalDuration = 0;
let totalBufferedDuration = 0;
const tableBody = tasks.map(task => {
totalOriginalDuration += task.duration;
let bufferAmount = 0;
if (bufferType === 'percentage') {
bufferAmount = Math.round(task.duration * (bufferValue / 100));
} else {
bufferAmount = bufferValue;
}
const bufferedDuration = task.duration + bufferAmount;
totalBufferedDuration += bufferedDuration;
return [task.name, task.duration, bufferAmount, bufferedDuration];
});
// --- PDF Content ---
doc.setFontSize(18);
doc.setTextColor('#374151'); // gray-700
doc.text('Time Buffer Management Summary', 14, 22);
doc.setFontSize(11);
doc.setTextColor('#6B7280'); // gray-500
doc.text(`Generated on: ${new Date().toLocaleDateString()}`, 14, 30);
doc.text(`Buffer Applied: ${bufferValue}${bufferType === 'percentage' ? '%' : ' minutes (fixed)'}`, 14, 36);
// Add the table
doc.autoTable({
startY: 45,
head: [['Task Name', 'Original (mins)', 'Buffer Added (mins)', 'New Duration (mins)']],
body: tableBody,
theme: 'grid',
headStyles: {
fillColor: '#3b82f6' // blue-500
},
styles: {
cellPadding: 3,
fontSize: 10
}
});
// Add totals section after the table
const finalY = doc.autoTable.previous.finalY;
doc.setFontSize(12);
doc.setTextColor('#1F2937'); // gray-800
doc.text('Total Summary:', 14, finalY + 15);
doc.setFontSize(11);
doc.setTextColor('#374151'); // gray-700
doc.text(`Original Total Time: ${totalOriginalDuration} minutes`, 14, finalY + 22);
doc.setFontSize(11);
doc.setFont(undefined, 'bold');
doc.setTextColor('#2563EB'); // blue-600
doc.text(`Buffered Total Time: ${totalBufferedDuration} minutes`, 14, finalY + 29);
doc.save('Time-Buffer-Schedule.pdf');
};
// --- Event Listeners ---
if (tabBtn1) tabBtn1.addEventListener('click', () => switchTab(1));
if (tabBtn2) tabBtn2.addEventListener('click', () => switchTab(2));
if (prevBtn) prevBtn.addEventListener('click', () => switchTab(1));
if (nextBtn) nextBtn.addEventListener('click', () => switchTab(2));
if (bufferTypeSelect) {
bufferTypeSelect.addEventListener('change', (e) => {
if (bufferUnit) {
bufferUnit.textContent = e.target.value === 'percentage' ? '%' : 'mins';
}
});
}
if (addTaskBtn) {
addTaskBtn.addEventListener('click', () => {
const name = taskNameInput ? taskNameInput.value.trim() : '';
const duration = taskDurationInput ? parseInt(taskDurationInput.value, 10) : 0;
if (name && duration > 0) {
tasks.push({ id: Date.now(), name, duration });
renderTaskList();
if (taskNameInput) taskNameInput.value = '';
if (taskDurationInput) taskDurationInput.value = '';
if (taskNameInput) taskNameInput.focus();
} else {
alert('Please enter a valid task name and a duration greater than 0.');
}
});
}
// Event delegation for remove buttons
if (taskListContainer) {
taskListContainer.addEventListener('click', (e) => {
if (e.target.classList.contains('remove-task-btn')) {
const taskId = parseInt(e.target.getAttribute('data-id'), 10);
tasks = tasks.filter(task => task.id !== taskId);
renderTaskList();
}
});
}
if (downloadPdfBtn) {
downloadPdfBtn.addEventListener('click', generatePDF);
}
// Allow adding tasks by pressing Enter
if (taskDurationInput) {
taskDurationInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Prevent form submission
addTaskBtn.click();
}
});
}
// --- Initial Call ---
setupInitialTasks();
});