(function () { const wall = document.getElementById("notes-wall"); const form = document.getElementById("notes-form"); const authorInput = document.getElementById("note-author"); const contentInput = document.getElementById("note-content"); const authorFilter = document.getElementById("notes-author-filter"); let notesCache = []; if (!wall) return; function escapeHtml(str) { return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function renderNote(note) { const el = document.createElement("div"); el.className = "note"; el.innerHTML = `
${escapeHtml(note.author_name)}
${escapeHtml(note.content).replace(/\n/g, "
")}
`; return el; } function normaliseAuthor(author) { return (author || "").trim(); } function populateAuthorFilter(notes) { if (!authorFilter) return; const previousValue = authorFilter.value; const authors = Array.from( new Set(notes.map(note => normaliseAuthor(note.author_name)).filter(Boolean)) ).sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" })); authorFilter.innerHTML = ''; authors.forEach(author => { const option = document.createElement("option"); option.value = author; option.textContent = author; authorFilter.appendChild(option); }); authorFilter.value = authors.includes(previousValue) ? previousValue : ""; } function renderNotes() { wall.innerHTML = ""; const selectedAuthor = authorFilter ? authorFilter.value : ""; const notes = selectedAuthor ? notesCache.filter(note => normaliseAuthor(note.author_name) === selectedAuthor) : notesCache; if (notesCache.length === 0) { wall.innerHTML = "

No notes yet.

"; return; } if (notes.length === 0) { wall.innerHTML = "

No notes for this author.

"; return; } notes.forEach(note => { wall.appendChild(renderNote(note)); }); } async function loadNotes() { wall.innerHTML = "

Loading notes…

"; try { const res = await fetch("/api/notes"); if (!res.ok) throw new Error("Failed to fetch notes"); const notes = await res.json(); notesCache = notes; populateAuthorFilter(notesCache); renderNotes(); } catch (err) { console.error(err); wall.innerHTML = "

Could not load notes.

"; } } async function submitNote(e) { e.preventDefault(); const author = authorInput.value.trim(); const content = contentInput.value.trim(); if (!author || !content) return; form.querySelector("button").disabled = true; try { const res = await fetch("/api/notes", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ author_name: author, content: content, }), }); if (!res.ok) { const err = await res.json(); throw new Error(err.detail || "Failed to post note"); } contentInput.value = ""; await loadNotes(); } catch (err) { alert(err.message); } finally { form.querySelector("button").disabled = false; } } if (form) { form.addEventListener("submit", submitNote); } if (authorFilter) { authorFilter.addEventListener("change", renderNotes); } loadNotes(); })();