Remote Work Productivity Monitor

Remote Work Productivity Monitor

Visualize your team's performance and identify key productivity trends.

Productivity Dashboard

Team Performance Overview

Team Member Details

Team Member Tasks Completed Hours Logged Productivity Score

Team Data Input

Add, edit, or remove team members and their weekly data below.

${kpi.label}

${kpi.value}

`).join(''); lucide.createIcons(); // Render Chart renderPerformanceChart(); // Render Details Table dom.teamDetailsTable.innerHTML = teamData.map(member => { const productivity = member.hours > 0 ? ((member.tasks / member.hours) * 10).toFixed(1) : 'N/A'; return ` ${member.name} ${member.tasks} ${member.hours} ${productivity} `; }).join(''); } function renderPerformanceChart() { const ctx = document.getElementById('team-performance-chart').getContext('2d'); const labels = teamData.map(m => m.name); const tasksData = teamData.map(m => m.tasks); const hoursData = teamData.map(m => m.hours); if (teamPerformanceChart) { teamPerformanceChart.destroy(); } teamPerformanceChart = new Chart(ctx, { type: 'bar', data: { labels, datasets: [ { label: 'Tasks Completed', data: tasksData, backgroundColor: '#3b82f6', borderColor: '#1e40af', borderWidth: 1, borderRadius: 4, }, { label: 'Hours Logged', data: hoursData, backgroundColor: '#a5b4fc', borderColor: '#4338ca', borderWidth: 1, borderRadius: 4, } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, grid: { color: '#e5e7eb' } }, x: { grid: { display: false } } }, plugins: { legend: { position: 'top' } } } }); } // --- EVENT HANDLERS & DATA MANIPULATION --- function handleDataChange(event) { const id = parseInt(event.target.dataset.id, 10); const field = event.target.dataset.field; const value = field === 'name' ? event.target.value : parseInt(event.target.value, 10) || 0; const memberIndex = teamData.findIndex(m => m.id === id); if (memberIndex > -1) { teamData[memberIndex][field] = value; } renderDashboard(); } function addMember() { const newId = teamData.length > 0 ? Math.max(...teamData.map(m => m.id)) + 1 : 1; teamData.push({ id: newId, name: 'New Member', tasks: 0, hours: 0 }); renderDataConfiguration(); renderDashboard(); } function deleteMember(event) { const id = parseInt(event.currentTarget.dataset.id, 10); teamData = teamData.filter(m => m.id !== id); renderDataConfiguration(); renderDashboard(); } // --- UI & PDF --- window.changeTab = function(tabNumber) { document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active')); document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active')); document.getElementById(`tab-btn-${tabNumber}`).classList.add('active'); document.getElementById(`tab-content-${tabNumber}`).classList.add('active'); dom.navPrev.style.display = (tabNumber === 2) ? 'inline-flex' : 'none'; dom.navNext.style.display = (tabNumber === 1) ? 'inline-flex' : 'none'; } window.downloadPDF = function() { const { jsPDF } = window.jspdf; const pdfElement = document.getElementById('pdf-output'); if (teamPerformanceChart) teamPerformanceChart.options.animation = false; html2canvas(pdfElement, { scale: 2, backgroundColor: '#f0f2f5', onclone: (doc) => { // Re-render lucide icons in the cloned document for canvas capture doc.querySelectorAll('[data-lucide]').forEach(el => { const iconName = el.getAttribute('data-lucide'); if (lucide.icons[iconName]) el.innerHTML = lucide.icons[iconName].toSvg(); }); } }).then(canvas => { if (teamPerformanceChart) teamPerformanceChart.options.animation = true; const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'px', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pageMargin = 40; const contentWidth = pdfWidth - (pageMargin * 2); const canvasRatio = canvas.height / canvas.width; const contentHeight = contentWidth * canvasRatio; pdf.addImage(imgData, 'PNG', pageMargin, pageMargin, contentWidth, contentHeight); pdf.save('Productivity-Report.pdf'); }); } init(); });
Scroll to Top