99 lines
2.3 KiB
JavaScript
99 lines
2.3 KiB
JavaScript
const STATES = [
|
|
{ key: "completed", label: "Completed" },
|
|
{ key: "manager_review", label: "Manager Review" },
|
|
{ key: "in_progress", label: "In Progress" },
|
|
{ key: "not_started", label: "Not Started" },
|
|
{ key: "comments", label: "Comments" }
|
|
];
|
|
|
|
let draggedItemId = null;
|
|
|
|
function countByState(items) {
|
|
return items.reduce((acc, item) => {
|
|
acc[item.state] = (acc[item.state] || 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
}
|
|
|
|
function createCard(item) {
|
|
const card = document.createElement("div");
|
|
card.className = "kanban-card";
|
|
card.draggable = true;
|
|
card.dataset.id = item.id;
|
|
card.textContent = item.title;
|
|
|
|
card.addEventListener("dragstart", () => {
|
|
draggedItemId = item.id;
|
|
card.classList.add("dragging");
|
|
});
|
|
|
|
card.addEventListener("dragend", () => {
|
|
draggedItemId = null;
|
|
card.classList.remove("dragging");
|
|
});
|
|
|
|
return card;
|
|
}
|
|
|
|
function createColumn(state, items, counts) {
|
|
const col = document.createElement("div");
|
|
col.className = "kanban-column";
|
|
col.dataset.state = state.key;
|
|
|
|
const header = document.createElement("h3");
|
|
header.innerHTML = `
|
|
<span class="kanban-title">${state.label}</span>
|
|
<span class="kanban-count">${counts[state.key] || 0}</span>
|
|
`;
|
|
|
|
const list = document.createElement("div");
|
|
list.className = "kanban-list";
|
|
|
|
list.addEventListener("dragover", e => e.preventDefault());
|
|
|
|
list.addEventListener("drop", async () => {
|
|
if (!draggedItemId) return;
|
|
|
|
const res = await fetch(`/api/competencies/items/${draggedItemId}/state`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ state: state.key })
|
|
});
|
|
|
|
if (res.ok) {
|
|
loadBoard(); // simple & safe re-render
|
|
} else {
|
|
alert("Failed to update state");
|
|
}
|
|
});
|
|
|
|
items
|
|
.filter(i => i.state === state.key)
|
|
.forEach(i => list.appendChild(createCard(i)));
|
|
|
|
col.appendChild(header);
|
|
col.appendChild(list);
|
|
|
|
return col;
|
|
}
|
|
|
|
function renderBoard(items) {
|
|
const board = document.getElementById("kanban-board");
|
|
board.innerHTML = "";
|
|
|
|
const counts = countByState(items);
|
|
|
|
STATES.forEach(state => {
|
|
board.appendChild(createColumn(state, items, counts));
|
|
});
|
|
}
|
|
|
|
|
|
async function loadBoard() {
|
|
const res = await fetch("/api/competencies/items");
|
|
const items = await res.json();
|
|
renderBoard(items);
|
|
}
|
|
|
|
loadBoard();
|