Time Blocking Planner

Time Blocking Planner

Work Day Hours & Granularity

Task Categories & Colors

Effective Time Blocking Guide

1. Define Your Core Settings First
Go to the "Settings & Categories" tab. Set your typical work start/end times and time slot granularity (e.g., 30 minutes). Create task categories that make sense for your workflow (e.g., "Deep Work," "Meetings," "Admin," "Learning," "Personal Errands," "Breaks") and assign them distinct colors.
2. Plan Your Day
Navigate to the "Daily Planner" tab. Select the date you want to plan. Click "Add New Time Block".
3. Create Time Blocks
In the modal:
  • Give your task/activity a clear name.
  • Set the Start Time and End Time for the block.
  • Assign a Category to the block. This will color-code it on your timeline.
  • Add any optional notes.
The tool will prevent you from creating blocks that overlap with existing ones.
4. Be Realistic with Durations
Estimate task durations as accurately as possible. It's often better to slightly overestimate than underestimate. Remember to include buffer time if needed.
5. Schedule Breaks
Don't forget to block out time for short breaks, lunch, or any other personal needs. Create a "Break" category for this. Consistent breaks improve focus and prevent burnout.
6. Group Similar Tasks (Batching)
If you have many small, similar tasks (like responding to emails or making calls), try to group them into a single, dedicated time block.
7. Prioritize Important Tasks
Schedule your most important or high-concentration tasks ("Deep Work") during times of the day when you know you're most productive and least likely to be interrupted.
8. Review and Adapt
Your first time-blocked schedule might not be perfect. At the end of the day, review how it went. Did you stick to the plan? Were your time estimates accurate? Make adjustments to your categories or typical block durations for future planning.
9. Stick to the Plan (Mostly)
The goal of time blocking is to be more intentional with your time. Try to adhere to your schedule, but also allow for some flexibility when urgent, unexpected items arise. If you deviate, consciously decide how to adjust the rest of your day.
×

Add Time Block

Error: Work End Time must be after Start Time. Check settings.

"; if(tbpDownloadPdfBtn) tbpDownloadPdfBtn.style.display = 'none'; return; } if(tbpDownloadPdfBtn) tbpDownloadPdfBtn.style.display = 'block'; const slotHeightPx = 30; // Height of one slot in pixels (can be adjusted) const timelineTotalPixelHeight = (totalDayDurationMinutes / slotGranularity) * slotHeightPx; tbpTimelineGridEl.style.height = `${timelineTotalPixelHeight}px`; tbpTimelineGridEl.style.backgroundSize = `100% ${slotHeightPx}px`; for (let minutes = dayStartMinutes; minutes < dayEndMinutes; minutes += slotGranularity) { const timeLabelDiv = document.createElement('div'); timeLabelDiv.style.height = `${slotHeightPx}px`; timeLabelDiv.textContent = tbpMinutesToTime(minutes); tbpTimeLabelsEl.appendChild(timeLabelDiv); } const blocksForDate = tbpDailyTimeBlocks[tbpCurrentSelectedDate] || []; blocksForDate.forEach(block => { const blockStartMinutes = tbpTimeToMinutes(block.startTime); const blockEndMinutes = tbpTimeToMinutes(block.endTime); // Ensure block is within the displayable day range const effectiveBlockStart = Math.max(blockStartMinutes, dayStartMinutes); const effectiveBlockEnd = Math.min(blockEndMinutes, dayEndMinutes); const blockDurationMinutes = effectiveBlockEnd - effectiveBlockStart; if (blockDurationMinutes <= 0) return; const topPositionPx = ((effectiveBlockStart - dayStartMinutes) / slotGranularity) * slotHeightPx; const heightPx = (blockDurationMinutes / slotGranularity) * slotHeightPx; const blockEl = document.createElement('div'); blockEl.className = 'tbp-time-block'; blockEl.style.top = `${topPositionPx}px`; blockEl.style.height = `${heightPx}px`; const category = tbpSettings.taskCategories.find(cat => cat.id === block.categoryId); blockEl.style.backgroundColor = category ? category.color : 'var(--tbp-accent-color)'; // Basic contrast check for text color const bgColor = blockEl.style.backgroundColor; if (bgColor === "rgb(241, 196, 15)" || bgColor === "rgb(255, 202, 40)" || bgColor === "#F1C40F" || bgColor === "#FFCA28") { // Yellow/Amber blockEl.style.color = 'var(--tbp-text-color)'; } else { blockEl.style.color = 'var(--tbp-light-text-color)'; } blockEl.innerHTML = `
${block.taskName}
${tbpFormatTimeForDisplay(block.startTime)} - ${tbpFormatTimeForDisplay(block.endTime)}
${block.notes && blockHeightPx > 40 ? `
${block.notes.substring(0,50)}${block.notes.length > 50 ? '...' : ''}
` : ''} `; // Only show notes if block is tall enough blockEl.onclick = () => tbpOpenBlockModal(block.id); tbpTimelineGridEl.appendChild(blockEl); }); } // --- Daily Planner: Block Modal & CRUD --- window.tbpOpenBlockModal = function(blockId = null) { // Make globally accessible if (!tbpCurrentSelectedDate) { alert("Please select a date first."); return; } if(!tbpBlockForm || !tbpBlockIdInput || !tbpBlockDateInput || !tbpBlockModalTitleEl || !tbpDeleteBlockBtn || !tbpBlockTaskNameInput || !tbpBlockStartTimeInput || !tbpBlockEndTimeInput || !tbpBlockCategorySelectEl || !tbpBlockNotesInput ) { console.error("Modal elements not found"); return; } tbpBlockForm.reset(); tbpBlockIdInput.value = ''; tbpBlockDateInput.value = tbpCurrentSelectedDate; tbpPopulateCategorySelect(); tbpDeleteBlockBtn.style.display = 'none'; if (blockId) { const blocks = tbpDailyTimeBlocks[tbpCurrentSelectedDate] || []; const block = blocks.find(b => b.id === blockId); if (block) { tbpBlockModalTitleEl.textContent = 'Edit Time Block'; tbpBlockIdInput.value = block.id; tbpBlockTaskNameInput.value = block.taskName; tbpBlockStartTimeInput.value = block.startTime; tbpBlockEndTimeInput.value = block.endTime; tbpBlockCategorySelectEl.value = block.categoryId || ""; tbpBlockNotesInput.value = block.notes || ""; tbpDeleteBlockBtn.style.display = 'inline-block'; } } else { tbpBlockModalTitleEl.textContent = 'Add New Time Block'; tbpBlockStartTimeInput.value = tbpSettings.dayStartTime; const defaultEndMins = tbpTimeToMinutes(tbpSettings.dayStartTime) + parseInt(tbpSettings.timeSlotGranularityMinutes); tbpBlockEndTimeInput.value = tbpMinutesToTime(Math.min(defaultEndMins, tbpTimeToMinutes(tbpSettings.dayEndTime))); } if(tbpBlockModalEl) tbpBlockModalEl.style.display = 'block'; } window.tbpCloseModal = (modalId) => { // Make globally accessible const modal = document.getElementById(modalId); if(modal) modal.style.display = 'none'; } function handleBlockFormSubmit(e) { e.preventDefault(); const blockId = tbpBlockIdInput.value; const blockDate = tbpBlockDateInput.value; const blockData = { taskName: tbpBlockTaskNameInput.value.trim(), startTime: tbpBlockStartTimeInput.value, endTime: tbpBlockEndTimeInput.value, categoryId: tbpBlockCategorySelectEl.value, notes: tbpBlockNotesInput.value.trim() }; if (!blockData.taskName || !blockData.startTime || !blockData.endTime) { alert("Task name, start time, and end time are required."); return; } if (tbpTimeToMinutes(blockData.endTime) <= tbpTimeToMinutes(blockData.startTime)) { alert("End time must be after start time."); return; } // Overlap Check const dayBlocks = tbpDailyTimeBlocks[blockDate] || []; const newStartM = tbpTimeToMinutes(blockData.startTime); const newEndM = tbpTimeToMinutes(blockData.endTime); for (const existingBlock of dayBlocks) { if (existingBlock.id === blockId) continue; const existingStartM = tbpTimeToMinutes(existingBlock.startTime); const existingEndM = tbpTimeToMinutes(existingBlock.endTime); if (newStartM < existingEndM && newEndM > existingStartM) { alert(`Overlap detected with task: "${existingBlock.taskName}" (${existingBlock.startTime} - ${existingBlock.endTime}). Please adjust times.`); return; } } if (!tbpDailyTimeBlocks[blockDate]) tbpDailyTimeBlocks[blockDate] = []; if (blockId) { const index = tbpDailyTimeBlocks[blockDate].findIndex(b => b.id === blockId); if (index > -1) { tbpDailyTimeBlocks[blockDate][index] = { ...tbpDailyTimeBlocks[blockDate][index], ...blockData }; } } else { const newBlock = { id: 'tbp-block-' + Date.now(), ...blockData }; tbpDailyTimeBlocks[blockDate].push(newBlock); } tbpDailyTimeBlocks[blockDate].sort((a,b) => a.startTime.localeCompare(b.startTime)); tbpSaveDailyBlocks(); tbpCloseModal('tbpBlockModal'); } window.tbpHandleDeleteBlock = function() { // Make globally accessible const blockId = tbpBlockIdInput.value; const blockDate = tbpBlockDateInput.value; if (blockId && blockDate && tbpDailyTimeBlocks[blockDate]) { if (confirm("Are you sure you want to delete this time block?")) { tbpDailyTimeBlocks[blockDate] = tbpDailyTimeBlocks[blockDate].filter(b => b.id !== blockId); tbpSaveDailyBlocks(); tbpCloseModal('tbpBlockModal'); } } } // --- PDF Export --- function handlePdfDownload() { const selectedDateKey = tbpCurrentSelectedDate; if (!selectedDateKey || !tbpDailyTimeBlocks[selectedDateKey] || tbpDailyTimeBlocks[selectedDateKey].length === 0) { alert("No time blocks planned for this day to export."); return; } const dayBlocks = tbpDailyTimeBlocks[selectedDateKey]; const doc = new jsPDF(); // Use the global jsPDF from window.jspdf const displayDate = new Date(selectedDateKey + "T00:00:00").toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); doc.setFontSize(18); doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--tbp-primary-color').trim()); doc.text(`Time Blocked Plan - ${displayDate}`, 14, 22); let yPos = 35; const pageHeight = doc.internal.pageSize.height; const leftMargin = 14; const timelineWidth = doc.internal.pageSize.width - leftMargin * 2; const timeLabelWidth = 20; const gridStartX = leftMargin + timeLabelWidth; const gridWidth = timelineWidth - timeLabelWidth - 5; const dayStartMinutes = tbpTimeToMinutes(tbpSettings.dayStartTime); const dayEndMinutes = tbpTimeToMinutes(tbpSettings.dayEndTime); const totalVisibleDayMinutes = dayEndMinutes - dayStartMinutes; if (totalVisibleDayMinutes <=0) { doc.text("Invalid work hours set.", 14, yPos); doc.save(`TimeBlockingPlan_Error_${selectedDateKey}.pdf`); return; } const pdfTimelineHeight = 220; doc.setDrawColor(getComputedStyle(document.documentElement).getPropertyValue('--tbp-border-color').trim()); doc.setLineWidth(0.2); doc.setFontSize(8); doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--tbp-accent-color').trim()); for (let minutes = dayStartMinutes; minutes <= dayEndMinutes; minutes += parseInt(tbpSettings.timeSlotGranularityMinutes)) { const y = yPos + ((minutes - dayStartMinutes) / totalVisibleDayMinutes) * pdfTimelineHeight; if (y > pageHeight - 20 && minutes < dayEndMinutes) { break; } if(minutes % 60 === 0 || parseInt(tbpSettings.timeSlotGranularityMinutes) < 60) { doc.text(tbpMinutesToTime(minutes), leftMargin, y + 2); } doc.line(gridStartX, y, gridStartX + gridWidth, y); } dayBlocks.forEach(block => { const blockStartMinutes = tbpTimeToMinutes(block.startTime); const blockEndMinutes = tbpTimeToMinutes(block.endTime); const effectiveBlockStart = Math.max(blockStartMinutes, dayStartMinutes); const effectiveBlockEnd = Math.min(blockEndMinutes, dayEndMinutes); const blockDurationMinutes = effectiveBlockEnd - effectiveBlockStart; if(blockDurationMinutes <=0) return; const blockTop = yPos + ((effectiveBlockStart - dayStartMinutes) / totalVisibleDayMinutes) * pdfTimelineHeight; const blockHeight = (blockDurationMinutes / totalVisibleDayMinutes) * pdfTimelineHeight; const category = tbpSettings.taskCategories.find(cat => cat.id === block.categoryId); const color = category ? category.color : '#BDC3C7'; doc.setFillColor(color.startsWith('var') ? '#BDC3C7' : color); doc.rect(gridStartX + 1, blockTop, gridWidth - 2, blockHeight, 'F'); doc.setFontSize(7); if (color === "#F1C40F" || color === "#FFCA28" || color.toLowerCase() === "#ecf0f1") { doc.setTextColor(50,50,50); } else { doc.setTextColor(255, 255, 255); } const textX = gridStartX + 3; const textY = blockTop + 4; const textMaxWidth = gridWidth - 6; const taskNameLines = doc.splitTextToSize(block.taskName, textMaxWidth); doc.text(taskNameLines, textX, textY); let timeYOffset = taskNameLines.length * 3; doc.setFontSize(6); if(blockHeight > 10) { doc.text(`${block.startTime}-${block.endTime}`, textX, textY + timeYOffset); } }); let tableYPos = yPos + pdfTimelineHeight + 10; if (tableYPos > pageHeight - 30 || dayBlocks.length > 10) { doc.addPage(); tableYPos = 20; } doc.setFontSize(12); doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--tbp-text-color').trim()); doc.text("Task List for the Day:", 14, tableYPos); tableYPos += 7; const tableColumns = ["Time", "Task", "Category", "Notes"]; const tableRows = dayBlocks.map(b => { const cat = tbpSettings.taskCategories.find(c => c.id === b.categoryId); return [`${b.startTime}-${b.endTime}`, b.taskName, cat ? cat.name : 'N/A', b.notes || '']; }); if (tableRows.length > 0) { doc.autoTable({ head: [tableColumns], body: tableRows, startY: tableYPos, theme: 'striped', headStyles: { fillColor: getComputedStyle(document.documentElement).getPropertyValue('--tbp-primary-color').trim()} }); } doc.save(`TimeBlockingPlan_${selectedDateKey}.pdf`); } // --- Initialization --- document.addEventListener('DOMContentLoaded', () => { // Assign DOM elements to global vars after DOM is ready tbpWorkStartTimeInput = document.getElementById('tbpWorkStartTime'); tbpWorkEndTimeInput = document.getElementById('tbpWorkEndTime'); tbpTimeSlotGranularitySelect = document.getElementById('tbpTimeSlotGranularity'); tbpAddCategoryForm = document.getElementById('tbpAddCategoryForm'); tbpCategoryNameInput = document.getElementById('tbpCategoryName'); tbpCategoryColorInput = document.getElementById('tbpCategoryColor'); tbpCategoriesListEl = document.getElementById('tbpCategoriesList'); tbpSelectedDateInput = document.getElementById('tbpSelectedDate'); tbpTimeLabelsEl = document.getElementById('tbpTimeLabels'); tbpTimelineGridEl = document.getElementById('tbpTimelineGrid'); tbpBlockModalEl = document.getElementById('tbpBlockModal'); tbpBlockModalTitleEl = document.getElementById('tbpBlockModalTitle'); tbpBlockForm = document.getElementById('tbpBlockForm'); tbpBlockIdInput = document.getElementById('tbpBlockId'); tbpBlockDateInput = document.getElementById('tbpBlockDate'); tbpBlockTaskNameInput = document.getElementById('tbpBlockTaskName'); tbpBlockStartTimeInput = document.getElementById('tbpBlockStartTime'); tbpBlockEndTimeInput = document.getElementById('tbpBlockEndTime'); tbpBlockCategorySelectEl = document.getElementById('tbpBlockCategory'); tbpBlockNotesInput = document.getElementById('tbpBlockNotes'); tbpDeleteBlockBtn = document.getElementById('tbpDeleteBlockBtn'); tbpDownloadPdfBtn = document.getElementById('tbpDownloadPdfButton'); // Attach event listeners if(tbpAddCategoryForm) tbpAddCategoryForm.addEventListener('submit', handleAddCategoryFormSubmit); if(tbpBlockForm) tbpBlockForm.addEventListener('submit', handleBlockFormSubmit); if(tbpSelectedDateInput) tbpSelectedDateInput.addEventListener('change', handleSelectedDateChange); if(tbpDownloadPdfBtn) tbpDownloadPdfBtn.addEventListener('click', handlePdfDownload); tbpLoadData(); const firstTabButton = document.querySelector('#timeBlockingPlannerTool .tbp-tab-button'); if (firstTabButton) { firstTabButton.click(); } window.addEventListener('click', function(event) { if (event.target.classList.contains('tbp-modal')) { tbpCloseModal(event.target.id); } }); });
Scroll to Top