Files
2026-06-10 08:32:46 +02:00

113 lines
3.6 KiB
JavaScript

// Create page: pick dates on the calendar, optionally give each a time.
const picked = new Map(); // dateStr -> time ("" if none)
const today = todayStr();
const cal = new Calendar(document.getElementById("calendar"), {
canClick: (ds) => ds >= today,
isPicked: (ds) => picked.has(ds),
onToggle: (ds) => {
if (picked.has(ds)) picked.delete(ds);
else picked.set(ds, "");
},
afterToggle: renderPickedList,
decorate: (ds, cell) => {
const t = picked.get(ds);
if (t) {
const chip = document.createElement("span");
chip.className = "timechip";
chip.textContent = t;
cell.appendChild(chip);
}
},
});
const listEl = document.getElementById("picked-list");
function renderPickedList() {
listEl.innerHTML = "";
if (picked.size === 0) {
listEl.innerHTML = '<p class="empty">Nothing circled yet — tap dates on the calendar above.</p>';
return;
}
for (const ds of [...picked.keys()].sort()) {
const row = document.createElement("div");
row.className = "picked-row";
const d = document.createElement("span");
d.className = "d";
d.textContent = formatDate(ds);
const time = document.createElement("input");
time.type = "time";
time.value = picked.get(ds);
time.setAttribute("aria-label", "Time for " + formatDate(ds) + " (optional)");
time.addEventListener("change", () => {
picked.set(ds, time.value);
cal.render(); // refresh time chips
});
const rm = document.createElement("button");
rm.type = "button";
rm.className = "rm";
rm.textContent = "Remove";
rm.addEventListener("click", () => {
picked.delete(ds);
renderPickedList();
cal.render();
});
row.append(d, time, rm);
listEl.appendChild(row);
}
}
const errEl = document.getElementById("error");
const createBtn = document.getElementById("create-btn");
createBtn.addEventListener("click", async () => {
errEl.textContent = "";
const title = document.getElementById("title").value.trim();
if (!title) { errEl.textContent = "Give the plan a name first."; return; }
if (picked.size === 0) { errEl.textContent = "Circle at least one date on the calendar."; return; }
createBtn.disabled = true;
try {
const res = await fetch("/api/polls", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title,
description: document.getElementById("description").value.trim(),
options: [...picked.entries()].map(([date, time]) => ({ date, time })),
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || "Something went wrong.");
const shareURL = location.origin + "/p/" + data.id;
const adminURL = shareURL + "?admin=" + data.adminToken;
document.getElementById("share-url").value = shareURL;
document.getElementById("admin-url").value = adminURL;
document.getElementById("open-poll").href = adminURL;
document.getElementById("create-view").hidden = true;
document.getElementById("done-view").hidden = false;
window.scrollTo(0, 0);
} catch (e) {
errEl.textContent = e.message;
} finally {
createBtn.disabled = false;
}
});
document.querySelectorAll("[data-copy]").forEach((btn) => {
btn.addEventListener("click", async () => {
const input = document.getElementById(btn.dataset.copy);
input.select();
try { await navigator.clipboard.writeText(input.value); } catch { document.execCommand("copy"); }
const old = btn.textContent;
btn.textContent = "Copied";
setTimeout(() => (btn.textContent = old), 1200);
});
});