Baseret på brugerens gennemgang af siden i browser: - Ved succesfuld bestilling omdirigeres brugeren nu til en dedikeret GET /bestilling-modtaget i stedet for en inline besked, der skjulte vinkataloget — brugeren vil fortsat kunne se hvad de har bestilt. Siden gør det eksplicit at bestillingen først er gyldig ved modtaget betaling, og linker tilbage til bestillingssiden. - Rettet et CSS-layoutbug på smalle skærme: flex-basis (sat til 600px/260px til brug for bredde i to-kolonne-layoutet) blev fejlagtigt fortolket som højde, når layoutet skiftede til flex-direction: column under 800px, hvilket gav et stort tomt mellemrum mellem vinkatalog og sidebar. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
124 lines
4.2 KiB
JavaScript
124 lines
4.2 KiB
JavaScript
(function () {
|
|
function formatAmount(n) {
|
|
return n.toFixed(2);
|
|
}
|
|
|
|
function showMessage(el, text, kind) {
|
|
el.textContent = text;
|
|
el.className = "form-message " + kind;
|
|
el.hidden = false;
|
|
}
|
|
|
|
async function extractErrorDetail(response) {
|
|
try {
|
|
const body = await response.json();
|
|
if (typeof body.detail === "string") return body.detail;
|
|
if (Array.isArray(body.detail)) {
|
|
return body.detail.map((e) => e.msg || JSON.stringify(e)).join(", ");
|
|
}
|
|
return JSON.stringify(body.detail);
|
|
} catch (err) {
|
|
return "Der skete en fejl. Prøv igen.";
|
|
}
|
|
}
|
|
|
|
const orderForm = document.getElementById("order-form");
|
|
if (orderForm) {
|
|
const qtyInputs = Array.from(orderForm.querySelectorAll(".qty-input"));
|
|
const totalEurEl = document.getElementById("total-eur");
|
|
const totalDkkEl = document.getElementById("total-dkk");
|
|
const rateAttr = orderForm.dataset.eurDkkRate;
|
|
const rate = rateAttr ? parseFloat(rateAttr) : null;
|
|
|
|
function recalculate() {
|
|
let totalEur = 0;
|
|
qtyInputs.forEach((input) => {
|
|
const qty = parseInt(input.value, 10) || 0;
|
|
const price = parseFloat(input.dataset.price) || 0;
|
|
const rowTotal = qty * price;
|
|
totalEur += rowTotal;
|
|
const cell = orderForm.querySelector(
|
|
'[data-row-total-for="' + input.dataset.offeringId + '"]'
|
|
);
|
|
if (cell) cell.textContent = formatAmount(rowTotal);
|
|
});
|
|
if (totalEurEl) totalEurEl.textContent = formatAmount(totalEur);
|
|
if (totalDkkEl && rate) totalDkkEl.textContent = formatAmount(totalEur * rate);
|
|
}
|
|
|
|
qtyInputs.forEach((input) => input.addEventListener("input", recalculate));
|
|
recalculate();
|
|
|
|
orderForm.addEventListener("submit", async function (event) {
|
|
event.preventDefault();
|
|
const messageEl = document.getElementById("order-message");
|
|
const orderLines = qtyInputs
|
|
.map((input) => ({
|
|
wine_offering_id: parseInt(input.dataset.offeringId, 10),
|
|
quantity: parseInt(input.value, 10) || 0,
|
|
}))
|
|
.filter((line) => line.quantity > 0);
|
|
|
|
if (orderLines.length === 0) {
|
|
showMessage(messageEl, "Vælg mindst én vin med et antal større end 0.", "error");
|
|
return;
|
|
}
|
|
|
|
const payload = {
|
|
participant: {
|
|
name: orderForm.elements["name"].value,
|
|
email: orderForm.elements["email"].value,
|
|
phone: orderForm.elements["phone"].value,
|
|
is_active: orderForm.elements["is_active"].checked,
|
|
},
|
|
order_lines: orderLines,
|
|
};
|
|
|
|
try {
|
|
const response = await fetch("/public/orders", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(payload),
|
|
});
|
|
if (response.ok) {
|
|
window.location.href = "/bestilling-modtaget";
|
|
return;
|
|
} else {
|
|
showMessage(messageEl, await extractErrorDetail(response), "error");
|
|
}
|
|
} catch (err) {
|
|
showMessage(messageEl, "Kunne ikke sende bestillingen. Tjek din internetforbindelse og prøv igen.", "error");
|
|
}
|
|
});
|
|
}
|
|
|
|
const signupForm = document.getElementById("signup-form");
|
|
if (signupForm) {
|
|
signupForm.addEventListener("submit", async function (event) {
|
|
event.preventDefault();
|
|
const messageEl = document.getElementById("signup-message");
|
|
const payload = {
|
|
name: signupForm.elements["name"].value,
|
|
email: signupForm.elements["email"].value,
|
|
};
|
|
|
|
try {
|
|
const response = await fetch("/public/signup", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(payload),
|
|
});
|
|
if (response.ok) {
|
|
signupForm.querySelectorAll("label, button[type=submit]").forEach((el) => {
|
|
el.hidden = true;
|
|
});
|
|
showMessage(messageEl, "Tak! Du er nu tilmeldt.", "success");
|
|
} else {
|
|
showMessage(messageEl, await extractErrorDetail(response), "error");
|
|
}
|
|
} catch (err) {
|
|
showMessage(messageEl, "Kunne ikke sende tilmeldingen. Tjek din internetforbindelse og prøv igen.", "error");
|
|
}
|
|
});
|
|
}
|
|
})();
|