No logs available or found for the selected date range. Please add logs in Tab 1.
';
const dashboardDisplayEl = document.getElementById('shpi-dashboard-display');
const insightsListEl = document.getElementById('shpi-insights-list');
const avgSummaryEl = document.getElementById('shpi-average-summary-list');
if (shpiSessionLogs.length === 0 && shpiCurrentTabIndex === 1) {
if(dashboardDisplayEl) dashboardDisplayEl.innerHTML = noDataMsg;
if(insightsListEl) insightsListEl.innerHTML = '
No data to analyze.';
if(avgSummaryEl) avgSummaryEl.innerHTML = '
No data for averages.';
Object.values(shpiChartInstances).forEach(chart => chart ? chart.destroy() : null);
return;
}
const startDateStr = document.getElementById('shpi-analysis-start-date').value;
const endDateStr = document.getElementById('shpi-analysis-end-date').value;
if(!startDateStr || !endDateStr) return;
const startDate = new Date(startDateStr + "T00:00:00");
const endDate = new Date(endDateStr + "T23:59:59");
const filteredLogs = shpiSessionLogs.filter(log => log.date >= startDate && log.date <= endDate);
if (filteredLogs.length === 0 && shpiCurrentTabIndex === 1) {
if(dashboardDisplayEl) dashboardDisplayEl.innerHTML = noDataMsg;
if(insightsListEl) insightsListEl.innerHTML = '
No data in selected range for insights.';
if(avgSummaryEl) avgSummaryEl.innerHTML = '
No data in range for averages.';
Object.values(shpiChartInstances).forEach(chart => chart ? chart.destroy() : null);
return;
}
// Calculate Averages
if(avgSummaryEl){
if(filteredLogs.length > 0){
const calcAvg = (key) => filteredLogs.reduce((s,l)=>s+l[key],0)/filteredLogs.length;
avgSummaryEl.innerHTML = `
Avg. Sleep: ${calcAvg('sleepHours').toFixed(1)}h (Quality: ${calcAvg('sleepQuality').toFixed(1)}/5)
Avg. Mood: ${calcAvg('mood').toFixed(1)}/5 | Avg. Stress: ${calcAvg('stressLevel').toFixed(1)}/5 | Avg. Energy: ${calcAvg('energyLevel').toFixed(1)}/5
Avg. Tasks Completed: ${calcAvg('tasksCompleted').toFixed(1)}
Avg. Productivity: ${calcAvg('productivity').toFixed(1)}/5 | Avg. Focus: ${calcAvg('focus').toFixed(1)}/5
Avg. Physical Activity: ${calcAvg('physicalActivity').toFixed(1)} min
`;
} else { avgSummaryEl.innerHTML = '
No data in range for averages.'; }
}
// Prepare chart data
const chartData = (key) => filteredLogs.map(log => ({x: log.date, y: log[key]}));
if(dashboardDisplayEl) dashboardDisplayEl.innerHTML = `
Sleep Duration & Quality
Mood Over Time
Stress Level Over Time
Energy Level Over Time
Productivity Rating Over Time
Focus Level Over Time
Physical Activity (min)
`;
// Render Charts
shpiRenderLineChart('shpi-mood-chart', chartData('mood'), 'Mood (1-5)', 'var(--success-color)', 5);
shpiRenderLineChart('shpi-stress-chart', chartData('stressLevel'), 'Stress (1-5)', 'var(--danger-color)', 5);
shpiRenderLineChart('shpi-energy-chart', chartData('energyLevel'), 'Energy (1-5)', 'var(--accent-color)', 5);
shpiRenderLineChart('shpi-productivity-chart', chartData('productivity'), 'Productivity (1-5)', 'var(--primary-color)', 5);
shpiRenderLineChart('shpi-focus-chart', chartData('focus'), 'Focus (1-5)', 'var(--dark-color)', 5);
shpiRenderLineChart('shpi-activity-chart', chartData('physicalActivity'), 'Physical Activity (min)', 'var(--secondary-color)');
const sleepQualityData = filteredLogs.map(log => ({x: log.date, y: log.sleepQuality}));
const sleepHoursData = filteredLogs.map(log => ({x: log.date, y: log.sleepHours}));
const sleepCtx = document.getElementById('shpi-sleep-chart');
if (sleepCtx) {
if (shpiChartInstances['shpi-sleep-chart']) shpiChartInstances['shpi-sleep-chart'].destroy();
shpiChartInstances['shpi-sleep-chart'] = new Chart(sleepCtx.getContext('2d'), {
type: 'line', data: {
datasets: [
{ label: 'Sleep Quality (1-5)', data: sleepQualityData, borderColor: 'var(--primary-color)', yAxisID: 'yQuality', tension: 0.1 },
{ label: 'Sleep Hours', data: sleepHoursData, borderColor: 'var(--accent-color)', yAxisID: 'yHours', tension: 0.1 }
]},
options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false },
scales: {
x: { type: 'time', time: { unit: 'day', tooltipFormat: 'MMM dd, yy' } },
yQuality: { type: 'linear', position: 'left', min:0, max:5, title:{display:true, text:'Quality (1-5)'} },
yHours: { type: 'linear', position: 'right', min:0, title:{display:true, text:'Hours'}, grid: { drawOnChartArea: false } }
}
}
});
}
// Generate Insights
if(insightsListEl){
insightsListEl.innerHTML = ''; let insightsGeneratedCount = 0;
if (filteredLogs.length >= 5) { // Need some data for robust insights
// Simple correlation: Sleep Quality vs Next Day Mood
let goodSleepGoodMoodCount = 0; let lowSleepLowMoodCount = 0;
for(let i=0; i < filteredLogs.length -1; i++){
if(filteredLogs[i].sleepQuality >=4 && filteredLogs[i+1].mood >=4) goodSleepGoodMoodCount++;
if(filteredLogs[i].sleepQuality <=2 && filteredLogs[i+1].mood <=2) lowSleepLowMoodCount++;
}
if(goodSleepGoodMoodCount > filteredLogs.length / 4) { insightsListEl.innerHTML += `
Good sleep quality often seems to lead to a better mood the next day for you. Prioritize restful sleep!`; insightsGeneratedCount++;}
if(lowSleepLowMoodCount > filteredLogs.length / 4) { insightsListEl.innerHTML += `
Poor sleep quality frequently appears to impact your mood negatively the following day. Focus on improving sleep hygiene.`; insightsGeneratedCount++;}
const avgTasksOnActiveDays = filteredLogs.filter(l => l.physicalActivity > 0).reduce((s,l,_,a)=>s+l.tasksCompleted/a.length,0);
const avgTasksOnInactiveDays = filteredLogs.filter(l => l.physicalActivity === 0).reduce((s,l,_,a)=>s+l.tasksCompleted/a.length,0);
if(filteredLogs.filter(l=>l.physicalActivity > 0).length > 2 && filteredLogs.filter(l=>l.physicalActivity === 0).length > 2 && avgTasksOnActiveDays > avgTasksOnInactiveDays * 1.1){
insightsListEl.innerHTML += `
You tend to complete more tasks on days you engage in physical activity. Even short bursts of exercise can help!`; insightsGeneratedCount++;
}
const highStressDays = filteredLogs.filter(l => l.stressLevel >=4);
if(highStressDays.length > filteredLogs.length / 3){
const avgFocusOnHighStress = highStressDays.reduce((s,l)=>s+l.focus,0) / highStressDays.length;
const avgFocusOverall = filteredLogs.reduce((s,l)=>s+l.focus,0) / filteredLogs.length;
if(avgFocusOnHighStress < avgFocusOverall * 0.8) {insightsListEl.innerHTML += `
High stress days show a noticeable drop in your average focus level. Consider stress-reduction techniques on demanding days.`; insightsGeneratedCount++;}
}
}
if(insightsGeneratedCount === 0 && filteredLogs.length > 0) insightsListEl.innerHTML += `
Consistent logging will reveal more personalized insights. Pay attention to how different factors influence each other in your charts.`;
else if (filteredLogs.length === 0) insightsListEl.innerHTML += `
No data in selected range to provide insights.`;
}
}
function shpiRenderLineChart(canvasId, dataPoints, label, color, suggestedMax = undefined) {
const ctx = document.getElementById(canvasId);
if (!ctx) return;
if (shpiChartInstances[canvasId]) shpiChartInstances[canvasId].destroy();
shpiChartInstances[canvasId] = new Chart(ctx.getContext('2d'), {
type: 'line',
data: { datasets: [{ label: label, data: dataPoints, borderColor: color, tension: 0.1, fill: false, borderWidth: 2 }] },
options: {
responsive: true, maintainAspectRatio: false,
scales: { x: { type: 'time', time: { unit: 'day', tooltipFormat: 'MMM dd, yy', displayFormats: {'day': 'MMM dd'} } },
y: { beginAtZero: false, suggestedMin:1, suggestedMax: suggestedMax, title: {display:true, text:label.split('(')[0].trim()}} }
}
});
}
// PDF Download
function shpiDownloadPDF() {
const dashboardDisplayEl = document.getElementById('shpi-dashboard-display');
if (!dashboardDisplayEl || dashboardDisplayEl.innerHTML.includes("Log daily data") || shpiSessionLogs.length === 0) {
alert("Please log some data and view the dashboard first."); return;
}
const analysisStartDate = document.getElementById('shpi-analysis-start-date').value;
const analysisEndDate = document.getElementById('shpi-analysis-end-date').value;
let pdfHTML = `
Healthy Productivity Insights Report
`;
pdfHTML += `
Analysis Period: ${analysisStartDate} to ${analysisEndDate}
`;
const avgSummaryContent = document.getElementById('shpi-average-summary-list').outerHTML;
if(avgSummaryContent) pdfHTML += `
Overall Averages (Selected Period)
${avgSummaryContent}`;
const chartsToInclude = [
{instance: shpiChartInstances['shpi-sleep-chart'], title: "Sleep Duration & Quality"},
{instance: shpiChartInstances['shpi-mood-chart'], title: "Mood Over Time"},
{instance: shpiChartInstances['shpi-stress-chart'], title: "Stress Level Over Time"},
{instance: shpiChartInstances['shpi-energy-chart'], title: "Energy Level Over Time"},
{instance: shpiChartInstances['shpi-productivity-chart'], title: "Productivity Rating Over Time"},
{instance: shpiChartInstances['shpi-focus-chart'], title: "Focus Level Over Time"},
{instance: shpiChartInstances['shpi-activity-chart'], title: "Physical Activity (min)"}
];
chartsToInclude.forEach(chartInfo => {
if(chartInfo.instance){
try { // Adding a border to charts in PDF for better visual separation
pdfHTML += `
${chartInfo.title}
`;
} catch (e) { console.error("Error converting chart to image for PDF: ", chartInfo.title, e); }
}
});
const insightsContent = document.getElementById('shpi-insights-list').outerHTML;
if(insightsContent) pdfHTML += `
"Smart" Insights & Recommendations
${insightsContent}`;
const filteredLogsForPDF = shpiSessionLogs.filter(log => {
const logDateOnly = log.date.toISOString().split('T')[0];
return logDateOnly >= analysisStartDate && logDateOnly <= analysisEndDate;
});
if (filteredLogsForPDF.length > 0 && confirm("Include detailed daily logs in PDF? This can make the PDF long.")) {
pdfHTML += `
Detailed Logs (${analysisStartDate} to ${analysisEndDate})
`;
pdfHTML += `
| Date | Sleep(H) | Sleep(Q) | Stress | Mood | Energy | Activity(m) | Tasks | Productivity | Focus | Notes |
`;
filteredLogsForPDF.forEach(log => {
pdfHTML += `
| ${log.date.toLocaleDateString()} | ${log.sleepHours.toFixed(1)} | ${log.sleepQuality} |
${log.stressLevel} | ${log.mood} | ${log.energyLevel} | ${log.physicalActivity} |
${log.tasksCompleted} | ${log.productivity} | ${log.focus} |
${log.notes.substring(0,50)}${log.notes.length > 50 ? '...' : ''} |
`;
});
pdfHTML += `
`;
}
const pdfContainer = document.getElementById('shpi-report-content-for-pdf');
pdfContainer.innerHTML = pdfHTML;
const opt = {
margin: [0.5, 0.4, 0.5, 0.4], filename: `Healthy_Productivity_Insights_${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 },
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.");
});
}