Online Real-Time Task Progress Chart

Real-Time Task Progress Chart

Task Completion Status

Add a New Task

50%

Task List

Export Progress Chart

Download the current Task Progress Chart as a PDF document.

No tasks added yet.

'; return; } const table = document.createElement('table'); table.className = 'min-w-full bg-white'; table.innerHTML = ` Task Name Progress Actions ${tasks.map(task => ` ${task.name} ${task.progress}% `).join('')} `; taskListContainer.innerHTML = ''; taskListContainer.appendChild(table); } // --- LOGIC FUNCTIONS --- function clearForm() { taskForm.reset(); taskIdInput.value = ''; taskProgressInput.value = 50; progressValueSpan.textContent = '50%'; formTitle.textContent = 'Add a New Task'; saveBtn.textContent = 'Add Task'; } function handleFormSubmit(e) { e.preventDefault(); const id = taskIdInput.value ? parseInt(taskIdInput.value) : null; const taskData = { name: taskNameInput.value, progress: parseInt(taskProgressInput.value), }; if (id) { // Update const index = tasks.findIndex(t => t.id === id); tasks[index] = { ...tasks[index], ...taskData }; } else { // Add const newId = tasks.length > 0 ? Math.max(...tasks.map(t => t.id)) + 1 : 1; tasks.push({ id: newId, ...taskData }); } renderAll(); clearForm(); } window.editTask = (id) => { const task = tasks.find(t => t.id === id); if (task) { taskIdInput.value = task.id; taskNameInput.value = task.name; taskProgressInput.value = task.progress; progressValueSpan.textContent = `${task.progress}%`; formTitle.textContent = 'Edit Task'; saveBtn.textContent = 'Save Changes'; changeTab(null, 'manage-tasks'); } } window.deleteTask = (id) => { if (confirm('Are you sure you want to delete this task?')) { tasks = tasks.filter(t => t.id !== id); renderAll(); } } function downloadPDF() { const { jsPDF } = window.jspdf; const pdfContentEl = document.getElementById('pdf-content'); html2canvas(pdfContentEl, { scale: 2 }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgProps = pdf.getImageProperties(imgData); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, 'PNG', 20, 20, pdfWidth - 40, pdfHeight - 40); pdf.save('Task_Progress_Report.pdf'); }); } function renderAll() { renderChart(); renderTaskList(); } // --- TAB NAVIGATION --- window.changeTab = function(evt, tabName) { document.querySelectorAll(".tab-content").forEach(tc => tc.classList.remove('active')); document.querySelectorAll(".tab-button").forEach(tb => tb.classList.remove('active')); document.getElementById(tabName).classList.add('active'); const button = evt ? evt.currentTarget : document.querySelector(`.tab-button[onclick*="'${tabName}'"]`); if(button) button.classList.add('active'); currentTab = tabName; updateNavButtons(); if (tabName === 'progress-chart') renderChart(); } function updateNavButtons() { const currentIndex = tabs.indexOf(currentTab); prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex === tabs.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); } prevBtn.addEventListener('click', () => { const currentIndex = tabs.indexOf(currentTab); if (currentIndex > 0) changeTab(null, tabs[currentIndex - 1]); }); nextBtn.addEventListener('click', () => { const currentIndex = tabs.indexOf(currentTab); if (currentIndex < tabs.length - 1) changeTab(null, tabs[currentIndex + 1]); }); // --- EVENT LISTENERS --- taskForm.addEventListener('submit', handleFormSubmit); clearBtn.addEventListener('click', clearForm); taskProgressInput.addEventListener('input', (e) => { progressValueSpan.textContent = `${e.target.value}%`; }); downloadPdfBtn.addEventListener('click', downloadPDF); // --- INITIALIZATION --- renderAll(); updateNavButtons(); });
Scroll to Top