Personal Unproductive Activity Logger
Personal Unproductive Activity Logger & Analyzer

Define Unproductive Activity Categories


Log an Unproductive Activity

Filter & Review Logged Activities

Detailed Log of Unproductive Activities

DateStartEndDurationCategoryDescriptionAffected TaskActions

Total Unproductive Time Logged: ${pual_formatDurationForDisplay(totalUnproductiveMinutes)}

`; html += '

Time by Category:

'; const sortedCategories = Object.entries(timeByCategory).sort(([,a],[,b]) => b-a); if(sortedCategories.length > 0) { const maxCatTime = sortedCategories.length > 0 ? sortedCategories[0][1] : 1; sortedCategories.forEach(([cat, mins]) => { const percentage = maxCatTime > 0 ? Math.max(5, (mins / maxCatTime * 100)) : 5; // Min 5% width for visibility html += `
${cat} (${pual_formatDurationForDisplay(mins)})
${pual_formatDurationForDisplay(mins)}
`; }); } else { html += "

No time logged with duration.

"; } html += '
'; html += '

Most Frequent Activities:

    '; const sortedActivities = Object.entries(activityCounts).sort(([,a],[,b]) => b-a).slice(0,5); // Top 5 if(sortedActivities.length > 0){ sortedActivities.forEach(([desc, count]) => { html += `
  • ${desc}: ${count} times
  • `; }); } else { html += "
  • No specific activities logged.
  • "; } html += '
'; resultsDiv.innerHTML = html; } // --- PDF and Clear All --- function pual_clearAllLogData() { if (confirm("Are you sure you want to clear ALL logged unproductive activities? Categories will remain.")) { pual_loggedActivities = []; pual_logIdCounter = 0; pual_editLogId = null; // Clear any edit state pual_clearLogForm(); // Reset form on tab 1 pual_applyFiltersAndAnalyze(); // Re-renders empty log and analytics } } function pual_downloadPDF() { if (!tpc_jsPDF_loaded_PUAL || !tpc_autoTable_loaded_PUAL) { alert("PUAL Error: PDF libraries not loaded."); return; } const fromDateStr = document.getElementById('pual-filter-from-date').value; const toDateStr = document.getElementById('pual-filter-to-date').value; const catFilter = document.getElementById('pual-filter-category').value; const activityFilter = document.getElementById('pual-filter-activity').value.toLowerCase(); const fromDate = fromDateStr ? new Date(fromDateStr + "T00:00:00") : null; const toDate = toDateStr ? new Date(toDateStr + "T23:59:59") : null; const dataForPdf = pual_loggedActivities.filter(entry => { const entryDate = new Date(`${entry.date}T${entry.startTime}`); if (fromDate && entryDate < fromDate) return false; if (toDate && entryDate > toDate) return false; if (catFilter && entry.categoryId !== catFilter) return false; if (activityFilter && !entry.description.toLowerCase().includes(activityFilter)) return false; return true; }); if (dataForPdf.length === 0) { alert("No log entries (matching current filters) to export."); return; } const doc = new TPC_jsPDF_PUAL(); const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const darkColor = getComputedStyle(document.documentElement).getPropertyValue('--dark-color').trim(); let finalY = 15; const reportDateStr = new Date().toLocaleDateString(); doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text("Personal Unproductive Activity Report", doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center' }); finalY += 8; doc.setFontSize(10); doc.setTextColor(darkColor); doc.text(`Report Date: ${reportDateStr}`, doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center'}); let filterText = `Filters: Period: ${fromDateStr || 'Any'} to ${toDateStr || 'Any'}. `; if(catFilter) filterText += `Category: ${pual_unproductiveCategories.find(c=>c.id === catFilter)?.name || 'N/A'}. `; if(activityFilter) filterText += `Activity Desc Contains: "${activityFilter}".`; finalY += 5; doc.text(filterText, 14, finalY, {maxWidth: doc.internal.pageSize.getWidth() - 28}); finalY += 10; let totalUnproductiveMinutes = 0; const timeByCategory = {}; dataForPdf.forEach(entry => { if (entry.durationMinutes !== null) { totalUnproductiveMinutes += entry.durationMinutes; timeByCategory[entry.categoryName] = (timeByCategory[entry.categoryName] || 0) + entry.durationMinutes; } }); doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text("Summary:", 14, finalY); finalY += 6; doc.setFontSize(9); doc.setTextColor(darkColor); doc.text(`Total Unproductive Time (in filtered log): ${pual_formatDurationForDisplay(totalUnproductiveMinutes)} from ${dataForPdf.length} entries.`, 14, finalY); finalY +=5; if(Object.keys(timeByCategory).length > 0){ finalY = doc.autoTable({ startY: finalY, head: [['Unproductive Category', 'Total Time Spent']], body: Object.entries(timeByCategory).map(([cat, mins]) => [cat, pual_formatDurationForDisplay(mins)]), theme: 'striped', headStyles: {fillColor:primaryColor, textColor:'#fff', fontSize:9}, styles:{fontSize:8, cellPadding:1.5}, margin: {left: 14, right: 14} }).finalY + 7; } doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text("Detailed Log:", 14, finalY); finalY += 6; const tableBody = dataForPdf.map(entry => [ entry.date ? new Date(entry.date+"T00:00:00Z").toLocaleDateString(undefined,{timeZone:'UTC'}) : 'N/A', entry.startTime, entry.endTime, pual_formatDurationForDisplay(entry.durationMinutes), entry.categoryName, entry.description, entry.affectedTask || '-' ]); doc.autoTable({ startY: finalY, head: [['Date', 'Start', 'End', 'Duration', 'Category', 'Description', 'Affected Task']], body: tableBody, theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff', fontSize: 9 }, styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' } }); doc.save(`Unproductive_Activity_Report_${new Date().toISOString().slice(0,10)}.pdf`); }
Scroll to Top