Work Routine Optimizer

Work Routine Optimizer

General Work Hours

Define Time Block Types

Create Daily Template Schedule


Tasks for Date
Scheduled Routine for Date

Work Routine Optimization Guide

1. Understand Your Energy Levels
Identify times of the day when you are most alert and focused (for "Focus Work") and when you might be better suited for lighter tasks ("Admin/Emails") or meetings.
2. Time Blocking
Allocate specific blocks of time for specific types of tasks. The "Daily Template" helps you do this. Stick to your blocks as much as possible.
3. Prioritize ruthlessly
Use the priority field for tasks. When scheduling, try to fit high-priority items into your most productive blocks.
4. Estimate Task Durations
Accurately estimating how long tasks will take is crucial for effective scheduling. Be realistic and add a small buffer if unsure. This tool helps you see if you're overcommitting time in a block.
5. Batch Similar Tasks
Group similar tasks together (e.g., do all email responses in one "Admin" block). This reduces context switching and improves efficiency.
6. Include Breaks
Don't forget to schedule short breaks throughout your day. Define a "Break" block type. Regular breaks prevent burnout and can actually increase overall productivity (e.g., Pomodoro Technique).
7. Minimize Distractions
During "Focus Work" blocks, try to minimize interruptions. Turn off notifications or find a quiet space.
8. Review and Adjust
Your ideal routine might take time to perfect. At the end of each day or week, review what worked and what didn't. Adjust your `Daily Template` or task categorization in the `Settings & Template` tab as needed.
9. Single Task Focus
While a block might contain multiple small tasks of the same type, try to focus on completing one task before moving to the next, especially during "Focus Work" blocks.
×

Add Task for Day

×

Assign Tasks to Block

Select a date to see the schedule.

'; if(wroSelectedDateDisplay1El) wroSelectedDateDisplay1El.textContent = "N/A"; if(wroSelectedDateDisplay2El) wroSelectedDateDisplay2El.textContent = "N/A"; wroDownloadPdfBtn.style.display = 'none'; return; } const displayDate = new Date(selectedDateKey + "T00:00:00").toLocaleDateString(undefined, {month:'short', day:'numeric'}); if(wroSelectedDateDisplay1El) wroSelectedDateDisplay1El.textContent = displayDate; if(wroSelectedDateDisplay2El) wroSelectedDateDisplay2El.textContent = displayDate; // Ensure the day's schedule structure exists, based on template if (!wroDailySchedules[selectedDateKey]) { wroDailySchedules[selectedDateKey] = { dayTasksList: [], // Master list of tasks planned for this day scheduledBlocks: JSON.parse(JSON.stringify(wroSettings.dailyTemplate)).map(tb => ({ // Deep clone template blocks ...tb, // spread template block properties like id (templateBlockId), name, startTime, endTime, blockTypeId id: 'dsb-' + Date.now() + '-' + Math.random().toString(16).slice(2), // Unique instance ID for this day's block templateBlockId: tb.id, // Keep reference to original template block tasks: [] // Task IDs scheduled in this specific block instance })) }; } else if (!wroDailySchedules[selectedDateKey].scheduledBlocks || wroDailySchedules[selectedDateKey].scheduledBlocks.length !== wroSettings.dailyTemplate.length) { // If template changed, try to reconcile or rebuild. For simplicity, rebuild if lengths differ or if scheduledBlocks is missing. // A more sophisticated merge could be done if needed. const existingDayTasks = wroDailySchedules[selectedDateKey].dayTasksList || []; wroDailySchedules[selectedDateKey] = { dayTasksList: existingDayTasks, scheduledBlocks: JSON.parse(JSON.stringify(wroSettings.dailyTemplate)).map(tb => ({ ...tb, id: 'dsb-' + Date.now() + '-' + Math.random().toString(16).slice(2), templateBlockId: tb.id, tasks: [] })) }; } wroRenderDayTasksList(selectedDateKey); wroRenderDailyScheduleView(selectedDateKey); wroDownloadPdfBtn.style.display = 'block'; } function wroRenderDayTasksList(dateKey) { wroDayTasksListEl.innerHTML = ''; const dayData = wroDailySchedules[dateKey]; if (!dayData || !dayData.dayTasksList || dayData.dayTasksList.length === 0) { wroDayTasksListEl.innerHTML = '

No tasks added for this day yet.

'; return; } dayData.dayTasksList.forEach(task => { const taskType = wroSettings.timeBlockTypes.find(t => t.id === task.taskTypeId); const itemEl = document.createElement('div'); itemEl.className = 'wro-task-to-schedule-item'; itemEl.innerHTML = `

${task.name}

Est: ${task.estimatedTimeMinutes}m | Type: ${taskType ? taskType.name : 'N/A'} | P: ${task.priority} | Status: ${task.status}

`; wroDayTasksListEl.appendChild(itemEl); }); } // For Daily Tasks (not yet scheduled into blocks, or general list for the day) window.wroOpenDailyTaskModal = function(taskId = null) { const selectedDateKey = wroSelectedDateInput.value; if (!selectedDateKey) { alert("Please select a date first."); return; } wroDailyTaskForm.reset(); wroDailyTaskIdInput.value = ''; wroPopulateBlockTypeSelects(); // Ensure task type dropdown is fresh if (taskId) { const dayData = wroDailySchedules[selectedDateKey]; const task = dayData ? dayData.dayTasksList.find(t => t.id === taskId) : null; if (task) { wroDailyTaskModalTitleEl.textContent = 'Edit Daily Task'; wroDailyTaskIdInput.value = task.id; wroDailyTaskNameInput.value = task.name; wroDailyTaskEstTimeInput.value = task.estimatedTimeMinutes; wroDailyTaskTypeInputEl.value = task.taskTypeId; wroDailyTaskPriorityInput.value = task.priority; wroDailyTaskStatusInput.value = task.status; } } else { wroDailyTaskModalTitleEl.textContent = 'Add New Task for ' + new Date(selectedDateKey+"T00:00:00").toLocaleDateString(); } wroDailyTaskModalEl.style.display = 'block'; } if(wroDailyTaskForm) wroDailyTaskForm.addEventListener('submit', function(e) { e.preventDefault(); const selectedDateKey = wroSelectedDateInput.value; if (!selectedDateKey) { alert("Error: No date selected for task."); return; } if (!wroDailySchedules[selectedDateKey]) { wroHandleDateChange(); // Initialize if somehow not present } const taskId = wroDailyTaskIdInput.value; const taskData = { name: wroDailyTaskNameInput.value.trim(), estimatedTimeMinutes: parseInt(wroDailyTaskEstTimeInput.value), taskTypeId: wroDailyTaskTypeInputEl.value, priority: wroDailyTaskPriorityInput.value, status: wroDailyTaskStatusInput.value }; if (!taskData.name || isNaN(taskData.estimatedTimeMinutes) || taskData.estimatedTimeMinutes <= 0) { alert("Task name and a valid positive estimated time are required."); return; } if (taskId) { // Editing const taskIndex = wroDailySchedules[selectedDateKey].dayTasksList.findIndex(t => t.id === taskId); if (taskIndex > -1) { wroDailySchedules[selectedDateKey].dayTasksList[taskIndex] = { ...wroDailySchedules[selectedDateKey].dayTasksList[taskIndex], ...taskData }; } } else { // Adding new const newTask = { id: 'dtask-' + Date.now(), ...taskData, assignedToBlockInstanceId: null }; wroDailySchedules[selectedDateKey].dayTasksList.push(newTask); } wroSaveDailySchedule(selectedDateKey); wroRenderDayTasksList(selectedDateKey); wroRenderDailyScheduleView(selectedDateKey); // Update schedule view if task details changed wroCloseModal('wroDailyTaskModal'); }); window.wroDeleteDailyTask = function(taskId) { const selectedDateKey = wroSelectedDateInput.value; if (!selectedDateKey || !wroDailySchedules[selectedDateKey]) return; if (confirm("Are you sure you want to delete this task from the day's list? It will also be removed from any scheduled block.")) { // Remove from master list wroDailySchedules[selectedDateKey].dayTasksList = wroDailySchedules[selectedDateKey].dayTasksList.filter(t => t.id !== taskId); // Remove from any scheduled blocks wroDailySchedules[selectedDateKey].scheduledBlocks.forEach(block => { block.tasks = block.tasks.filter(id => id !== taskId); }); wroSaveDailySchedule(selectedDateKey); wroRenderDayTasksList(selectedDateKey); wroRenderDailyScheduleView(selectedDateKey); } } // --- Scheduling tasks into blocks --- function wroRenderDailyScheduleView(dateKey) { wroDailyScheduleOutputEl.innerHTML = ''; const daySchedule = wroDailySchedules[dateKey]; if (!daySchedule || !daySchedule.scheduledBlocks) { wroDailyScheduleOutputEl.innerHTML = '

Daily template not set or no schedule for this day.

'; return; } daySchedule.scheduledBlocks.forEach(blockInstance => { const blockType = wroSettings.timeBlockTypes.find(t => t.id === blockInstance.blockTypeId); const blockDiv = document.createElement('div'); blockDiv.className = 'wro-schedule-block-display'; blockDiv.style.borderLeftColor = blockType ? blockType.color : 'var(--wro-accent-color)'; let totalTaskTimeInBlock = 0; let tasksHTML = ''; if (blockInstance.tasks && blockInstance.tasks.length > 0) { blockInstance.tasks.forEach(taskId => { const task = daySchedule.dayTasksList.find(t => t.id === taskId); if (task) { totalTaskTimeInBlock += task.estimatedTimeMinutes; tasksHTML += `
${task.name} (${task.estimatedTimeMinutes}m) - P: ${task.priority}
`; } }); } else { tasksHTML = '

No tasks assigned to this block.

'; } const blockDurationMinutes = wroTimeDiffInMinutes(blockInstance.startTime, blockInstance.endTime); const remainingTime = blockDurationMinutes - totalTaskTimeInBlock; const capacityText = `Capacity: ${totalTaskTimeInBlock}m / ${blockDurationMinutes}m used. (${remainingTime}m remaining)`; blockDiv.innerHTML = `
${wroFormatTime(blockInstance.startTime)} - ${wroFormatTime(blockInstance.endTime)} ${blockInstance.name || (blockType ? blockType.name : 'Block')}

${capacityText}

${tasksHTML}
`; wroDailyScheduleOutputEl.appendChild(blockDiv); }); } window.wroOpenAssignTaskModal = function(blockInstanceId) { const selectedDateKey = wroSelectedDateInput.value; if (!selectedDateKey || !wroDailySchedules[selectedDateKey]) return; const blockInstance = wroDailySchedules[selectedDateKey].scheduledBlocks.find(b => b.id === blockInstanceId); if (!blockInstance) return; wroAssignTargetBlockInstanceIdInput.value = blockInstanceId; wroAssignTaskModalTitleEl.textContent = `Assign Tasks to: ${blockInstance.name || 'Block'} (${wroFormatTime(blockInstance.startTime)}-${wroFormatTime(blockInstance.endTime)})`; wroAssignableTasksListEl.innerHTML = ''; const dayTasks = wroDailySchedules[selectedDateKey].dayTasksList; const assignableTasks = dayTasks.filter(task => !wroIsTaskAssignedToAnyBlock(task.id, selectedDateKey) && // Not already assigned to *any* block (task.taskTypeId === blockInstance.blockTypeId || !blockInstance.blockTypeId) // Match block type or if block has no type ); if (assignableTasks.length === 0) { wroAssignableTasksListEl.innerHTML = '

No suitable unassigned tasks available for this block type, or all tasks are already scheduled.

'; } else { assignableTasks.forEach(task => { const div = document.createElement('div'); div.innerHTML = ``; wroAssignableTasksListEl.appendChild(div); }); } wroAssignTaskModalEl.style.display = 'block'; } function wroIsTaskAssignedToAnyBlock(taskId, dateKey) { if (!wroDailySchedules[dateKey] || !wroDailySchedules[dateKey].scheduledBlocks) return false; return wroDailySchedules[dateKey].scheduledBlocks.some(block => block.tasks.includes(taskId)); } window.wroConfirmTaskAssignment = function() { const selectedDateKey = wroSelectedDateInput.value; const blockInstanceId = wroAssignTargetBlockInstanceIdInput.value; if (!selectedDateKey || !blockInstanceId || !wroDailySchedules[selectedDateKey]) return; const blockInstance = wroDailySchedules[selectedDateKey].scheduledBlocks.find(b => b.id === blockInstanceId); if (!blockInstance) return; const selectedTaskCheckboxes = wroAssignableTasksListEl.querySelectorAll('input[name="assignableTask"]:checked'); let assignedTaskTotalTime = blockInstance.tasks.reduce((sum, tid) => { const task = wroDailySchedules[selectedDateKey].dayTasksList.find(t => t.id === tid); return sum + (task ? task.estimatedTimeMinutes : 0); }, 0); const blockDuration = wroTimeDiffInMinutes(blockInstance.startTime, blockInstance.endTime); selectedTaskCheckboxes.forEach(checkbox => { const taskId = checkbox.value; const taskToAdd = wroDailySchedules[selectedDateKey].dayTasksList.find(t => t.id === taskId); if (taskToAdd && (assignedTaskTotalTime + taskToAdd.estimatedTimeMinutes <= blockDuration)) { if (!blockInstance.tasks.includes(taskId)) { blockInstance.tasks.push(taskId); assignedTaskTotalTime += taskToAdd.estimatedTimeMinutes; } } else if (taskToAdd) { alert(`Cannot add task "${taskToAdd.name}". Exceeds block capacity of ${blockDuration} minutes.`); } }); wroSaveDailySchedule(selectedDateKey); wroRenderDayTasksList(selectedDateKey); // To update if any tasks are now visually "scheduled" wroRenderDailyScheduleView(selectedDateKey); wroCloseModal('wroAssignTaskModal'); } window.wroUnassignTaskFromBlock = function(blockInstanceId, taskId) { const selectedDateKey = wroSelectedDateInput.value; if (!selectedDateKey || !blockInstanceId || !taskId || !wroDailySchedules[selectedDateKey]) return; const blockInstance = wroDailySchedules[selectedDateKey].scheduledBlocks.find(b => b.id === blockInstanceId); if (blockInstance) { blockInstance.tasks = blockInstance.tasks.filter(id => id !== taskId); wroSaveDailySchedule(selectedDateKey); wroRenderDailyScheduleView(selectedDateKey); wroRenderDayTasksList(selectedDateKey); // Refresh tasks list too } } // --- PDF Export --- if(wroDownloadPdfBtn) wroDownloadPdfBtn.addEventListener('click', function() { const selectedDateKey = wroSelectedDateInput.value; if (!selectedDateKey || !wroDailySchedules[selectedDateKey]) { alert("Please select a date with a planned routine to download."); return; } const daySchedule = wroDailySchedules[selectedDateKey]; const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(18); doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--wro-primary-color').trim()); doc.text(`Work Routine for: ${dtsgFormatDisplayDate(selectedDateKey)}`, 14, 22); let yPos = 35; doc.setFontSize(10); doc.setTextColor(50); doc.text(`Work Hours: ${wroFormatTime(wroSettings.workStartTime)} - ${wroFormatTime(wroSettings.workEndTime)}`, 14, yPos); yPos += 10; daySchedule.scheduledBlocks.forEach(blockInstance => { if (yPos > 260) { doc.addPage(); yPos = 20; } const blockType = wroSettings.timeBlockTypes.find(t => t.id === blockInstance.blockTypeId); const blockColor = blockType ? blockType.color : '#cccccc'; doc.setFontSize(12); // Simulate colored header for block - difficult to get actual CSS var value reliably in jsPDF without parsing // For now, just use a standard color or pass the hex directly doc.setFillColor(blockColor.startsWith('var') ? '#dddddd' : blockColor); // Fallback for CSS vars doc.rect(14, yPos - 4, doc.internal.pageSize.getWidth() - 28, 7, 'F'); doc.setTextColor(blockColor === '#F39C12' || blockColor === '#2ECC71' ? 50 : 255); // Text color based on perceived BG doc.text(`${wroFormatTime(blockInstance.startTime)} - ${wroFormatTime(blockInstance.endTime)}: ${blockInstance.name || (blockType ? blockType.name : 'Block')}`, 15, yPos); yPos += 8; doc.setTextColor(50); // Reset text color doc.setFontSize(9); if (blockInstance.tasks && blockInstance.tasks.length > 0) { blockInstance.tasks.forEach(taskId => { if (yPos > 270) { doc.addPage(); yPos = 20; } const task = daySchedule.dayTasksList.find(t => t.id === taskId); if (task) { const taskTypeForPdf = wroSettings.timeBlockTypes.find(t => t.id === task.taskTypeId); doc.text(` \u2022 ${task.name} (${task.estimatedTimeMinutes}m) - P: ${task.priority}, S: ${task.status}, Type: ${taskTypeForPdf ? taskTypeForPdf.name : 'N/A'}`, 18, yPos); yPos += 5; } }); } else { if (yPos > 270) { doc.addPage(); yPos = 20; } doc.text(" No tasks scheduled in this block.", 18, yPos); yPos += 5; } yPos += 3; // Space after block }); doc.save(`WorkRoutine_${selectedDateKey}.pdf`); }); // --- Initialization --- document.addEventListener('DOMContentLoaded', () => { wroLoadSettings(); wroLoadDailySchedules(); const today = new Date(2025, 4, 14); // May 14, 2025 for default wroSelectedDateInput.value = wroFormatDateKey(today); wroHandleDateChange(); // Initial render for selected/default date const firstTabButton = document.querySelector('#workRoutineOptimizerTool .wro-tab-button'); if (firstTabButton) { firstTabButton.click(); } // Close modals if clicked outside window.addEventListener('click', function(event) { if (event.target.classList.contains('wro-modal')) { wroCloseModal(event.target.id); } }); });
Scroll to Top