// 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 = '

Nothing circled yet — tap dates on the calendar above.

'; 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); }); });