`).join('');
card.innerHTML = `
`;
return card;
};
/**
* Populates the assignee dropdown in the task creation form.
*/
const populateAssigneeDropdown = () => {
taskAssigneeSelect.innerHTML = teamMembers.map(m => ``).join('');
};
/**
* Handles the creation of a new task from the form.
*/
const handleTaskSubmit = (e) => {
e.preventDefault();
const title = document.getElementById('taskTitle').value;
const assignee = taskAssigneeSelect.value;
if (!title.trim()) {
alert('Please enter a task title.');
return;
}
const newTask = {
id: nextTaskId++,
title: title,
assignee: assignee,
status: 'To Do',
discussions: []
};
tasks.push(newTask);
taskForm.reset();
renderBoard();
};
/**
* Generates and downloads a PDF report of all tasks.
*/
const downloadPDF = () => {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(22);
doc.text('Task Discussion Report', 14, 20);
let yPos = 30;
tasks.forEach(task => {
if (yPos > 260) {
doc.addPage();
yPos = 20;
}
doc.setFontSize(14);
doc.setFont('helvetica', 'bold');
doc.text(`Task: ${task.title}`, 14, yPos);
yPos += 7;
doc.setFontSize(10);
doc.setFont('helvetica', 'normal');
doc.text(`Assignee: ${task.assignee} | Status: ${task.status}`, 14, yPos);
yPos += 7;
if (task.discussions.length > 0) {
doc.setFont('helvetica', 'bold');
doc.text('Discussion:', 14, yPos);
yPos += 5;
doc.setFont('helvetica', 'normal');
task.discussions.forEach(comment => {
if (yPos > 270) {
doc.addPage();
yPos = 20;
}
const splitText = doc.splitTextToSize(`- ${comment.user}: ${comment.text}`, 180);
doc.text(splitText, 16, yPos);
yPos += (splitText.length * 4) + 2;
});
}
yPos += 5; // Extra space between tasks
});
doc.save('task-discussion-report.pdf');
};
// --- Event Listeners ---
taskForm.addEventListener('submit', handleTaskSubmit);
pdfDownloadBtn.addEventListener('click', downloadPDF);
// Event delegation for dynamic elements on the board
kanbanBoard.addEventListener('change', (e) => {
if (e.target.classList.contains('status-select')) {
const taskId = parseInt(e.target.dataset.taskId);
const newStatus = e.target.value;
const task = tasks.find(t => t.id === taskId);
if (task) {
task.status = newStatus;
renderBoard(); // Re-render to move the card
}
}
});
kanbanBoard.addEventListener('click', (e) => {
if (e.target.classList.contains('add-comment-btn')) {
const card = e.target.closest('.task-card');
const taskId = parseInt(card.dataset.taskId);
const task = tasks.find(t => t.id === taskId);
const textarea = card.querySelector('.discussion-input');
const commentText = textarea.value.trim();
if (task && commentText) {
// For simplicity, we'll use the assignee's name as the commenter
task.discussions.push({ user: task.assignee, text: commentText });
textarea.value = '';
renderBoard(); // Re-render to show the new comment
}
}
});
// --- Initial Setup ---
const initializeTool = () => {
populateAssigneeDropdown();
renderBoard();
};
initializeTool();
});
${task.title}
Assignee: ${task.assignee}
Discussion
${discussionsHtml}
