Task Breakdown Assistant

Task Breakdown Assistant

Deconstruct large projects into manageable, actionable steps.

Define Your Project

Major Milestones

Assign Tasks to Milestones

Complete Project Plan

${project.goal || 'Not defined'}

${project.milestones.map(m => `

${m.name}

${m.tasks.length > 0 ? m.tasks.map(t => ` `).join('') : ``}
Task Est. Hours Priority
${t.desc} ${t.hours} ${t.priority}
No tasks for this milestone.
`).join('')} `; }; // --- Event Handlers --- const handleUpdateGoal = (e) => { project.goal = e.target.value; saveData(); }; const handleAddMilestone = (e) => { e.preventDefault(); const input = getElement('milestone-name'); if (input.value.trim()) { project.milestones.push({ id: Date.now(), name: input.value.trim(), tasks: [] }); input.value = ''; saveData(); renderMilestoneList(); } }; const handleDeleteMilestone = (e) => { if (e.target.classList.contains('delete-milestone-btn')) { const id = parseInt(e.target.dataset.id); project.milestones = project.milestones.filter(m => m.id !== id); saveData(); renderMilestoneList(); } }; const handleAddTask = (e) => { e.preventDefault(); if (e.target.classList.contains('add-task-form')) { const milestoneId = parseInt(e.target.dataset.milestoneId); const milestone = project.milestones.find(m => m.id === milestoneId); const desc = e.target.elements.desc.value; const hours = parseInt(e.target.elements.hours.value); const priority = e.target.elements.priority.value; if (milestone && desc && hours > 0) { milestone.tasks.push({ id: Date.now(), desc, hours, priority }); saveData(); renderTaskBreakdownArea(); } } }; const handleDeleteTask = (e) => { if (e.target.classList.contains('delete-task-btn')) { const milestoneId = parseInt(e.target.dataset.milestoneId); const taskId = parseInt(e.target.dataset.taskId); const milestone = project.milestones.find(m => m.id === milestoneId); if (milestone) { milestone.tasks = milestone.tasks.filter(t => t.id !== taskId); saveData(); renderTaskBreakdownArea(); } } }; const generatePDF = () => { const content = getElement('pdf-content'); if (!content) return; content.classList.add('pdf-mode'); html2canvas(content, { scale: 2 }).then(canvas => { content.classList.remove('pdf-mode'); const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const ratio = canvas.width / canvas.height; const pdfImgWidth = pdfWidth - 20; const pdfImgHeight = pdfImgWidth / ratio; pdf.addImage(imgData, 'PNG', 10, 10, pdfImgWidth, pdfImgHeight); pdf.save('Project_Breakdown.pdf'); }); }; // --- Navigation & Tab Logic --- const updateTabView = () => { tabs.forEach(tab => tab.classList.toggle('active', parseInt(tab.dataset.tab) === currentTab)); tabContents.forEach(content => content.classList.toggle('active', parseInt(content.id.split('-')[1]) === currentTab)); prevBtn.style.display = currentTab === 1 ? 'none' : 'inline-flex'; nextBtn.style.display = currentTab === 3 ? 'none' : 'inline-flex'; }; let currentTab = 1; tabs.forEach(tab => tab.addEventListener('click', () => { currentTab = parseInt(tab.dataset.tab); if (currentTab === 2) renderTaskBreakdownArea(); if (currentTab === 3) renderReview(); updateTabView(); })); prevBtn.addEventListener('click', () => { if (currentTab > 1) currentTab--; updateTabView(); }); nextBtn.addEventListener('click', () => { if (currentTab < 3) currentTab++; if (currentTab === 2) renderTaskBreakdownArea(); if (currentTab === 3) renderReview(); updateTabView(); }); // --- Initial Setup & Event Listeners --- getElement('project-goal').addEventListener('change', handleUpdateGoal); getElement('add-milestone-form').addEventListener('submit', handleAddMilestone); getElement('milestone-list').addEventListener('click', handleDeleteMilestone); getElement('task-breakdown-area').addEventListener('submit', handleAddTask); getElement('task-breakdown-area').addEventListener('click', handleDeleteTask); getElement('download-pdf-btn').addEventListener('click', generatePDF); loadData(); renderAll(); updateTabView(); });
Scroll to Top