Files
nouri-App/nouri/static/js/planner.js
T

82 lines
2.9 KiB
JavaScript

(() => {
const getCsrfToken = () => {
const meta = document.querySelector('meta[name="csrf-token"]');
return meta ? meta.getAttribute("content") : "";
};
const initWeekDragAndDrop = () => {
const board = document.querySelector(".week-board");
if (!board) return;
let draggedEntry = null;
board.querySelectorAll(".draggable-plan-entry").forEach((entry) => {
if (entry.getAttribute("draggable") !== "true") return;
entry.addEventListener("dragstart", () => {
draggedEntry = entry;
entry.classList.add("is-dragging");
});
entry.addEventListener("dragend", () => {
entry.classList.remove("is-dragging");
draggedEntry = null;
board.querySelectorAll(".drop-slot").forEach((slot) => slot.classList.remove("is-drag-over"));
});
});
board.querySelectorAll(".drop-slot").forEach((slot) => {
slot.addEventListener("dragover", (event) => {
event.preventDefault();
if (!draggedEntry) return;
slot.classList.add("is-drag-over");
});
slot.addEventListener("dragleave", () => {
slot.classList.remove("is-drag-over");
});
slot.addEventListener("drop", async (event) => {
event.preventDefault();
slot.classList.remove("is-drag-over");
if (!draggedEntry) return;
// Keep DnD lightweight: move on the server, then refresh into the canonical rendered state.
const moveUrl = draggedEntry.dataset.moveUrl;
const payload = new URLSearchParams({
csrf_token: getCsrfToken(),
target_date: slot.dataset.targetDate,
target_daypart_id: slot.dataset.targetDaypartId,
});
try {
const response = await fetch(moveUrl, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
},
body: payload.toString(),
});
if (!response.ok) {
throw new Error("move failed");
}
const result = await response.json();
if (result.redirect_url) {
window.location.href = result.redirect_url;
} else {
window.location.reload();
}
} catch (_error) {
window.location.reload();
}
});
});
};
document.addEventListener("DOMContentLoaded", () => {
initWeekDragAndDrop();
});
})();