Productivity Score Analyzer

Productivity Score Analyzer

Add / Edit Task

Task List

Productivity Analysis

Scoring Settings

Value: ${task.value} | Due: ${task.dueDate ? formatDate(task.dueDate) : 'N/A'}

`; plannedTasksListUL.appendChild(li); }); if(completed.length === 0) completedTasksListUL.innerHTML = "
  • No tasks were completed in this period.
  • "; completed.forEach(task => { const li = document.createElement('li'); li.className = 'task-item status-done'; // All completed tasks are 'done' let timelinessInfo = task.timelinessStatus && task.timelinessStatus !== 'N/A' ? ` | Status: ${task.timelinessStatus}` : ''; li.innerHTML = `

    ${task.description}

    Achieved Value: ${task.achievedValueWithBonus.toFixed(1)} (Base: ${task.value}) | Completed: ${formatDate(task.completionDate)}${timelinessInfo}

    `; completedTasksListUL.appendChild(li); }); } // --- PDF Download --- downloadReportPdfBtn.addEventListener('click', () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const periodText = analysisPeriodSelect.options[analysisPeriodSelect.selectedIndex].text; let dateRangeText = periodText; if (periodText === 'Custom Range') { dateRangeText = `${formatDate(customStartDateInput.value)} to ${formatDate(customEndDateInput.value)}`; } doc.setFontSize(18); doc.setTextColor(parseInt(getComputedStyle(document.documentElement).getPropertyValue('--primary-color').substring(1,3),16), parseInt(getComputedStyle(document.documentElement).getPropertyValue('--primary-color').substring(3,5),16), parseInt(getComputedStyle(document.documentElement).getPropertyValue('--primary-color').substring(5,7),16)); doc.text('Productivity Analysis Report', 14, 22); doc.setFontSize(12); doc.setTextColor(100); doc.text(`Period: ${dateRangeText}`, 14, 30); doc.text(`Generated on: ${new Date().toLocaleString()}`, 14, 36); doc.setFontSize(14); doc.text(`Overall Productivity Score: ${productivityScoreDiv.textContent}`, 14, 46); doc.setFontSize(11); let yPos = 54; doc.text(`Value Planned for Period: ${totalValuePlannedDiv.textContent} points`, 14, yPos); yPos +=6; doc.text(`Value Achieved (incl. bonus): ${totalValueAchievedDiv.textContent} points`, 14, yPos); yPos +=6; doc.text(`Tasks Completed: ${tasksCompletedCountDiv.textContent}`, 14, yPos); yPos +=6; doc.text(`Tasks On Time: ${tasksOnTimeCountDiv.textContent}`, 14, yPos); yPos +=6; doc.text(`Tasks Late: ${tasksLateCountDiv.textContent}`, 14, yPos); yPos +=10; doc.setFontSize(12); doc.text('Tasks Considered Planned:', 14, yPos); yPos +=6; const plannedData = Array.from(plannedTasksListUL.children).map(li => { const desc = li.querySelector('.task-description').textContent; const meta = li.querySelector('.task-meta').textContent; const value = meta.match(/Value: (\d+)/) ? meta.match(/Value: (\d+)/)[1] : 'N/A'; const dueDate = meta.match(/Due: (.*?)$/) ? meta.match(/Due: (.*?)$/)[1].trim() : 'N/A'; return [desc, value, dueDate]; }); if (plannedData.length > 0) { doc.autoTable({ startY: yPos, head: [['Description', 'Value', 'Due Date']], body: plannedData, theme: 'grid' }); yPos = doc.lastAutoTable.finalY + 10; } else { doc.text('No tasks were planned for this period.', 16, yPos); yPos += 7; } doc.setFontSize(12); doc.text('Tasks Completed in Period:', 14, yPos); yPos +=6; const completedData = Array.from(completedTasksListUL.children).map(li => { const desc = li.querySelector('.task-description').textContent; const meta = li.querySelector('.task-meta').textContent; // "Achieved Value: X (Base: Y) | Completed: Z | Status: W" const achieved = meta.match(/Achieved Value: ([\d\.]+)/) ? meta.match(/Achieved Value: ([\d\.]+)/)[1] : 'N/A'; const completed = meta.match(/Completed: ([\d\-]+)/) ? meta.match(/Completed: ([\d\-]+)/)[1] : 'N/A'; const status = meta.match(/Status: (.*?)$/) ? meta.match(/Status: (.*?)$/)[1].trim() : 'N/A'; return [desc, achieved, completed, status]; }); if (completedData.length > 0) { doc.autoTable({ startY: yPos, head: [['Description', 'Achieved Value', 'Completed Date', 'Timeliness']], body: completedData, theme: 'grid' }); } else { doc.text('No tasks were completed in this period.', 16, yPos); } doc.save(`Productivity_Report_${dateRangeText.replace(/[\s/:]/g, '_')}.pdf`); }); // --- Initializations --- setDateInputConstraints(); loadSettings(); renderTaskList(); // Set default custom range for analysis tab const today = new Date(); const todayStr = formatDate(today); const sevenDaysAgo = new Date(today); sevenDaysAgo.setDate(today.getDate() - 6); customStartDateInput.value = formatDate(sevenDaysAgo); customEndDateInput.value = todayStr; })(); // End IIFE
    Scroll to Top