Task Delegation Recommender

Task Delegation Recommender

Team Overview

Team Workload Distribution

Total Team Members

0

Tasks to Delegate

0

Manage Team

Manage Tasks

Delegation Recommender

Export Delegation Plan

Generate a PDF of the current delegation recommendations for all tasks.

${m.name} (${m.workload}%)

${m.skills.map(s => `${s}`).join(' ')}
`).join(''); } function renderTaskList() { taskList.innerHTML = tasks.map(t => `

${t.name}

${t.skills.map(s => `${s}`).join(' ')}
`).join(''); } function renderDashboard() { document.getElementById('total-members').textContent = team.length; document.getElementById('total-tasks').textContent = tasks.length; if (workloadChart) workloadChart.destroy(); const ctx = document.getElementById('workloadChart').getContext('2d'); workloadChart = new Chart(ctx, { type: 'bar', data: { labels: team.map(m => m.name), datasets: [{ label: 'Workload %', data: team.map(m => m.workload), backgroundColor: 'rgba(59, 130, 246, 0.5)', borderColor: 'rgba(59, 130, 246, 1)', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, max: 100 } } } }); } function renderTaskSelect() { taskSelect.innerHTML = tasks.map(t => ``).join(''); if (tasks.length > 0) getRecommendations(); else recommendationOutput.innerHTML = '

No tasks available to recommend.

'; } // --- LOGIC --- function getRecommendations() { const taskId = parseInt(taskSelect.value); const task = tasks.find(t => t.id === taskId); if (!task) return; const recommendations = team.map(member => { const skillMatch = member.skills.filter(s => task.skills.includes(s)).length; const skillScore = (skillMatch / task.skills.length) * 100; const workloadScore = 100 - member.workload; // Weighted score: 70% for skills, 30% for availability const finalScore = (skillScore * 0.7) + (workloadScore * 0.3); return { ...member, score: finalScore, reason: `Skill Match: ${skillMatch}/${task.skills.length}, Availability: ${100-member.workload}%` }; }).sort((a, b) => b.score - a.score); recommendationOutput.innerHTML = `
${recommendations.map((rec, index) => `

${index+1}. ${rec.name}

${index === 0 ? '

Top Recommendation

' : ''}

${rec.reason}

`).join('')}
`; } function clearForm(formType) { if (formType === 'team') { teamForm.reset(); memberIdInput.value = ''; document.getElementById('save-member-btn').textContent = 'Add Member'; } else { taskForm.reset(); taskIdInput.value = ''; document.getElementById('save-task-btn').textContent = 'Add Task'; } } window.editMember = (id) => { const member = team.find(m => m.id === id); memberIdInput.value = member.id; memberNameInput.value = member.name; memberSkillsInput.value = member.skills.join(', '); memberWorkloadInput.value = member.workload; document.getElementById('save-member-btn').textContent = 'Update Member'; }; window.deleteMember = (id) => { if (confirm('Delete this team member?')) { team = team.filter(m => m.id !== id); renderAll(); } }; window.editTask = (id) => { const task = tasks.find(t => t.id === id); taskIdInput.value = task.id; taskNameInput.value = task.name; taskSkillsInput.value = task.skills.join(', '); document.getElementById('save-task-btn').textContent = 'Update Task'; }; window.deleteTask = (id) => { if (confirm('Delete this task?')) { tasks = tasks.filter(t => t.id !== id); renderAll(); } }; function downloadPDF() { const { jsPDF } = window.jspdf; const pdfContentEl = document.getElementById('pdf-content'); let reportHTML = `

Delegation Plan

`; tasks.forEach(task => { const recommendations = team.map(member => { const skillMatch = member.skills.filter(s => task.skills.includes(s)).length; const skillScore = (skillMatch / task.skills.length) * 100; const workloadScore = 100 - member.workload; const finalScore = (skillScore * 0.7) + (workloadScore * 0.3); return { name: member.name, score: finalScore }; }).sort((a, b) => b.score - a.score); reportHTML += `

Task: ${task.name}

Recommended: ${recommendations[0] ? recommendations[0].name : 'N/A'}

`; }); pdfContentEl.innerHTML = `
${reportHTML}
`; html2canvas(pdfContentEl, { scale: 2 }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const imgProps = pdf.getImageProperties(imgData); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, 'PNG', 20, 20, pdfWidth - 40, pdfHeight - 40); pdf.save('Delegation_Plan.pdf'); }); } function renderAll() { renderTeamList(); renderTaskList(); renderDashboard(); renderTaskSelect(); } // --- EVENT LISTENERS --- teamForm.addEventListener('submit', (e) => { e.preventDefault(); const id = memberIdInput.value ? parseInt(memberIdInput.value) : null; const skills = memberSkillsInput.value.split(',').map(s => s.trim()).filter(Boolean); const memberData = { name: memberNameInput.value, skills: skills, workload: parseInt(memberWorkloadInput.value) }; if (id) { const index = team.findIndex(m => m.id === id); team[index] = { ...team[index], ...memberData }; } else { const newId = team.length > 0 ? Math.max(...team.map(m => m.id)) + 1 : 1; team.push({ id: newId, ...memberData }); } clearForm('team'); renderAll(); }); taskForm.addEventListener('submit', (e) => { e.preventDefault(); const id = taskIdInput.value ? parseInt(taskIdInput.value) : null; const skills = taskSkillsInput.value.split(',').map(s => s.trim()).filter(Boolean); const taskData = { name: taskNameInput.value, skills: skills }; if (id) { const index = tasks.findIndex(t => t.id === id); tasks[index] = { ...tasks[index], ...taskData }; } else { const newId = tasks.length > 0 ? Math.max(...tasks.map(t => t.id)) + 1 : 1; tasks.push({ id: newId, ...taskData }); } clearForm('task'); renderAll(); }); taskSelect.addEventListener('change', getRecommendations); document.getElementById('download-pdf-btn').addEventListener('click', downloadPDF); // --- TAB NAVIGATION --- window.changeTab = function(evt, tabName) { document.querySelectorAll(".tab-content").forEach(tc => tc.classList.remove('active')); document.querySelectorAll(".tab-button").forEach(tb => tb.classList.remove('active')); document.getElementById(tabName).classList.add('active'); const button = evt ? evt.currentTarget : document.querySelector(`.tab-button[onclick*="'${tabName}'"]`); if(button) button.classList.add('active'); currentTab = tabName; updateNavButtons(); if (tabName === 'dashboard') renderDashboard(); if (tabName === 'recommender') renderTaskSelect(); } function updateNavButtons() { const currentIndex = tabs.indexOf(currentTab); prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex === tabs.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); } prevBtn.addEventListener('click', () => { const currentIndex = tabs.indexOf(currentTab); if (currentIndex > 0) changeTab(null, tabs[currentIndex - 1]); }); nextBtn.addEventListener('click', () => { const currentIndex = tabs.indexOf(currentTab); if (currentIndex < tabs.length - 1) changeTab(null, tabs[currentIndex + 1]); }); // --- INITIALIZATION --- renderAll(); updateNavButtons(); });
Scroll to Top