`;
if (day.tasks.length === 0) {
dayDiv.innerHTML += '
No tasks scheduled.
';
} else {
day.tasks.sort((a,b) => TASK_PRIORITY_ORDER[a.priority] - TASK_PRIORITY_ORDER[b.priority]).forEach(task => { // Sort tasks within the day by priority for display
dayDiv.innerHTML += `
${task.priority}
${task.name} (${swp_formatDurationFromMinutes(task.durationMinutes)})
${task.dueDate ? `(Due: ${new Date(task.dueDate+"T00:00:00Z").toLocaleDateString(undefined, {timeZone:'UTC'})})` : ''}
`;
});
}
planOutputDiv.appendChild(dayDiv);
});
if (unscheduledTasks.length > 0) {
unscheduledTasks.forEach(task => {
unscheduledListUl.innerHTML += `
${task.name} (${swp_formatDurationFromMinutes(task.durationMinutes)}, ${task.priority}) - Reason: ${task.reason || 'No capacity'}`;
});
} else {
unscheduledListUl.innerHTML = '
All tasks were successfully scheduled!';
}
document.getElementById('swp-generated-plan-area').style.display = 'block';
document.getElementById('swp-download-pdf-button').disabled = false;
}
function swp_clearAllData() {
if (confirm("Clear all tasks and the generated plan? Capacity settings will remain.")) {
document.getElementById('swp-tasks-input-list').innerHTML = '';
swp_taskInputRowCounter = 0; swp_tasks = [];
swp_addTaskInputRow();
document.getElementById('swp-plan-output').innerHTML = '';
document.getElementById('swp-unscheduled-tasks-list').innerHTML = '';
swp_disablePdf();
}
}
function swp_downloadPDF() {
if (!tpc_jsPDF_loaded_SWP || !tpc_autoTable_loaded_SWP) { alert("SWP Error: PDF libraries not loaded."); return; }
if (!swp_generatedPlanForPdf) { alert("Please generate a plan first."); return; }
const { dailySlots, unscheduledTasks, settings } = swp_generatedPlanForPdf;
const doc = new TPC_jsPDF_SWP();
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim();
const darkColor = getComputedStyle(document.documentElement).getPropertyValue('--dark-color').trim();
let finalY = 15;
const reportDateStr = new Date().toLocaleDateString();
doc.setFontSize(18); doc.setTextColor(primaryColor);
doc.text("Smart Workload Plan Report", doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center' });
finalY += 8; doc.setFontSize(10); doc.setTextColor(darkColor);
doc.text(`Report Date: ${reportDateStr} | Plan Start: ${new Date(settings.startDate+"T00:00:00Z").toLocaleDateString(undefined, {timeZone:'UTC'})} for ${settings.numDays} days`, doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center'});
finalY += 5;
doc.text(`Daily Capacity: ${settings.dailyCapacityHours} hours on Workdays: ${settings.workDays.map(d => ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][d]).join(', ')}`, doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center'});
finalY += 10;
dailySlots.forEach(day => {
if (finalY > 250) { doc.addPage(); finalY = 15; }
doc.setFontSize(12); doc.setTextColor(primaryColor);
const utilization = day.capacityMinutes > 0 ? (day.scheduledMinutes / day.capacityMinutes * 100).toFixed(0) : 0;
doc.text(day.date.toLocaleDateString(undefined, {timeZone:'UTC', weekday:'long', month:'long', day:'numeric', year:'numeric'}), 14, finalY);
finalY += 6;
doc.setFontSize(9); doc.setTextColor(darkColor);
doc.text(`Capacity: ${swp_formatDurationFromMinutes(day.capacityMinutes)} | Scheduled: ${swp_formatDurationFromMinutes(day.scheduledMinutes)} (${utilization}%)`, 14, finalY);
finalY += 6;
if (day.tasks.length > 0) {
const tableBody = day.tasks.map(task => [
task.name, task.priority, swp_formatDurationFromMinutes(task.durationMinutes),
task.dueDate ? new Date(task.dueDate+"T00:00:00Z").toLocaleDateString(undefined,{timeZone:'UTC'}) : '-'
]);
doc.autoTable({
startY: finalY, head: [['Task', 'Priority', 'Duration', 'Due Date']], body: tableBody,
theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff', fontSize: 9 },
styles: { fontSize: 8, cellPadding: 1.5 }
});
finalY = doc.lastAutoTable.finalY + 7;
} else {
doc.setFontSize(9); doc.setTextColor(darkColor); doc.text("No tasks scheduled for this day.", 14, finalY); finalY += 7;
}
});
if (unscheduledTasks.length > 0) {
if (finalY > 250) { doc.addPage(); finalY = 15; }
doc.setFontSize(12); doc.setTextColor(primaryColor);
doc.text("Unscheduled Tasks", 14, finalY); finalY += 7;
const unscheduledBody = unscheduledTasks.map(task => [
task.name, task.priority, swp_formatDurationFromMinutes(task.durationMinutes), task.dueDate || '-', task.reason || 'No capacity/slot'
]);
doc.autoTable({
startY: finalY, head: [['Task', 'Priority', 'Duration', 'Due Date', 'Reason Not Scheduled']], body: unscheduledBody,
theme: 'grid', headStyles: {fillColor: getComputedStyle(document.documentElement).getPropertyValue('--warning-color').trim(), textColor: darkColor, fontSize:9},
styles: {fontSize:8, cellPadding:1.5}
});
}
doc.save(`Smart_Workload_Plan_${new Date().toISOString().slice(0,10)}.pdf`);
}