Files
feedc0de fe666111f8
Publish and deploy birthday invitation / Check JavaScript (push) Successful in 2s
Publish and deploy birthday invitation / Build and push (push) Successful in 8s
Publish and deploy birthday invitation / Deploy to Kubernetes (push) Successful in 1m49s
Add party slideshow photo upload link
2026-10-14 21:16:33 +02:00

137 lines
4.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const loading = document.querySelector("#loading");
const form = document.querySelector("#rsvp-form");
const invalidState = document.querySelector("#invalid-state");
const invalidMessage = document.querySelector("#invalid-message");
const successState = document.querySelector("#success-state");
const greeting = document.querySelector("#guest-greeting");
const companionWrap = document.querySelector("#companion-wrap");
const companionInput = document.querySelector("#companion-name");
const errorBox = document.querySelector("#form-error");
const submitButton = document.querySelector("#submit-button");
const updateNote = document.querySelector("#update-note");
const changeButton = document.querySelector("#change-button");
const successCopy = document.querySelector("#success-copy");
const inviteCard = document.querySelector("#invite-card");
const inviteImage = document.querySelector("#invite-image");
const pdfLink = document.querySelector("#pdf-link");
const inviteColumn = document.querySelector(".invite-column");
const photoUpload = document.querySelector("#photo-upload");
const tokenMatch = window.location.pathname.match(/^\/i\/([A-Za-z0-9_-]+)\/?$/);
const token = tokenMatch?.[1];
function show(element) { element.hidden = false; }
function hide(element) { element.hidden = true; }
function toggleCompanion() {
const selected = form.elements.answer.value;
companionWrap.hidden = selected !== "with_someone";
companionInput.required = selected === "with_someone";
}
function populate(invite) {
const assetBase = `/api/invites/${encodeURIComponent(token)}/assets`;
inviteImage.src = `${assetBase}/image`;
inviteCard.href = `${assetBase}/pdf`;
pdfLink.href = `${assetBase}/pdf`;
greeting.textContent = invite.guestName ? `Hallo ${invite.guestName}!` : "Hallo!";
show(photoUpload);
if (invite.answer) {
const radio = form.querySelector(`[name="answer"][value="${invite.answer}"]`);
if (radio) radio.checked = true;
companionInput.value = invite.companionName || "";
show(updateNote);
submitButton.textContent = "Antwort aktualisieren";
}
toggleCompanion();
}
async function loadInvitation() {
if (!token) {
hide(inviteColumn);
hide(loading);
show(invalidState);
invalidMessage.textContent = "Bitte öffne den persönlichen Link aus deiner Einladung.";
return;
}
try {
const response = await fetch(`/api/invites/${encodeURIComponent(token)}`);
const data = await response.json();
if (!response.ok) throw new Error(data.error || "Einladung nicht gefunden.");
populate(data);
hide(loading);
show(form);
} catch (error) {
hide(inviteColumn);
hide(loading);
show(invalidState);
invalidMessage.textContent = error.message;
}
}
form.addEventListener("change", event => {
if (event.target.name === "answer") {
hide(errorBox);
toggleCompanion();
if (!companionWrap.hidden) companionInput.focus();
}
});
form.addEventListener("submit", async event => {
event.preventDefault();
hide(errorBox);
const answer = form.elements.answer.value;
const companionName = companionInput.value.trim();
if (!answer) {
errorBox.textContent = "Bitte wähle eine Antwort aus.";
show(errorBox);
return;
}
if (answer === "with_someone" && !companionName) {
errorBox.textContent = "Bitte verrate uns den Namen deiner Begleitung.";
show(errorBox);
companionInput.focus();
return;
}
submitButton.disabled = true;
submitButton.textContent = "Wird gespeichert …";
try {
const response = await fetch(`/api/invites/${encodeURIComponent(token)}/rsvp`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ answer, companionName })
});
const data = await response.json();
if (!response.ok) throw new Error(data.error || "Antwort konnte nicht gespeichert werden.");
const messages = {
not_coming: "Schade, dass du diesmal nicht dabei sein kannst. Danke fürs Bescheidgeben!",
alone: "Wunderbar – wir freuen uns darauf, mit dir zu feiern!",
with_someone: `Wunderbar – wir freuen uns auf euch${data.companionName ? ` und besonders auch auf ${data.companionName}` : ""}!`
};
successCopy.textContent = messages[data.answer];
hide(form);
show(successState);
successState.focus();
} catch (error) {
errorBox.textContent = error.message;
show(errorBox);
} finally {
submitButton.disabled = false;
submitButton.textContent = "Antwort aktualisieren";
}
});
changeButton.addEventListener("click", () => {
hide(successState);
show(form);
show(updateNote);
submitButton.textContent = "Antwort aktualisieren";
form.querySelector("input:checked")?.focus();
});
loadInvitation();