Online Task Completion Forecasting Tool

Task Completion Forecasting Tool

Analyze your past performance to predict future task timelines.

Log a Completed Task

Your Historical Data

No new tasks added yet.

'; generateForecastBtn.disabled = true; return; } generateForecastBtn.disabled = false; appData.newTasks.forEach(task => { const taskEl = document.createElement('div'); taskEl.className = 'flex items-center justify-between p-3 bg-white border rounded-lg'; taskEl.innerHTML = ` ${task.name} Est: ${task.estimated}h `; newTaskList.appendChild(taskEl); }); }; addNewTaskBtn.addEventListener('click', () => { const name = newTaskName.value.trim(); const estimated = parseFloat(newEstimatedTime.value); if (!name || isNaN(estimated) || estimated <= 0) { showMessage('Please enter a task name and a valid estimated time.'); return; } appData.newTasks.push({ id: Date.now(), name, estimated }); saveData(); renderNewTaskList(); newTaskName.value = ''; newEstimatedTime.value = ''; showMessage('New task added.', false); }); newTaskList.addEventListener('click', (e) => { if (e.target.classList.contains('delete-new-task-btn')) { const taskId = parseInt(e.target.dataset.taskId, 10); appData.newTasks = appData.newTasks.filter(t => t.id !== taskId); saveData(); renderNewTaskList(); } }); // --- TAB 3: FORECASTING --- generateForecastBtn.addEventListener('click', () => { if (appData.historicalTasks.length < 3) { showMessage('Please add at least 3 historical tasks for an accurate forecast.'); return; } if (appData.newTasks.length === 0) { showMessage('Please add new tasks to forecast on Tab 2.'); return; } // Calculate completion factor const totalEstimated = appData.historicalTasks.reduce((sum, t) => sum + t.estimated, 0); const totalActual = appData.historicalTasks.reduce((sum, t) => sum + t.actual, 0); const completionFactor = totalActual / totalEstimated; // Render forecast renderForecast(completionFactor); // Generate AI advice generateAdvice(completionFactor); switchTab('tab3'); }); const renderForecast = (factor) => { completionFactorDisplay.textContent = factor.toFixed(2); factorPercentageDisplay.textContent = (factor * 100).toFixed(0); forecastList.innerHTML = ''; appData.newTasks.forEach(task => { const forecastedTime = task.estimated * factor; const listItem = document.createElement('li'); listItem.className = 'flex justify-between items-center p-2'; listItem.innerHTML = ` ${task.name} ${forecastedTime.toFixed(1)}h `; forecastList.appendChild(listItem); }); }; const generateAdvice = async (factor) => { adviceLoader.classList.remove('hidden'); adviceContent.innerHTML = ''; const historySummary = appData.historicalTasks.map(t => `Task "${t.name}" was estimated at ${t.estimated} hours but took ${t.actual} hours.` ).join('\n'); const prompt = `A user has a task completion factor of ${factor.toFixed(2)}. This means they tend to take ${ (factor * 100).toFixed(0) }% of their estimated time. Their recent task history is:\n${historySummary}\n\nBased on this, provide 2-3 concise, actionable tips to help them improve their estimation accuracy and project planning. Frame the advice positively.`; const advice = await callGeminiAPI(prompt); adviceLoader.classList.add('hidden'); if (advice) { adviceContent.innerHTML = advice.replace(/\n/g, '
'); } else { adviceContent.innerHTML = '

Could not generate advice at this time.

'; } }; // --- PDF DOWNLOAD --- downloadPdfBtn.addEventListener('click', () => { showMessage('Preparing PDF...', false); const { jsPDF } = window.jspdf; const element = document.getElementById('pdf-export-area'); html2canvas(element, { scale: 2, useCORS: true }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'in', format: 'letter' }); const pdfWidth = pdf.internal.pageSize.getWidth() - 1; const pdfHeight = (canvas.height * pdfWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0.5, 0.5, pdfWidth, pdfHeight); pdf.save('Task_Forecast_Plan.pdf'); showMessage('PDF downloaded successfully!', false); }).catch(err => { console.error("PDF Generation Error:", err); showMessage("An error occurred during PDF generation."); }); }); // --- INITIALIZATION --- const initializeApp = () => { loadData(); renderHistoricalList(); renderNewTaskList(); switchTab('tab1'); }; initializeApp(); });
Scroll to Top