Smart Workload Planner
Smart Workload Planner

Define Your Work Capacity

Enter Tasks to Plan

Workload Plan

`; 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`); }
    Scroll to Top