Add static assets
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
// 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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user