103 lines
2.4 KiB
JavaScript
Executable File
103 lines
2.4 KiB
JavaScript
Executable File
(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");
|
|
|
|
if (!wall) return;
|
|
|
|
function escapeHtml(str) {
|
|
return str
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
|
|
function renderNote(note) {
|
|
const el = document.createElement("div");
|
|
el.className = "note";
|
|
|
|
el.innerHTML = `
|
|
<div class="note-meta">
|
|
<span class="note-author">${escapeHtml(note.author_name)}</span>
|
|
<time datetime="${note.created_at}">
|
|
${new Date(note.created_at).toLocaleString()}
|
|
</time>
|
|
</div>
|
|
<div class="note-content">
|
|
${escapeHtml(note.content).replace(/\n/g, "<br>")}
|
|
</div>
|
|
`;
|
|
|
|
return el;
|
|
}
|
|
|
|
async function loadNotes() {
|
|
wall.innerHTML = "<p>Loading notes…</p>";
|
|
|
|
try {
|
|
const res = await fetch("/api/notes");
|
|
if (!res.ok) throw new Error("Failed to fetch notes");
|
|
|
|
const notes = await res.json();
|
|
wall.innerHTML = "";
|
|
|
|
if (notes.length === 0) {
|
|
wall.innerHTML = "<p>No notes yet.</p>";
|
|
return;
|
|
}
|
|
|
|
notes.forEach(note => {
|
|
wall.appendChild(renderNote(note));
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
wall.innerHTML = "<p>Could not load notes.</p>";
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
loadNotes();
|
|
})();
|