Real-Time Task Time Estimator

Real-Time Task Time Estimator

Task List

Your task list is empty. Add a task to begin.

Total Estimated Time: 0 Hours, 0 Minutes

${task.description}

${task.time} ${task.unit}
`; 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(); });
Scroll to Top