';
}
pwhaAnalysisResultsEl.style.display = 'block';
pwhaDownloadPdfBtn.style.display = 'block';
}
// --- PDF Export ---
function handlePdfDownload() {
const periodType = pwhaAnalysisPeriodSelectEl.value;
const selectedDateForContextKey = pwhaSelectedLogDateInput.value;
if (!selectedDateForContextKey) { alert("Please select a date for context."); return; }
const contextDate = new Date(selectedDateForContextKey + "T00:00:00Z");
let startDate, endDate;
let periodDisplayStrFull = "";
if (periodType === "selected_day") { /* ... same logic as pwhaRunAnalysis ... */
startDate = new Date(contextDate); endDate = new Date(contextDate);
periodDisplayStrFull = `Day: ${pwhaFormatDisplayDate(selectedDateForContextKey)}`;
} else if (periodType === "current_week") {
startDate = new Date(contextDate);
const dayOfWeek = startDate.getUTCDay(); const diffToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
startDate.setUTCDate(startDate.getUTCDate() + diffToMonday);
endDate = new Date(startDate); endDate.setUTCDate(startDate.getUTCDate() + 6);
periodDisplayStrFull = `Week: ${pwhaFormatDisplayDate(pwhaFormatDateKey(startDate))} to ${pwhaFormatDisplayDate(pwhaFormatDateKey(endDate))}`;
} else if (periodType === "current_month") {
startDate = new Date(Date.UTC(contextDate.getUTCFullYear(), contextDate.getUTCMonth(), 1));
endDate = new Date(Date.UTC(contextDate.getUTCFullYear(), contextDate.getUTCMonth() + 1, 0));
periodDisplayStrFull = `Month: ${contextDate.toLocaleDateString(undefined, { month: 'long', year: 'numeric' })}`;
}
const analysisData = { totalHours: 0, byCategory: {}, detailedLog: [] };
let currentDateIter = new Date(startDate);
while(currentDateIter <= endDate) { /* ... same data aggregation as pwhaRunAnalysis ... */
const dateKey = pwhaFormatDateKey(currentDateIter);
if (pwhaWorkLogEntries[dateKey]) {
pwhaWorkLogEntries[dateKey].forEach(entry => {
analysisData.totalHours += entry.durationHours;
const cat = pwhaSettings.categories.find(c => c.id === entry.categoryId) || {name: "Uncategorized", color:"#cccccc"};
if (!analysisData.byCategory[cat.name]) {
analysisData.byCategory[cat.name] = { hours: 0, color: cat.color };
}
analysisData.byCategory[cat.name].hours += entry.durationHours;
analysisData.detailedLog.push({...entry, date: dateKey, categoryName: cat.name});
});
}
currentDateIter.setUTCDate(currentDateIter.getUTCDate() + 1);
}
if(analysisData.totalHours === 0 && analysisData.detailedLog.length === 0) {
alert("No data to export for the selected period."); return;
}
const { jsPDF } = window.jspdf; // Local instance
const doc = new jsPDF();
doc.setFontSize(18);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--pwha-primary-color').trim());
doc.text("Personal Work-Hour Analysis", 14, 22);
doc.setFontSize(12);
doc.setTextColor(100);
doc.text(`Period: ${periodDisplayStrFull}`, 14, 30);
doc.text(`Total Hours Logged: ${analysisData.totalHours.toFixed(1)} hours`, 14, 38);
let yPos = 50;
doc.setFontSize(14);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--pwha-primary-color').trim());
doc.text("Time Distribution by Category:", 14, yPos);
yPos += 8;
const tableCategoryColumn = ["Category", "Hours Spent", "% of Total"];
const tableCategoryRows = [];
for (const catName in analysisData.byCategory) {
const catData = analysisData.byCategory[catName];
const percentage = analysisData.totalHours > 0 ? ((catData.hours / analysisData.totalHours) * 100).toFixed(1) : 0;
tableCategoryRows.push([catName, catData.hours.toFixed(1), percentage + "%"]);
}
tableCategoryRows.sort((a,b) => parseFloat(b[1]) - parseFloat(a[1])); // Sort by hours desc
doc.autoTable({
head: [tableCategoryColumn], body: tableCategoryRows, startY: yPos,
theme: 'striped', headStyles: { fillColor: getComputedStyle(document.documentElement).getPropertyValue('--pwha-secondary-color').trim() }
});
yPos = doc.lastAutoTable.finalY + 15;
if (analysisData.detailedLog.length > 0) {
if (yPos > 250) { doc.addPage(); yPos = 20; }
doc.setFontSize(14);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--pwha-primary-color').trim());
doc.text("Detailed Activities:", 14, yPos);
yPos += 8;
const tableDetailColumn = ["Date", "Activity", "Category", "Duration (h)", "Notes"];
const tableDetailRows = [];
analysisData.detailedLog.sort((a,b) => new Date(a.date + "T00:00:00Z") - new Date(b.date + "T00:00:00Z") );
analysisData.detailedLog.forEach(entry => {
tableDetailRows.push([
pwhaFormatDisplayDate(entry.date),
entry.description,
entry.categoryName,
entry.durationHours.toFixed(1),
entry.notes || ""
]);
});
doc.autoTable({
head: [tableDetailColumn], body: tableDetailRows, startY: yPos,
theme: 'grid', headStyles: { fillColor: getComputedStyle(document.documentElement).getPropertyValue('--pwha-secondary-color').trim() },
columnStyles: { 1: { cellWidth: 60 }, 4: { cellWidth: 'auto'} } // Activity desc, Notes auto
});
}
doc.save(`WorkHourAnalysis_${periodDisplayStrFull.replace(/[^a-zA-Z0-9]/g, '_')}.pdf`);
}
// --- Initialization ---
document.addEventListener('DOMContentLoaded', () => {
// Assign DOM elements
pwhaSelectedLogDateInput = document.getElementById('pwhaSelectedLogDate');
pwhaLogDateDisplay1El = document.getElementById('pwhaLogDateDisplay1');
pwhaLogDateDisplay2El = document.getElementById('pwhaLogDateDisplay2');
pwhaLoggedEntriesListEl = document.getElementById('pwhaLoggedEntriesList');
pwhaAddCategoryForm = document.getElementById('pwhaAddCategoryForm');
pwhaCategoryNameInput = document.getElementById('pwhaCategoryNameInput');
pwhaCategoryColorInput = document.getElementById('pwhaCategoryColorInput');
pwhaCategoriesListEl = document.getElementById('pwhaCategoriesList');
pwhaLogEntryModalEl = document.getElementById('pwhaLogEntryModal');
pwhaLogEntryModalTitleEl = document.getElementById('pwhaLogEntryModalTitle');
pwhaLogEntryForm = document.getElementById('pwhaLogEntryForm');
pwhaLogEntryIdInput = document.getElementById('pwhaLogEntryId');
pwhaLogEntryDateKeyInput = document.getElementById('pwhaLogEntryDateKey');
pwhaEntryDescriptionInput = document.getElementById('pwhaEntryDescription');
pwhaEntryCategorySelectEl = document.getElementById('pwhaEntryCategory');
pwhaEntryDurationInput = document.getElementById('pwhaEntryDuration');
pwhaEntryNotesInput = document.getElementById('pwhaEntryNotes');
pwhaAnalysisPeriodSelectEl = document.getElementById('pwhaAnalysisPeriodSelect');
pwhaAnalysisResultsEl = document.getElementById('pwhaAnalysisResults');
pwhaAnalysisPeriodDisplayEl = document.getElementById('pwhaAnalysisPeriodDisplay');
pwhaTotalHoursAnalyzedEl = document.getElementById('pwhaTotalHoursAnalyzed');
pwhaCategoryChartContainerEl = document.getElementById('pwhaCategoryChartContainer');
pwhaCategorySummaryTableBodyEl = document.querySelector('#pwhaCategorySummaryTable tbody');
pwhaDetailedLogForPeriodEl = document.getElementById('pwhaDetailedLogForPeriod');
pwhaDownloadPdfBtn = document.getElementById('pwhaDownloadPdfButton');
// Attach event listeners
if(pwhaAddCategoryForm) pwhaAddCategoryForm.addEventListener('submit', handleAddCategoryFormSubmit);
if(pwhaLogEntryForm) pwhaLogEntryForm.addEventListener('submit', pwhaLogEntryForm.onsubmit); // Check this, should be the function name directly
if(pwhaSelectedLogDateInput) pwhaSelectedLogDateInput.addEventListener('change', pwhaHandleLogDateChange);
// Analysis button is handled by its onclick in HTML directly, or add listener here if preferred.
if(pwhaDownloadPdfBtn) pwhaDownloadPdfBtn.addEventListener('click', handlePdfDownload);
// Set default date for log entry and load data
const today = new Date(2025, 4, 14); // May 14, 2025
if(pwhaSelectedLogDateInput) pwhaSelectedLogDateInput.value = pwhaFormatDateKey(today);
pwhaLoadData();
const firstTabButton = document.querySelector('#personalWorkHourAnalyzerTool .pwha-tab-button');
if (firstTabButton) {
firstTabButton.click();
}
window.addEventListener('click', function(event) {
if (event.target.classList.contains('pwha-modal')) {
pwhaCloseModal(event.target.id);
}
});
});