137 lines
4.7 KiB
JavaScript
137 lines
4.7 KiB
JavaScript
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();
|