Work Hour Optimization Dashboard

Work Hour Optimization Dashboard

Log New Activity

Logged Activities

Date Activity Category Start End Duration (min) Value Actions

Note: Activity data is stored in your browser's LocalStorage. Clearing it here will remove all logged activities permanently from this browser.

Analysis Filters

Log activities and select a date range to view the dashboard.

No activities logged. Please log activities in Tab 1 to see the dashboard.

'; return; } const startDateStr = document.getElementById('whod-analysis-start-date').value; const endDateStr = document.getElementById('whod-analysis-end-date').value; if(!startDateStr || !endDateStr) { // This can happen if called before inputs are fully set, like on initial load before date defaults are fully applied. // It might be better to call this explicitly after defaults are set and tab is opened. // For now, if date inputs are not ready, don't proceed. return; } const startDate = new Date(startDateStr + "T00:00:00"); const endDate = new Date(endDateStr + "T23:59:59"); const filteredActivities = whodLoggedActivities.filter(act => act.dateObj >= startDate && act.dateObj <= endDate); if (filteredActivities.length === 0) { document.getElementById('whod-dashboard-display').innerHTML = '

No activities logged in the selected date range.

'; if(whodChartCategoryInstance) whodChartCategoryInstance.destroy(); if(whodChartValueInstance) whodChartValueInstance.destroy(); return; } let timeByCategory = {}; let timeByValue = { High: 0, Medium: 0, Low: 0 }; let totalLoggedMinutes = 0; WHOD_ACTIVITY_CATEGORIES.forEach(cat => timeByCategory[cat] = 0); // Initialize categories filteredActivities.forEach(act => { timeByCategory[act.category] = (timeByCategory[act.category] || 0) + act.duration; timeByValue[act.value] = (timeByValue[act.value] || 0) + act.duration; totalLoggedMinutes += act.duration; }); const totalHoursLogged = (totalLoggedMinutes / 60).toFixed(1); let focusedWorkMinutes = timeByCategory["Focused Work"] || 0; let meetingMinutes = timeByCategory["Meetings"] || 0; let highValueMinutes = timeByValue["High"] || 0; // Build Dashboard HTML let dashboardHTML = `

Key Metrics (${startDate.toLocaleDateString()} - ${endDate.toLocaleDateString()})

  • Total Hours Logged: ${totalHoursLogged} hrs
  • Focused Work: ${(focusedWorkMinutes / 60).toFixed(1)} hrs (${totalLoggedMinutes > 0 ? (focusedWorkMinutes/totalLoggedMinutes*100).toFixed(0) : 0}%)
  • Meetings: ${(meetingMinutes / 60).toFixed(1)} hrs (${totalLoggedMinutes > 0 ? (meetingMinutes/totalLoggedMinutes*100).toFixed(0) : 0}%)
  • High Value Activities: ${(highValueMinutes / 60).toFixed(1)} hrs (${totalLoggedMinutes > 0 ? (highValueMinutes/totalLoggedMinutes*100).toFixed(0) : 0}%)

Time Allocation by Category

Time Allocation by Perceived Value

Optimization Insights & Recommendations

    `; document.getElementById('whod-dashboard-display').innerHTML = dashboardHTML; // Generate Charts whodRenderPieChart('whod-category-chart', timeByCategory, 'Time by Category'); whodRenderPieChart('whod-value-chart', timeByValue, 'Time by Value'); // Generate Insights const insightsListEl = document.getElementById('whod-insights-list'); insightsListEl.innerHTML = ''; // Clear previous let insightsGenerated = 0; if (totalLoggedMinutes > 0) { if ((meetingMinutes / totalLoggedMinutes) > 0.4) { insightsListEl.innerHTML += `
  • Meetings constitute over 40% of your logged time. Review if all are essential or could be optimized (e.g., shorter, fewer attendees, email instead).
  • `; insightsGenerated++;} if ((timeByCategory["Admin"] / totalLoggedMinutes) > 0.2 && timeByValue["Low"] > (timeByCategory["Admin"] * 0.5) ) { insightsListEl.innerHTML += `
  • A significant portion of time is on Admin tasks, potentially of low value. Explore batching these tasks or delegation.
  • `; insightsGenerated++;} if ((focusedWorkMinutes / totalLoggedMinutes) < 0.3) { insightsListEl.innerHTML += `
  • Focused work is less than 30% of logged time. Try scheduling dedicated 'deep work' blocks and minimizing distractions during them.
  • `; insightsGenerated++;} if ((timeByCategory["Interruptions"] / totalLoggedMinutes) > 0.1) { insightsListEl.innerHTML += `
  • Interruptions account for over 10% of time. Identify common sources and create strategies to reduce them (e.g., status messages, focused time slots).
  • `; insightsGenerated++;} if ((highValueMinutes / totalLoggedMinutes) < 0.4) { insightsListEl.innerHTML += `
  • Less than 40% of time is spent on high-value activities. Align daily tasks with key goals to maximize impact. Consider if low-value tasks can be reduced.
  • `; insightsGenerated++;} } if(insightsGenerated === 0 && totalLoggedMinutes > 0) { insightsListEl.innerHTML += `
  • Your time distribution seems relatively balanced based on common heuristics. Continue to monitor and adjust as needed!
  • `; } else if (totalLoggedMinutes === 0) { insightsListEl.innerHTML += `
  • No activities logged in this period to provide insights.
  • `; } } function whodRenderPieChart(canvasId, dataObject, chartLabel) { const ctx = document.getElementById(canvasId); if (!ctx) return; const labels = Object.keys(dataObject).filter(key => dataObject[key] > 0); const data = labels.map(key => dataObject[key]); // Predefined color palette for consistency in charts const chartColors = [ '#42A5F5', '#66BB6A', '#FFCA28', '#EF5350', '#AB47BC', '#7E57C2', '#26C6DA', '#FF7043', '#8D6E63', '#78909c' ]; const backgroundColors = labels.map((_, i) => chartColors[i % chartColors.length]); let existingChartInstance = canvasId === 'whod-category-chart' ? whodChartCategoryInstance : whodChartValueInstance; if (existingChartInstance) { existingChartInstance.destroy(); } const chartInstance = new Chart(ctx.getContext('2d'), { type: 'pie', data: { labels: labels, datasets: [{ label: chartLabel, data: data, backgroundColor: backgroundColors, borderColor: '#fff', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'right', labels: { boxWidth:15, font: {size:10}} }, tooltip: { callbacks: { label: function(context) { let label = context.label || ''; if (label) label += ': '; if (context.parsed !== null) { label += (context.parsed / 60).toFixed(1) + ' hrs'; // Show hours in tooltip const total = context.dataset.data.reduce((a, b) => a + b, 0); const percentage = total > 0 ? (context.parsed / total * 100).toFixed(1) : 0; label += ` (${percentage}%)`; } return label; } } } } } }); if (canvasId === 'whod-category-chart') whodChartCategoryInstance = chartInstance; else whodChartValueInstance = chartInstance; } // PDF Download function whodDownloadPDF() { const dashboardDisplayElement = document.getElementById('whod-dashboard-display'); if (!dashboardDisplayElement || dashboardDisplayElement.innerHTML.includes("Log activities and select")) { alert("Please generate the dashboard first by logging activities and selecting a date range."); return; } const analysisStartDate = document.getElementById('whod-analysis-start-date').value; const analysisEndDate = document.getElementById('whod-analysis-end-date').value; let pdfHTML = `

    Work Hour Optimization Report

    `; pdfHTML += `

    Analysis Period: ${analysisStartDate} to ${analysisEndDate}

    `; // Key Metrics (extract from generated dashboard) const metricsCardContent = dashboardDisplayElement.querySelector('.whod-metrics-card'); if(metricsCardContent) pdfHTML += `

    Key Metrics

    ${metricsCardContent.innerHTML}`; // Charts (as images) if (whodChartCategoryInstance) { pdfHTML += `

    Time Allocation by Category

    `; } if (whodChartValueInstance) { pdfHTML += `

    Time Allocation by Perceived Value

    `; } // Insights const insightsCardContent = dashboardDisplayElement.querySelector('.whod-insights-card'); if(insightsCardContent) pdfHTML += `
    ${insightsCardContent.innerHTML}`; // Optional: Detailed Activity Log for the period const filteredActivities = whodLoggedActivities.filter(act => { const actDateOnly = act.dateObj.toISOString().split('T')[0]; return actDateOnly >= analysisStartDate && actDateOnly <= analysisEndDate; }); if (filteredActivities.length > 0) { pdfHTML += `

    Detailed Activity Log (${analysisStartDate} to ${analysisEndDate})

    `; pdfHTML += ``; filteredActivities.forEach(act => { pdfHTML += ``; }); pdfHTML += `
    DateActivityCategoryStartEndDuration (min)Value
    ${act.dateObj.toLocaleDateString()}${act.name}${act.category} ${act.startTime}${act.endTime}${act.duration} ${act.value}
    `; } const pdfContainer = document.getElementById('whod-report-content-for-pdf'); pdfContainer.innerHTML = pdfHTML; // Re-apply styles for value tags in PDF dynamically pdfContainer.querySelectorAll('.whod-value-tag').forEach(tag => { if (tag.classList.contains('value-High')) { tag.style.backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--value-high-bg'); tag.style.color = getComputedStyle(document.documentElement).getPropertyValue('--value-high-text');} else if (tag.classList.contains('value-Medium')) { tag.style.backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--value-medium-bg'); tag.style.color = getComputedStyle(document.documentElement).getPropertyValue('--value-medium-text');} else if (tag.classList.contains('value-Low')) { tag.style.backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--value-low-bg'); tag.style.color = getComputedStyle(document.documentElement).getPropertyValue('--value-low-text');} }); const opt = { margin: [0.5, 0.4, 0.5, 0.4], filename: `WorkHour_Optimization_Dashboard_${analysisStartDate}_to_${analysisEndDate}.pdf`, image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, useCORS: true, logging: false, scrollX:0, scrollY: -window.scrollY, windowWidth: pdfContainer.scrollWidth + 100 }, // Ensure content fits jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }, pagebreak: { mode: ['avoid-all', 'css', 'legacy'] } }; html2pdf().from(pdfContainer).set(opt).save().then(() => { pdfContainer.innerHTML = ''; }).catch(err => { console.error("Error generating PDF:", err); pdfContainer.innerHTML = ''; alert("An error occurred while generating the PDF. Check console for details."); }); }
    Scroll to Top