`;
};
// --- EVENT HANDLING ---
const addEventListeners = () => {
// Add/Edit/Delete Tasks
document.querySelectorAll('.add-task-btn').forEach(btn => {
btn.onclick = (e) => openTaskModal(e.target.previousElementSibling.dataset.columnId);
});
document.querySelectorAll('.edit-task-btn').forEach(btn => {
btn.onclick = (e) => {
const taskId = e.currentTarget.dataset.taskId;
const { column, task } = findTask(taskId);
openTaskModal(column.id, task);
};
});
document.querySelectorAll('.delete-task-btn').forEach(btn => {
btn.onclick = (e) => deleteTask(e.currentTarget.dataset.taskId);
});
// Delete Column
document.querySelectorAll('.delete-column-btn').forEach(btn => {
btn.onclick = (e) => deleteColumn(e.currentTarget.dataset.columnId);
});
// Drag and Drop
const tasks = document.querySelectorAll('.task-card');
const taskLists = document.querySelectorAll('.task-list');
tasks.forEach(task => {
task.addEventListener('dragstart', () => {
task.classList.add('dragging');
});
task.addEventListener('dragend', () => {
task.classList.remove('dragging');
});
});
taskLists.forEach(list => {
list.addEventListener('dragover', e => {
e.preventDefault();
list.classList.add('drag-over');
});
list.addEventListener('dragleave', () => list.classList.remove('drag-over'));
list.addEventListener('drop', e => {
e.preventDefault();
list.classList.remove('drag-over');
const draggingTask = document.querySelector('.dragging');
if (draggingTask) {
const targetColumnId = list.dataset.columnId;
moveTask(draggingTask.id, targetColumnId);
}
});
});
};
// --- MODAL LOGIC ---
const openTaskModal = (columnId, task = null) => {
taskForm.reset();
document.getElementById('modal-title').textContent = task ? 'Edit Task' : 'Add New Task';
document.getElementById('column-id').value = columnId;
if (task) {
document.getElementById('task-id').value = task.id;
document.getElementById('task-title').value = task.title;
document.getElementById('task-description').value = task.description;
document.getElementById('task-priority').value = task.priority;
}
taskModal.classList.remove('hidden');
};
const closeTaskModal = () => {
taskModal.classList.add('hidden');
};
const handleSaveTask = () => {
const taskId = document.getElementById('task-id').value;
const columnId = document.getElementById('column-id').value;
const title = document.getElementById('task-title').value;
const description = document.getElementById('task-description').value;
const priority = document.getElementById('task-priority').value;
if (!title) {
alert("Title is required."); // Replace with a better notification if possible
return;
}
if (taskId) { // Editing existing task
const { task } = findTask(taskId);
if(task){
task.title = title;
task.description = description;
task.priority = priority;
}
} else { // Creating new task
const newTask = {
id: `task-${Date.now()}`,
title,
description,
priority
};
const column = boardState.columns.find(c => c.id === columnId);
if (column) {
column.tasks.push(newTask);
}
}
saveState();
renderBoard();
closeTaskModal();
};
// --- CRUD & DRAG/DROP LOGIC ---
const findTask = (taskId) => {
for (const column of boardState.columns) {
const task = column.tasks.find(t => t.id === taskId);
if (task) return { column, task };
}
return { column: null, task: null };
};
const deleteTask = (taskId) => {
const { column } = findTask(taskId);
if (column) {
column.tasks = column.tasks.filter(t => t.id !== taskId);
saveState();
renderBoard();
}
};
const addColumn = () => {
const title = prompt("Enter new column title:");
if (title) {
const newColumn = {
id: `col-${Date.now()}`,
title,
tasks: []
};
boardState.columns.push(newColumn);
saveState();
renderBoard();
}
};
const deleteColumn = (columnId) => {
if(confirm("Are you sure you want to delete this column and all its tasks?")){
boardState.columns = boardState.columns.filter(c => c.id !== columnId);
saveState();
renderBoard();
}
};
const moveTask = (taskId, targetColumnId) => {
const { column: sourceColumn, task } = findTask(taskId);
if (sourceColumn && task) {
// Remove from source
sourceColumn.tasks = sourceColumn.tasks.filter(t => t.id !== taskId);
// Add to target
const targetColumn = boardState.columns.find(c => c.id === targetColumnId);
if (targetColumn) {
targetColumn.tasks.push(task);
saveState();
renderBoard();
}
}
};
// --- PDF DOWNLOAD FUNCTIONALITY ---
const downloadPDF = () => {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(18);
doc.text("Team Collaboration Board Status", 14, 22);
doc.setFontSize(11);
doc.setTextColor(100);
doc.text(`Report Generated: ${new Date().toLocaleString('en-US')}`, 14, 29);
let startY = 40;
boardState.columns.forEach(column => {
if (startY > 260) { // Add new page if content overflows
doc.addPage();
startY = 20;
}
doc.setFontSize(14);
doc.setFont(undefined, 'bold');
doc.text(column.title, 14, startY);
startY += 7;
const tableColumn = ["Task Title", "Description", "Priority"];
const tableRows = [];
column.tasks.forEach(task => {
tableRows.push([task.title, task.description, task.priority]);
});
if (tableRows.length > 0) {
doc.autoTable({
head: [tableColumn],
body: tableRows,
startY: startY,
theme: 'grid',
headStyles: { fillColor: [59, 130, 246] }, // blue-500
});
startY = doc.autoTable.previous.finalY + 10;
} else {
doc.setFontSize(10);
doc.setFont(undefined, 'normal');
doc.text("- No tasks in this column -", 16, startY);
startY += 10;
}
});
doc.save("collaboration_board.pdf");
};
// --- INITIALIZATION ---
document.getElementById('add-column-button').onclick = addColumn;
saveTaskButton.onclick = handleSaveTask;
cancelTaskButton.onclick = closeTaskModal;
pdfDownloadButton.onclick = downloadPDF;
loadState();
renderBoard();
});