1document.addEventListener("DOMContentLoaded", () => {
2 document.querySelectorAll("time[datetime]").forEach(el => {
3 const d = new Date(el.getAttribute("datetime"));
4 if (!isNaN(d)) {
5 el.textContent = d.toLocaleString(undefined, {
6 day: "numeric", month: "short", year: "numeric",
7 hour: "2-digit", minute: "2-digit"
8 });
9 }
10 });
11
12 // FAB toggle
13 const fabToggle = document.getElementById("fab-toggle");
14 const fabActions = document.getElementById("fab-actions");
15 if (fabToggle && fabActions) {
16 fabToggle.addEventListener("click", () => {
17 const expanded = fabToggle.getAttribute("aria-expanded") === "true";
18 fabToggle.setAttribute("aria-expanded", String(!expanded));
19 fabActions.hidden = expanded;
20 });
21 // Collapse when a dialog opens from a FAB action
22 fabActions.querySelectorAll(".fab-action").forEach(btn => {
23 btn.addEventListener("click", () => {
24 fabToggle.setAttribute("aria-expanded", "false");
25 fabActions.hidden = true;
26 });
27 });
28 }
29
30 // New task form: set the action URL based on the selected project
31 const taskForm = document.getElementById("form-new-task");
32 const projectSelect = document.getElementById("nt-project");
33 if (taskForm && projectSelect) {
34 const updateAction = () => {
35 taskForm.action = "/projects/" + encodeURIComponent(projectSelect.value) + "/tasks";
36 };
37 updateAction();
38 projectSelect.addEventListener("change", updateAction);
39 }
40
41 // Reveal copy-to-clipboard buttons only when the API is available
42 // (requires a secure context: HTTPS or localhost).
43 if (navigator.clipboard) {
44 const copyIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>';
45 const checkIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m12 15 2 2 4-4"/><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>';
46 document.querySelectorAll(".js-copy-id").forEach(btn => {
47 btn.hidden = false;
48 btn.addEventListener("click", () => {
49 navigator.clipboard.writeText(btn.dataset.copy).then(() => {
50 btn.innerHTML = checkIcon;
51 setTimeout(() => { btn.innerHTML = copyIcon; }, 1500);
52 });
53 });
54 });
55 }
56});