${task.title}
`;
columns[task.status].appendChild(card);
});
}
function renderStatusChart() {
const statusCtx = document.getElementById('statusChart')?.getContext('2d');
const statusData = tasks.reduce((acc, t) => {
acc[t.status] = (acc[t.status] || 0) + 1;
return acc;
}, {});
if (statusCtx) {
if (charts.status) charts.status.destroy();
charts.status = new Chart(statusCtx, {
type: 'pie',
data: {
labels: ['To Do', 'In Progress', 'Done'],
datasets: [{ data: [statusData['To Do']||0, statusData['In Progress']||0, statusData['Done']||0], backgroundColor: ['#3b82f6', '#f59e0b', '#10b981'] }]
},
options: { responsive: true, maintainAspectRatio: false }
});
}
}
function renderManageTaskTable() {
const tableBody = document.getElementById('task-table-body');
tableBody.innerHTML = '';
tasks.forEach(t => {
const row = document.createElement('tr');
row.innerHTML = `
${t.title} |
${t.assignee} |
${t.status} |
|
`;
tableBody.appendChild(row);
});
}
// --- EVENT HANDLERS & GLOBAL FUNCTIONS ---
wipLimitInput.addEventListener('change', (e) => {
const newLimit = parseInt(e.target.value);
if (newLimit > 0) {
wipLimit = newLimit;
renderAll();
}
});
addTaskForm.addEventListener('submit', (e) => {
e.preventDefault();
const taskId = document.getElementById('task-id').value;
const taskRecord = {
title: document.getElementById('task-title').value,
assignee: document.getElementById('task-assignee').value
};
if (taskId) { // Update
const index = tasks.findIndex(t => t.id == taskId);
tasks[index] = { ...tasks[index], ...taskRecord };
} else { // Add new
const newId = tasks.length > 0 ? Math.max(...tasks.map(t => t.id)) + 1 : 1;
tasks.push({ ...taskRecord, id: newId, status: 'To Do' });
}
cancelEdit();
renderAll();
});
window.moveTask = (id, direction) => {
const task = tasks.find(t => t.id === id);
if (!task) return;
const statuses = ['To Do', 'In Progress', 'Done'];
const currentIndex = statuses.indexOf(task.status);
let newIndex = currentIndex;
if (direction === 'next' && currentIndex < statuses.length - 1) newIndex++;
if (direction === 'prev' && currentIndex > 0) newIndex--;
task.status = statuses[newIndex];
renderAll();
};
window.editTask = (id) => {
const task = tasks.find(t => t.id === id);
if (!task) return;
document.getElementById('task-id').value = task.id;
document.getElementById('task-title').value = task.title;
document.getElementById('task-assignee').value = task.assignee;
document.getElementById('config-form-title').textContent = 'Edit Task';
document.getElementById('submit-task-btn').textContent = 'Update Task';
document.getElementById('cancel-edit-btn').classList.remove('hidden');
};
window.cancelEdit = () => {
addTaskForm.reset();
document.getElementById('task-id').value = '';
document.getElementById('config-form-title').textContent = 'Add New Task';
document.getElementById('submit-task-btn').textContent = 'Add Task';
document.getElementById('cancel-edit-btn').classList.add('hidden');
};
window.deleteTask = (id) => {
if (confirm('Are you sure you want to delete this task?')) {
tasks = tasks.filter(t => t.id !== id);
renderAll();
}
};
window.showTab = (tabName) => {
currentTab = tabName;
['dashboard', 'config'].forEach(t => {
document.getElementById(`${t}-tab`).classList.add('hidden');
document.getElementById(`tab-${t}-btn`).classList.replace('active', 'inactive');
});
document.getElementById(`${tabName}-tab`).classList.remove('hidden');
document.getElementById(`tab-${tabName}-btn`).classList.replace('inactive', 'active');
updateNavButtons();
};
window.navigateTabs = (direction) => {
const tabOrder = ['dashboard', 'config'];
const currentIndex = tabOrder.indexOf(currentTab);
let newIndex = currentIndex;
if (direction === 'next' && currentIndex < tabOrder.length - 1) newIndex++;
else if (direction === 'prev' && currentIndex > 0) newIndex--;
showTab(tabOrder[newIndex]);
};
function updateNavButtons() {
document.getElementById('prev-btn').disabled = (currentTab === 'dashboard');
document.getElementById('next-btn').disabled = (currentTab === 'config');
}
window.downloadPDF = async () => {
const { jsPDF } = window.jspdf;
const content = document.getElementById('pdf-content');
const button = document.querySelector('#pdf-button-container button');
if (!content || !button) { return; }
const originalButtonText = button.innerHTML;
button.disabled = true;
button.innerHTML = `Generating...`;
const title = document.createElement('h2');
title.className = 'text-2xl font-bold mb-6 text-center text-gray-800';
title.innerText = 'Work in Progress Report';
content.prepend(title);
try {
const canvas = await html2canvas(content, { scale: 2, useCORS: true, backgroundColor: '#ffffff', windowWidth: content.scrollWidth, windowHeight: content.scrollHeight });
const imgData = canvas.toDataURL('image/png');
const imgWidth = canvas.width;
const imgHeight = canvas.height;
const orientation = imgWidth > imgHeight ? 'l' : 'p';
const pdf = new jsPDF(orientation, 'px', [imgWidth, imgHeight]);
pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight);
pdf.save('WIP_Dashboard.pdf');
} catch (error) {
console.error('Error generating PDF:', error);
} finally {
title.remove();
button.disabled = false;
button.innerHTML = originalButtonText;
}
};
// --- INITIALIZATION ---
renderAll();
updateNavButtons();
});