`;
// Insights on goals
if (ptosOptimizationPrefs.reduceActivities.length > 0) {
insightsHTML += `
Reducing Time:
You aim to reduce time on: ${ptosOptimizationPrefs.reduceActivities.map(ptosEscapeHtml).join(', ')}.
`;
ptosOptimizationPrefs.reduceActivities.forEach(item => {
const activityMatch = ptosActivities.find(a => a.name === item);
const categoryMatchTime = categoryTimesWeekly[item];
if (activityMatch) {
let weeklyH = activityMatch.timeSpent; if(activityMatch.timeUnit === 'hours_per_day') weeklyH *=7;
insightsHTML += `- The activity '${ptosEscapeHtml(item)}' currently takes about ${weeklyH.toFixed(1)} hours/week. What's one small change you could make to reduce this?
`;
} else if (categoryMatchTime !== undefined) {
insightsHTML += `- The category '${ptosEscapeHtml(item)}' currently takes about ${categoryMatchTime.toFixed(1)} hours/week. Which specific activities within this category could be optimized or reduced?
`;
} else {
insightsHTML += `- For '${ptosEscapeHtml(item)}', ensure it's logged in your time profile for accurate reflection.
`;
}
});
insightsHTML += `
`;
}
let allIncreaseGoals = [...ptosOptimizationPrefs.increaseActivities];
if(ptosOptimizationPrefs.newIncreaseActivity) allIncreaseGoals.push(ptosOptimizationPrefs.newIncreaseActivity + " (New)");
if (allIncreaseGoals.length > 0) {
insightsHTML += `
Increasing Time / New Activities:
You aim to increase time on or start: ${allIncreaseGoals.map(ptosEscapeHtml).join(', ')}.
`;
allIncreaseGoals.forEach(item => {
const isNew = item.endsWith(" (New)");
const cleanItem = isNew ? item.replace(" (New)","") : item;
const activityMatch = ptosActivities.find(a => a.name === cleanItem);
const categoryMatchTime = categoryTimesWeekly[cleanItem];
if (activityMatch) {
let weeklyH = activityMatch.timeSpent; if(activityMatch.timeUnit === 'hours_per_day') weeklyH *=7;
insightsHTML += `- For '${ptosEscapeHtml(cleanItem)}' (currently ${weeklyH.toFixed(1)} hrs/week), how much more time would be ideal, and where could it come from?
`;
} else if (categoryMatchTime !== undefined) {
insightsHTML += `- For the category '${ptosEscapeHtml(cleanItem)}' (currently ${categoryMatchTime.toFixed(1)} hrs/week), which specific activities deserve more focus?
`;
} else {
insightsHTML += `- For '${ptosEscapeHtml(cleanItem)}'${isNew ? "" : " (not currently logged)"}, how much time do you envision allocating per week, and what existing activities might need to be adjusted to make space?
`;
}
});
insightsHTML += `
`;
}
// Distractions
let allDistractions = [...ptosOptimizationPrefs.identifiedDistractions];
if (ptosOptimizationPrefs.otherDistraction) allDistractions.push(ptosOptimizationPrefs.otherDistraction + " (Custom)");
const distractionTime = categoryTimesWeekly['Distractions'] || 0;
if (allDistractions.length > 0 || distractionTime > 0) {
insightsHTML += `
Addressing Distractions:
`;
if (distractionTime > 0) {
insightsHTML += `
Your log shows about ${distractionTime.toFixed(1)} hours/week (${(distractionTime / totalLoggedWeeklyHours * 100).toFixed(1)}%) on activities categorized as 'Distractions'.
`;
}
if (allDistractions.length > 0) {
insightsHTML += `
You've identified these as areas of concern: ${allDistractions.map(ptosEscapeHtml).join(', ')}.
- Consider for each: What are the common triggers? When do they most often occur?
- What's one strategy you could try to minimize one of these this week (e.g., time blocking for focus, turning off notifications, specific 'no-[distraction]' periods)?
`;
}
insightsHTML += `
`;
}
// Generic Suggestion Prompts
insightsHTML += `
General Reflection Prompts:
`;
if (categoryTimesWeekly['Essential Admin/Chores'] > 0) {
insightsHTML += `- Activities in 'Essential Admin/Chores' take up ${categoryTimesWeekly['Essential Admin/Chores'].toFixed(1)} hrs/week. Could any of these be batched or streamlined (e.g., processing emails at set times, grouping similar errands)?
`;
}
if (categoryTimesWeekly['Productive Focus'] > 0) {
insightsHTML += `- For your 'Productive Focus' activities (${categoryTimesWeekly['Productive Focus'].toFixed(1)} hrs/week), are there ways to protect this time further? Some find techniques like the Pomodoro (focused intervals) or time blocking for key tasks helpful.
`;
}
insightsHTML += `- Are there any tasks you are doing that could potentially be delegated or automated?
`;
insightsHTML += `- When do you feel most energetic and focused during your day/week? How could you align your most important tasks with these 'prime time' periods?
`;
insightsHTML += `
`;
ptosInsightsAreaEl.innerHTML = insightsHTML;
}
function ptosEscapeHtml(unsafe) {
if (typeof unsafe !== 'string') return '';
return unsafe.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'");
}
// PDF Download
function ptosDownloadPDF() {
if (ptosInsightsAreaEl.style.display === 'none' || ptosInsightsAreaEl.innerHTML.trim() === '') {
alert("Please generate insights first."); return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF('p', 'pt', 'a4');
const primaryColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--ptos-primary-color').trim();
const accentColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--ptos-accent-color').trim();
const textColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--ptos-text-color-dark').trim();
let yPos = 40;
const leftMargin = 40;
const contentWidth = doc.internal.pageSize.getWidth() - (2 * leftMargin);
const lineSpacing = 14;
doc.setFontSize(18); doc.setTextColor(primaryColorPDF);
doc.text("Personalized Time Optimization Insights", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' });
yPos += 25;
doc.setFontSize(10); doc.setTextColor(textColorPDF);
doc.text(`Report Generated: ${new Date().toLocaleDateString()}`, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' });
yPos += 30;
function addPdfSection(title, contentArray, isList = false) {
if (!contentArray || contentArray.length === 0) return;
yPos = checkPdfPageBreak(doc, yPos, 30 + lineSpacing);
doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(primaryColorPDF);
doc.text(title, leftMargin, yPos); yPos += lineSpacing * 1.2;
doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.setTextColor(textColorPDF);
contentArray.forEach(item => {
const prefix = isList ? "- " : "";
const lines = doc.splitTextToSize(prefix + item, contentWidth - (isList ? 10 : 0) ); // Indent list items
lines.forEach(line => {
yPos = checkPdfPageBreak(doc, yPos, lineSpacing);
doc.text(line, leftMargin + (isList ? 10 : 0), yPos);
yPos += lineSpacing;
});
});
yPos += lineSpacing * 0.5;
}
// 1. Time Profile Summary
const categoryTimesWeekly = {}; let totalLoggedWeeklyHours = 0;
ptosActivities.forEach(act => {
let weeklyHours = act.timeSpent; if (act.timeUnit === 'hours_per_day') weeklyHours *= 7;
categoryTimesWeekly[act.category] = (categoryTimesWeekly[act.category] || 0) + weeklyHours;
totalLoggedWeeklyHours += weeklyHours;
});
let timeProfileContent = [`Total time logged: ${totalLoggedWeeklyHours.toFixed(1)} hours/week.`];
for (const cat in categoryTimesWeekly) {
const percent = totalLoggedWeeklyHours > 0 ? (categoryTimesWeekly[cat] / totalLoggedWeeklyHours * 100).toFixed(1) : 0;
timeProfileContent.push(`${ptosEscapeHtml(cat)}: ${categoryTimesWeekly[cat].toFixed(1)} hours (${percent}%)`);
}
addPdfSection("Your Current Time Profile (Estimated Weekly):", timeProfileContent, true);
// 2. Optimization Goals
let goalsContent = [];
if(ptosOptimizationPrefs.reduceActivities.length > 0) goalsContent.push(`Aim to reduce time on: ${ptosOptimizationPrefs.reduceActivities.map(ptosEscapeHtml).join(', ')}.`);
let allIncreaseGoals = [...ptosOptimizationPrefs.increaseActivities];
if(ptosOptimizationPrefs.newIncreaseActivity) allIncreaseGoals.push(ptosOptimizationPrefs.newIncreaseActivity + " (New)");
if(allIncreaseGoals.length > 0) goalsContent.push(`Aim to increase time on/start: ${allIncreaseGoals.map(ptosEscapeHtml).join(', ')}.`);
let allDistractions = [...ptosOptimizationPrefs.identifiedDistractions];
if (ptosOptimizationPrefs.otherDistraction) allDistractions.push(ptosOptimizationPrefs.otherDistraction + " (Custom)");
if(allDistractions.length > 0) goalsContent.push(`Distractions to address: ${allDistractions.map(ptosEscapeHtml).join(', ')}.`);
if(goalsContent.length > 0) addPdfSection("Your Optimization Goals:", goalsContent, true);
// 3. Insights (Extract from HTML for simplicity, or re-generate text)
// For simplicity, let's just put a placeholder here. Ideally, regenerate text for PDF.
yPos = checkPdfPageBreak(doc, yPos, 30 + lineSpacing);
doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(primaryColorPDF);
doc.text("Insights & Reflection Prompts:", leftMargin, yPos); yPos += lineSpacing * 1.2;
doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.setTextColor(textColorPDF);
const insightItems = ptosInsightsAreaEl.querySelectorAll('.ptos-insight-item');
insightItems.forEach(item => {
const titleEl = item.querySelector('h4');
if (titleEl) {
yPos = checkPdfPageBreak(doc, yPos, lineSpacing * 1.5);
doc.setFont(undefined, 'bold');
const titleLines = doc.splitTextToSize(titleEl.textContent, contentWidth);
doc.text(titleLines, leftMargin, yPos);
yPos += titleLines.length * lineSpacing;
doc.setFont(undefined, 'normal');
}
item.querySelectorAll('p, li').forEach(pOrLi => {
const textLines = doc.splitTextToSize(pOrLi.textContent, contentWidth - (pOrLi.tagName === 'LI' ? 10 : 0));
lines.forEach(line => {
yPos = checkPdfPageBreak(doc, yPos, lineSpacing);
doc.text(line, leftMargin + (pOrLi.tagName === 'LI' ? 10 : 0), yPos);
yPos += lineSpacing;
});
});
yPos += lineSpacing * 0.5; // Space after each insight item
});
doc.save("Time_Optimization_Insights.pdf");
}
function checkPdfPageBreak(doc, currentY, spaceNeeded) {
if (currentY + spaceNeeded > doc.internal.pageSize.getHeight() - 40) {
doc.addPage(); return 40;
}
return currentY;
}