${t.name}
${t.skills.map(s => `${s}`).join(' ')}
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) => `
`).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 = `${index+1}. ${rec.name}
${index === 0 ? 'Top Recommendation
' : ''}${rec.reason}
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'}
${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();
});
