116 lines
4.0 KiB
JavaScript
116 lines
4.0 KiB
JavaScript
const tableBody = document.querySelector("#visitors");
|
|
const count = document.querySelector("#count");
|
|
const message = document.querySelector("#message");
|
|
const csvButton = document.querySelector("#export-csv");
|
|
const printButton = document.querySelector("#print-list");
|
|
let visitors = [];
|
|
|
|
function formatDateTime(value) {
|
|
return new Intl.DateTimeFormat("da-DK", {
|
|
dateStyle: "short",
|
|
timeStyle: "short"
|
|
}).format(new Date(value));
|
|
}
|
|
|
|
function showError(text) {
|
|
message.textContent = text;
|
|
message.className = "notice error";
|
|
message.hidden = false;
|
|
}
|
|
|
|
function escapeHtml(value) {
|
|
return String(value ?? "")
|
|
.replaceAll("&", "&")
|
|
.replaceAll("<", "<")
|
|
.replaceAll(">", ">")
|
|
.replaceAll('"', """)
|
|
.replaceAll("'", "'");
|
|
}
|
|
|
|
async function loadVisitors() {
|
|
csvButton.disabled = true;
|
|
printButton.disabled = true;
|
|
try {
|
|
const response = await fetch("/api/visitors");
|
|
if (!response.ok) {
|
|
showError("Listen kunne ikke hentes. Tjek admin-login og databaseforbindelse.");
|
|
count.textContent = "Fejl";
|
|
return;
|
|
}
|
|
|
|
visitors = await response.json();
|
|
updateParticipantMap(visitors);
|
|
message.hidden = true;
|
|
csvButton.disabled = false;
|
|
printButton.disabled = false;
|
|
count.textContent = `${visitors.length} registreret`;
|
|
|
|
if (visitors.length === 0) {
|
|
tableBody.innerHTML = '<tr><td colspan="8" class="empty">Ingen besøgende registreret endnu.</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tableBody.innerHTML = visitors.map((visitor) => `
|
|
<tr>
|
|
<td>${escapeHtml(visitor.name)}</td>
|
|
<td>${escapeHtml(visitor.streetAddress)}</td>
|
|
<td>${escapeHtml(visitor.postalCode)}</td>
|
|
<td>${escapeHtml(visitor.city)}</td>
|
|
<td>${escapeHtml(visitor.birthday)}</td>
|
|
<td><a href="mailto:${escapeHtml(visitor.email)}">${escapeHtml(visitor.email)}</a></td>
|
|
<td>${escapeHtml(formatDateTime(visitor.createdAt))}</td>
|
|
<td class="no-print"><button type="button" class="delete-button" data-id="${visitor.id}" aria-label="Slet ${escapeHtml(visitor.name)}">Slet</button></td>
|
|
</tr>
|
|
`).join("");
|
|
} catch {
|
|
showError("Der er ikke forbindelse til besøgslisten lige nu.");
|
|
count.textContent = "Fejl";
|
|
}
|
|
}
|
|
|
|
tableBody.addEventListener("click", async (event) => {
|
|
const button = event.target.closest("button[data-id]");
|
|
if (!button || button.disabled) return;
|
|
const visitor = visitors.find((item) => String(item.id) === button.dataset.id);
|
|
if (!visitor || !window.confirm(`Slet registreringen for ${visitor.name}? Dette kan ikke fortrydes.`)) return;
|
|
button.disabled = true;
|
|
csvButton.disabled = true;
|
|
printButton.disabled = true;
|
|
try {
|
|
const response = await fetch(`/api/visitors/${visitor.id}`, { method: "DELETE" });
|
|
if (!response.ok && response.status !== 404) throw new Error("Sletning mislykkedes.");
|
|
await loadVisitors();
|
|
} catch {
|
|
showError("Registreringen kunne ikke slettes. Prøv igen.");
|
|
button.disabled = false;
|
|
csvButton.disabled = false;
|
|
printButton.disabled = false;
|
|
}
|
|
});
|
|
|
|
function csvCell(value) {
|
|
let text = String(value ?? "");
|
|
// Prevent spreadsheet programs from evaluating visitor input as formulas.
|
|
if (/^[\s]*[=+@-]/.test(text)) text = "'" + text;
|
|
return `"${text.replaceAll('"', '""')}"`;
|
|
}
|
|
|
|
csvButton.addEventListener("click", () => {
|
|
const rows = [
|
|
["Navn", "Vejnavn og husnummer", "Postnummer", "Postby", "Fødselsdag", "Email", "Registreret"],
|
|
...visitors.map((visitor) => [visitor.name, visitor.streetAddress, visitor.postalCode,
|
|
visitor.city, visitor.birthday, visitor.email, formatDateTime(visitor.createdAt)])
|
|
];
|
|
const csv = "\uFEFF" + rows.map((row) => row.map(csvCell).join(";")).join("\r\n") + "\r\n";
|
|
const url = URL.createObjectURL(new Blob([csv], { type: "text/csv;charset=utf-8" }));
|
|
const link = document.createElement("a");
|
|
link.href = url;
|
|
link.download = "skydesportens-dag-besogende.csv";
|
|
link.click();
|
|
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
});
|
|
|
|
printButton.addEventListener("click", () => window.print());
|
|
|
|
loadVisitors();
|