`;
taskListDiv.appendChild(taskElement);
});
}
}
/**
* Calculates the total time from the tasks array and updates the summary display.
*/
function updateTotal() {
let totalMinutes = tasks.reduce((total, task) => {
const timeInMinutes = task.unit === 'Hours' ? task.time * 60 : parseInt(task.time, 10);
return total + timeInMinutes;
}, 0);
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
totalTimeDisplay.textContent = `${hours} Hours, ${minutes} Minutes`;
}
/**
* Adds a new task to the list based on user input.
*/
function handleAddTask() {
const description = taskDescriptionInput.value.trim();
const time = taskTimeInput.value;
const unit = taskTimeUnitSelect.value;
if (!description || !time || time <= 0) {
showErrorMessage('Please provide a valid task description and a positive time value.');
return;
}
tasks.push({ id: Date.now(), description, time: parseFloat(time), unit });
taskDescriptionInput.value = '';
taskTimeInput.value = '';
taskTimeUnitSelect.value = 'Minutes';
renderTasks();
updateTotal();
}
/**
* Removes a task from the list by its ID.
* @param {number} taskId - The unique ID of the task to remove.
*/
function removeTask(taskId) {
tasks = tasks.filter(task => task.id !== taskId);
renderTasks();
updateTotal();
}
/**
* Generates and triggers the download of a PDF summary of the tasks.
*/
function downloadPDF() {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
console.error('jsPDF library is not loaded.');
showErrorMessage('Could not generate PDF. The required library is missing.');
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(18);
doc.text('Task Time Estimate Summary', 14, 22);
doc.setFontSize(11);
doc.setTextColor(100);
doc.text(`Generated on: ${new Date().toLocaleDateString()}`, 14, 30);
const tableColumn = ["Task Description", "Estimated Time"];
const tableRows = tasks.map(task => [task.description, `${task.time} ${task.unit}`]);
const totalText = totalTimeDisplay.textContent;
const totalRow = [{content: 'Total Estimated Time', colSpan: 1, styles: { halign: 'right', fontStyle: 'bold' }}, {content: totalText, styles: { fontStyle: 'bold' }}];
// The autoTable function should now exist on the doc instance
doc.autoTable({
head: [tableColumn],
body: tableRows,
foot: [totalRow], // Using foot for the total row is semantically better
startY: 40,
theme: 'grid',
headStyles: { fillColor: [59, 130, 246], textColor: [255, 255, 255], fontStyle: 'bold' },
footStyles: { fillColor: [243, 244, 246] }
});
doc.save('task-time-estimate.pdf');
}
// IV.C: Primary event listeners are attached here.
addTaskBtn.addEventListener('click', handleAddTask);
downloadPdfBtn.addEventListener('click', downloadPDF);
taskTimeInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
event.preventDefault();
handleAddTask();
}
});
// Use event delegation for remove buttons for better performance
taskListDiv.addEventListener('click', function(event) {
if (event.target.classList.contains('remove-task-btn')) {
const taskId = parseInt(event.target.getAttribute('data-id'), 10);
removeTask(taskId);
}
});
// Initial call to load sample data and render the view
loadSampleData();
});
