Set Weekly Goals & Tasks

Weekly Goals (Max 5)

    Tasks

    Weekly Schedule & Time Blocking

    Unscheduled Tasks

      Summary & Review for week of

      Goal Progress

      Time Allocation

      Weekly Reflection

      ×

      Create/Edit Time Block

      No goals set for the week.

      '; wpa_goals.forEach(goal => { const tasksForGoal = wpa_tasks.filter(t => t.goalId === goal.id); const completedTasks = tasksForGoal.filter(t => t.isDone).length; const item = document.createElement('div'); item.classList.add('wpa-summary-item'); item.innerHTML = `

      ${goal.name}

      Progress: ${completedTasks} / ${tasksForGoal.length} tasks completed.

      `; goalProgressDiv.appendChild(item); }); // Time Allocation const timeAllocDiv = document.getElementById('wpa-timeAllocationSummary'); timeAllocDiv.innerHTML = ''; const timePerGoal = {}; wpa_goals.forEach(g => timePerGoal[g.id] = { name: g.name, color: g.color, totalMinutes: 0 }); const timePerDay = {mon:0, tue:0, wed:0, thu:0, fri:0, sat:0, sun:0}; wpa_scheduledBlocks.forEach(block => { const durationMins = wpa_timeStringToMinutes(block.endTime) - wpa_timeStringToMinutes(block.startTime); if (block.type === 'task') { const task = wpa_tasks.find(t => t.id === block.contentId); if (task && task.goalId && timePerGoal[task.goalId]) { timePerGoal[task.goalId].totalMinutes += durationMins; } } const dayIdx = new Date(block.date+"T00:00:00").getDay(); // Sun=0, Mon=1... const dayKey = wpa_daysOfWeek[dayIdx === 0 ? 6 : dayIdx - 1]; if (timePerDay.hasOwnProperty(dayKey)) timePerDay[dayKey] += durationMins; }); const goalAllocItem = document.createElement('div'); goalAllocItem.classList.add('wpa-summary-item'); goalAllocItem.innerHTML = '

      Time Allocated per Goal

      '; const goalUl = document.createElement('ul'); for(const goalId in timePerGoal) { const goalData = timePerGoal[goalId]; goalUl.innerHTML += `
    • ${goalData.name}: ${Math.floor(goalData.totalMinutes/60)}h ${goalData.totalMinutes%60}m
    • `; } goalAllocItem.appendChild(goalUl); timeAllocDiv.appendChild(goalAllocItem); const dayAllocItem = document.createElement('div'); dayAllocItem.classList.add('wpa-summary-item'); dayAllocItem.innerHTML = '

      Time Allocated per Day

      '; const dayUl = document.createElement('ul'); wpa_daysOfWeek.forEach((dayKey, index) => { const totalMins = timePerDay[dayKey]; dayUl.innerHTML += `
    • ${wpa_dayNamesFull[index]}: ${Math.floor(totalMins/60)}h ${totalMins%60}m
    • `; }); dayAllocItem.appendChild(dayUl); timeAllocDiv.appendChild(dayAllocItem); } function wpa_saveReflection() { wpa_weeklyReflection = document.getElementById('wpa-weeklyReflectionNotes').value; wpa_saveData(); } // --- PDF Download --- document.getElementById('wpa-downloadPdfBtn').onclick = async () => { if (!wpa_weekToPlan) { alert("Please select a week to plan first."); return; } const { jsPDF } = window.jspdf; const pdf = new jsPDF('l', 'mm', 'a4'); // Landscape let currentY = 15; const margin = 10; const contentWidth = pdf.internal.pageSize.getWidth() - 2 * margin; const accentColor = '#2ECC71'; const textColor = '#34495E'; pdf.setFontSize(20); pdf.setTextColor(accentColor); pdf.text(`Weekly Plan: ${new Date(wpa_weekToPlan+"T00:00:00").toLocaleDateString()}`, pdf.internal.pageSize.getWidth() / 2, currentY, { align: 'center' }); currentY += 10; // Goals pdf.setFontSize(14); pdf.setTextColor(accentColor); pdf.text("Weekly Goals", margin, currentY); currentY += 6; pdf.setFontSize(10); pdf.setTextColor(textColor); wpa_goals.forEach(goal => { const goalColorRgb = wpa_hexToRgb(goal.color); if (goalColorRgb) pdf.setFillColor(goalColorRgb.r, goalColorRgb.g, goalColorRgb.b); else pdf.setFillColor(200,200,200); pdf.rect(margin, currentY - 3.5, 4, 4, 'F'); pdf.text(goal.name, margin + 7, currentY); currentY += 6; }); currentY += 4; // Schedule Snapshot const scheduleTableEl = document.getElementById('wpa-scheduleTableCaptureArea'); const calendarWeekDisplayEl = document.getElementById('wpa-calendarWeekDisplay'); calendarWeekDisplayEl.style.display = 'block'; // Ensure header is visible for capture try { const canvas = await html2canvas(scheduleTableEl, { scale: 1.2, backgroundColor: '#FFFFFF', width: scheduleTableEl.scrollWidth, height: scheduleTableEl.scrollHeight }); calendarWeekDisplayEl.style.display = 'none'; // Hide after capture for normal view const imgData = canvas.toDataURL('image/png'); const imgProps = pdf.getImageProperties(imgData); let pdfImgWidth = contentWidth; let pdfImgHeight = (imgProps.height * pdfImgWidth) / imgProps.width; const pageHeight = pdf.internal.pageSize.getHeight(); if (currentY + pdfImgHeight + 10 > pageHeight - margin) { // +10 for next section spacing pdf.addPage(); currentY = margin; } if (pdfImgHeight > pageHeight - margin * 2) { pdfImgHeight = pageHeight - margin * 2; pdfImgWidth = (imgProps.width * pdfImgHeight) / imgProps.height; } // Scale if too tall for a page pdf.addImage(imgData, 'PNG', margin, currentY, pdfImgWidth, pdfImgHeight, undefined, 'FAST'); currentY += pdfImgHeight + 8; } catch (e) { calendarWeekDisplayEl.style.display = 'none'; console.error("PDF schedule capture error:", e); currentY+=5; } // Tasks by Goal (New Page might be needed) if (currentY > pdf.internal.pageSize.getHeight() - 50 || wpa_tasks.length > 10) { pdf.addPage(); currentY = margin; } pdf.setFontSize(14); pdf.setTextColor(accentColor); pdf.text("Tasks & Progress", margin, currentY); currentY += 7; wpa_goals.forEach(goal => { if (currentY > pdf.internal.pageSize.getHeight() - 20) { pdf.addPage(); currentY = margin; } const goalColorRgb = wpa_hexToRgb(goal.color); if (goalColorRgb) pdf.setFillColor(goalColorRgb.r, goalColorRgb.g, goalColorRgb.b); else pdf.setFillColor(200,200,200); pdf.rect(margin, currentY - 3.5, 4, 4, 'F'); pdf.setFontSize(11); pdf.setTextColor(goal.color); pdf.text(goal.name, margin + 7, currentY); currentY +=6; const tasksForGoal = wpa_tasks.filter(t => t.goalId === goal.id); if(tasksForGoal.length > 0) { const taskBody = tasksForGoal.map(t => [t.name, `${t.duration} min`, t.priority, t.isDone ? 'Done' : 'To Do']); pdf.autoTable({ head: [["Task", "Duration", "Priority", "Status"]], body: taskBody, startY: currentY, theme: 'grid', headStyles: { fillColor: '#f0f0f0', textColor: textColor }, styles: { fontSize: 8, cellPadding: 1.5 } }); currentY = pdf.lastAutoTable.finalY + 5; } else { pdf.setFontSize(9); pdf.setTextColor(textColor); pdf.text(" - No tasks for this goal.", margin + 5, currentY); currentY += 5; } }); currentY += 5; // Unscheduled Tasks const scheduledTaskIds = wpa_scheduledBlocks.filter(b => b.type === 'task').map(b => b.contentId); const unscheduledForPdf = wpa_tasks.filter(t => !t.isDone && !scheduledTaskIds.includes(t.id)); if (unscheduledForPdf.length > 0) { if (currentY > pdf.internal.pageSize.getHeight() - 30) { pdf.addPage(); currentY = margin; } pdf.setFontSize(12); pdf.setTextColor(accentColor); pdf.text("Unscheduled Tasks", margin, currentY); currentY +=6; const unscheduledBody = unscheduledForPdf.map(t => { const g = wpa_goals.find(gl => gl.id === t.goalId); return [t.name, g?g.name:'-', `${t.duration} min`, t.priority]; }); pdf.autoTable({ head: [["Task", "Goal", "Duration", "Priority"]], body: unscheduledBody, startY: currentY, theme: 'striped', headStyles: { fillColor: '#f0f0f0', textColor: textColor }, styles: { fontSize: 8, cellPadding: 1.5 } }); currentY = pdf.lastAutoTable.finalY + 8; } // Reflection if (wpa_weeklyReflection) { if (currentY > pdf.internal.pageSize.getHeight() - 40) { pdf.addPage(); currentY = margin; } pdf.setFontSize(12); pdf.setTextColor(accentColor); pdf.text("Weekly Reflection", margin, currentY); currentY +=6; pdf.setFontSize(10); pdf.setTextColor(textColor); const reflectionLines = pdf.splitTextToSize(wpa_weeklyReflection, contentWidth); pdf.text(reflectionLines, margin, currentY); } pdf.save(`Weekly_Plan_${wpa_weekToPlan}.pdf`); }; function wpa_hexToRgb(hex) { const r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return r ? {r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:null;} // --- Initial Load --- document.addEventListener('DOMContentLoaded', () => { wpa_openTab(null, wpa_tabs[0]); const firstTabButton = document.querySelector(`.wpa-tab-button[onclick*="${wpa_tabs[0]}"]`); if (firstTabButton) firstTabButton.classList.add('active'); wpa_updateNavButtons(); });
      Scroll to Top