Online Automated Productivity Time Tracker

Automated Productivity Time Tracker

Today's Log

Task Project Duration Actions

${project}: ${formatTime(duration)}

` ).join(''); // Render Chart const chartCanvas = document.getElementById('report-chart'); if (reportChart) reportChart.destroy(); reportChart = new Chart(chartCanvas, { type: 'doughnut', data: { labels: Object.keys(timeByProject), datasets: [{ label: 'Time by Project', data: Object.values(timeByProject), backgroundColor: ['#4f46e5', '#ec4899', '#22c55e', '#f97316', '#3b82f6', '#8b5cf6'], hoverOffset: 4 }] }, options: { responsive: true, maintainAspectRatio: false } }); document.getElementById('report-content').classList.remove('hidden'); }; // --- DATA CONFIGURATION --- const addProject = () => { const newProject = newProjectInput.value.trim(); if (newProject && !projects.includes(newProject)) { projects.push(newProject); saveData(); renderProjects(); newProjectInput.value = ''; } }; const deleteProject = (projectName) => { projects = projects.filter(p => p !== projectName); saveData(); renderProjects(); }; const deleteTask = (taskId) => { tasks = tasks.filter(t => t.id !== Number(taskId)); saveData(); renderTodaysLog(); }; // --- TAB MANAGEMENT --- window.changeTab = (tabId) => { currentTab = tabId; ['tab1', 'tab2', 'tab3'].forEach(id => { document.getElementById(id).classList.toggle('hidden', id !== tabId); document.getElementById(`${id}-button`).classList.toggle('active', id === tabId); }); updateButtonVisibility(); }; const updateButtonVisibility = () => { const prevBtn = document.getElementById('prev-button'); const nextBtn = document.getElementById('next-button'); const downloadBtn = document.getElementById('download-pdf-button'); prevBtn.classList.toggle('hidden', currentTab === 'tab1'); nextBtn.classList.toggle('hidden', currentTab === 'tab3'); downloadBtn.classList.toggle('hidden', currentTab !== 'tab2' || !document.getElementById('report-content').classList.contains('hidden')); }; window.handleNext = () => { const tabs = ['tab1', 'tab2', 'tab3']; const currentIndex = tabs.indexOf(currentTab); if (currentIndex < 2) changeTab(tabs[currentIndex + 1]); }; window.handlePrev = () => { const tabs = ['tab1', 'tab2', 'tab3']; const currentIndex = tabs.indexOf(currentTab); if (currentIndex > 0) changeTab(tabs[currentIndex - 1]); }; // --- PDF DOWNLOAD --- window.downloadPDF = async () => { const reportContent = document.getElementById('report-content'); if (reportContent.classList.contains('hidden')) { alert("Please generate a report first."); return; } const { jsPDF } = window.jspdf; try { const canvas = await html2canvas(reportContent, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'px', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgWidth = canvas.width; const imgHeight = canvas.height; const ratio = imgWidth / imgHeight; let newWidth = pdfWidth; let newHeight = newWidth / ratio; if (newHeight > pdfHeight) { newHeight = pdfHeight; newWidth = newHeight * ratio; } pdf.addImage(imgData, 'PNG', 0, 0, newWidth, newHeight); pdf.save('productivity-report.pdf'); } catch (error) { console.error("PDF generation failed:", error); alert("Could not generate PDF."); } }; // --- EVENT LISTENERS --- startBtn.addEventListener('click', startTimer); stopBtn.addEventListener('click', stopTimer); addProjectBtn.addEventListener('click', addProject); generateReportBtn.addEventListener('click', generateReport); projectList.addEventListener('click', (e) => { if (e.target.tagName === 'BUTTON' && e.target.dataset.project) { if (confirm(`Are you sure you want to delete the project "${e.target.dataset.project}"?`)) { deleteProject(e.target.dataset.project); } } }); todaysLogBody.addEventListener('click', (e) => { if (e.target.tagName === 'BUTTON' && e.target.dataset.taskId) { if (confirm(`Are you sure you want to delete this task entry?`)) { deleteTask(e.target.dataset.taskId); } } }); // --- INITIALIZATION --- loadData(); updateButtonVisibility(); const today = new Date().toISOString().slice(0, 10); reportStartDateInput.value = today; reportEndDateInput.value = today; });
Scroll to Top