`;
summaryHTML += `
Total Leisure Time: ${wlttFormatDuration(totalLeisureMins)}
`;
summaryHTML += `
Total Logged: ${wlttFormatDuration(totalLoggedMins)}
`;
summaryHTML += `
${workPercent > 10 ? 'Work ' + workPercent.toFixed(1)+'%' : ''}
${leisurePercent > 10 ? 'Leisure ' + leisurePercent.toFixed(1)+'%' : ''}
`;
summaryHTML += `
Time by Category:
`;
for (const category in categoryTimes) {
const catData = categoryTimes[category];
summaryHTML += `- ${category}: ${wlttFormatDuration(catData.total)}
(${catData.work > 0 ? `W: ${wlttFormatDuration(catData.work)}` : ''} ${catData.leisure > 0 ? (catData.work > 0 ? ', ': '') + `L: ${wlttFormatDuration(catData.leisure)}` : ''})
`;
}
summaryHTML += `
`;
summaryHTML += `
Detailed Activity Log:
`;
activitiesForDate.sort((a,b) => new Date(a.startTime) - new Date(b.startTime)).forEach(act => {
const start = new Date(act.startTime).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});
const end = new Date(act.endTime).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});
summaryHTML += `- ${act.name} (${act.category} - ${act.type})
${start} - ${end} (${wlttFormatDuration(act.durationMinutes)}) `;
});
summaryHTML += `
`;
reportArea.innerHTML = summaryHTML;
reportArea.style.display = 'block';
reflectionArea.style.display = 'block';
if(pdfBtn) pdfBtn.style.display = 'inline-block';
}
function wlttDownloadPDF() {
if (!jsPDF_constructor_wltt) { alert("PDF library error. Cannot generate PDF."); return; }
const activitiesForDate = wlttTimeTrackerData.activities.filter(act =>
new Date(act.startTime).toISOString().split('T')[0] === wlttTimeTrackerData.trackingDate
);
if (activitiesForDate.length === 0 && !document.getElementById('wltt-daily-reflection').value.trim()) {
alert("No data to download. Please log activities or add a reflection."); return;
}
wlttTimeTrackerData.dailyReflection = document.getElementById('wltt-daily-reflection').value.trim();
const doc = new jsPDF_constructor_wltt('p', 'pt', 'a4');
const FONT_FAMILY = "helvetica";
const ACCENT_COLOR_HEX = getComputedStyle(document.documentElement).getPropertyValue('--accent-color').trim();
const PRIMARY_TEXT_COLOR_HEX = getComputedStyle(document.documentElement).getPropertyValue('--primary-text').trim();
const SECTION_TITLE_COLOR_HEX = getComputedStyle(document.documentElement).getPropertyValue('--section-title-color').trim();
const BUTTON_TEXT_COLOR_HEX = getComputedStyle(document.documentElement).getPropertyValue('--button-text-color').trim();
const WORK_PDF_COLOR = getComputedStyle(document.documentElement).getPropertyValue('--work-color').trim();
const LEISURE_PDF_COLOR = getComputedStyle(document.documentElement).getPropertyValue('--leisure-color').trim();
let yPos = 40;
const pageWidth = doc.internal.pageSize.getWidth();
const margin = 40;
const usableWidth = pageWidth - (2 * margin);
doc.setFillColor(ACCENT_COLOR_HEX);
doc.rect(0, 0, pageWidth, yPos + 10, 'F');
doc.setFont(FONT_FAMILY, "bold"); doc.setFontSize(16); doc.setTextColor(BUTTON_TEXT_COLOR_HEX);
doc.text("Daily Time Log & Work-Leisure Balance", pageWidth / 2, yPos, { align: "center" });
yPos += 25;
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(10); doc.setTextColor(PRIMARY_TEXT_COLOR_HEX);
const loggedDateFormatted = new Date(wlttTimeTrackerData.trackingDate+'T00:00:00').toLocaleDateString(undefined, { weekday:'long', year: 'numeric', month: 'long', day: 'numeric' });
doc.text(`Log for Date: ${loggedDateFormatted}`, margin, yPos);
const genDate = new Date(2025, 4, 18).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' }); // Context date
doc.text(`Report Generated: ${genDate}`, pageWidth - margin, yPos, { align: 'right'});
yPos += 25;
let totalWorkMins = 0, totalLeisureMins = 0;
let categoryTimes = {};
activitiesForDate.forEach(act => {
if (act.type === "Work") totalWorkMins += act.durationMinutes;
else totalLeisureMins += act.durationMinutes;
if (!categoryTimes[act.category]) categoryTimes[act.category] = { work: 0, leisure: 0, total: 0 };
categoryTimes[act.category].total += act.durationMinutes;
if (act.type === "Work") categoryTimes[act.category].work += act.durationMinutes;
else categoryTimes[act.category].leisure += act.durationMinutes;
});
const totalLoggedMins = totalWorkMins + totalLeisureMins;
const workPercent = totalLoggedMins > 0 ? (totalWorkMins / totalLoggedMins * 100) : 0;
const leisurePercent = totalLoggedMins > 0 ? (totalLeisureMins / totalLoggedMins * 100) : 0;
doc.setFont(FONT_FAMILY, "bold"); doc.setFontSize(12); doc.setTextColor(SECTION_TITLE_COLOR_HEX);
doc.text("Overall Summary:", margin, yPos); yPos += 18;
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(10);
doc.text(`Total Work Time: ${wlttFormatDuration(totalWorkMins)} (${workPercent.toFixed(1)}%)`, margin, yPos); yPos += 14;
doc.text(`Total Leisure Time: ${wlttFormatDuration(totalLeisureMins)} (${leisurePercent.toFixed(1)}%)`, margin, yPos); yPos += 14;
doc.text(`Total Logged Time: ${wlttFormatDuration(totalLoggedMins)}`, margin, yPos); yPos += 20;
// Time by Category
if (yPos > doc.internal.pageSize.getHeight() - 80) { doc.addPage(); yPos = margin; }
doc.setFont(FONT_FAMILY, "bold"); doc.setFontSize(12); doc.setTextColor(SECTION_TITLE_COLOR_HEX);
doc.text("Time Allocation by Category:", margin, yPos); yPos += 18;
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(9);
if (Object.keys(categoryTimes).length > 0) {
for (const category in categoryTimes) {
if (yPos > doc.internal.pageSize.getHeight() - 25) { doc.addPage(); yPos = margin; }
const catData = categoryTimes[category];
let typeBreakdown = "";
if (catData.work > 0) typeBreakdown += `Work: ${wlttFormatDuration(catData.work)}`;
if (catData.leisure > 0) typeBreakdown += `${catData.work > 0 ? ', ' : ''}Leisure: ${wlttFormatDuration(catData.leisure)}`;
doc.text(`• ${category}: ${wlttFormatDuration(catData.total)} ${typeBreakdown ? `(${typeBreakdown})` : ''}`, margin + 10, yPos);
yPos += 12;
}
} else {
doc.text("No categories logged.", margin + 10, yPos); yPos += 12;
}
yPos += 10;
// Detailed Activity Log
if (yPos > doc.internal.pageSize.getHeight() - 60) { doc.addPage(); yPos = margin; }
doc.setFont(FONT_FAMILY, "bold"); doc.setFontSize(12); doc.setTextColor(SECTION_TITLE_COLOR_HEX);
doc.text("Detailed Activity Log:", margin, yPos); yPos += 5;
if (jsPDF_autoTable_plugin_wltt && activitiesForDate.length > 0) {
const activityTableBody = activitiesForDate.sort((a,b) => new Date(a.startTime) - new Date(b.startTime)).map(act => [
act.name, act.category, act.type,
new Date(act.startTime).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'}),
new Date(act.endTime).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'}),
wlttFormatDuration(act.durationMinutes)
]);
doc.autoTable({
startY: yPos,
head: [['Activity', 'Category', 'Type', 'Start', 'End', 'Duration']],
body: activityTableBody, theme: 'grid', margin: {left: margin, right: margin},
headStyles: { fillColor: ACCENT_COLOR_HEX, textColor: BUTTON_TEXT_COLOR_HEX, fontSize: 8, fontStyle:'bold'},
styles: { fontSize: 8, cellPadding: 2, overflow: 'linebreak' },
didParseCell: function(data) { // Color Type column
if (data.section === 'body' && data.column.index === 2) { // Type column
if (data.cell.raw === "Work") data.cell.styles.textColor = WORK_PDF_COLOR;
else if (data.cell.raw === "Leisure") data.cell.styles.textColor = LEISURE_PDF_COLOR;
data.cell.styles.fontStyle = 'bold';
}
}
});
yPos = doc.lastAutoTable.finalY + 15;
} else if (activitiesForDate.length > 0) { // Fallback if no autoTable
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(8);
activitiesForDate.sort((a,b) => new Date(a.startTime) - new Date(b.startTime)).forEach(act => {
if (yPos > doc.internal.pageSize.getHeight() - 20) { doc.addPage(); yPos = margin; }
const start = new Date(act.startTime).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});
const end = new Date(act.endTime).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});
doc.text(`• ${act.name} (${act.category}/${act.type}) [${start}-${end}] - ${wlttFormatDuration(act.durationMinutes)}`, margin, yPos);
yPos += 10;
});
yPos += 5;
} else {
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(9);
doc.text("No activities logged for this day.", margin, yPos); yPos += 15;
}
if (wlttTimeTrackerData.dailyReflection) {
if (yPos > doc.internal.pageSize.getHeight() - 50) { doc.addPage(); yPos = margin; }
doc.setFont(FONT_FAMILY, "bold"); doc.setFontSize(12); doc.setTextColor(SECTION_TITLE_COLOR_HEX);
doc.text("Reflection on Time Allocation:", margin, yPos); yPos += 18;
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(10);
const reflectionLines = doc.splitTextToSize(wlttTimeTrackerData.dailyReflection, usableWidth);
doc.text(reflectionLines, margin, yPos);
yPos += (reflectionLines.length * 12) + 10;
}
// Footer
const pageCount = doc.internal.getNumberOfPages();
for (let i = 1; i <= pageCount; i++) {
doc.setPage(i);
const pageHeight = doc.internal.pageSize.getHeight();
doc.setLineWidth(0.5); doc.setDrawColor(ACCENT_COLOR_HEX);
doc.line(margin, pageHeight - 30, pageWidth - margin, pageHeight - 30);
doc.setFont(FONT_FAMILY, "normal"); doc.setFontSize(8); doc.setTextColor(PRIMARY_TEXT_COLOR_HEX);
doc.text(`Page ${i} of ${pageCount}`, pageWidth / 2, pageHeight - 20, { align: "center" });
}
doc.save(`Time_Log_Report_${wlttTimeTrackerData.trackingDate}.pdf`);
}