forked from Aaron/Kino-Website
refactor: redistribute main.ts logic into Astro components
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<section id="checkout-view" class="hidden" style="padding: 40px 20px;">
|
||||
<section id="checkout-view" style="padding: 40px 20px;">
|
||||
<div class="checkout-container">
|
||||
<div class="progress-bar">
|
||||
<div class="step active" id="step-1-indicator">1</div>
|
||||
@@ -50,3 +50,189 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
import { currentUser, users, cart, emptyCart, occupiedSeatsData, updateCart, updateOccupiedSeats } from "../scripts/bigConstants";
|
||||
|
||||
function formatCheckoutEuro(value: number) {
|
||||
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
||||
}
|
||||
|
||||
let selectedPaymentMethod = "";
|
||||
|
||||
function setCheckoutStep(step: number) {
|
||||
const step1 = document.getElementById("checkout-step-1");
|
||||
const step2 = document.getElementById("checkout-step-2");
|
||||
const step3 = document.getElementById("checkout-step-3");
|
||||
step1?.classList.toggle("hidden", step !== 1);
|
||||
step2?.classList.toggle("hidden", step !== 2);
|
||||
step3?.classList.toggle("hidden", step !== 3);
|
||||
|
||||
const line1 = document.getElementById("line-1");
|
||||
const line2 = document.getElementById("line-2");
|
||||
const indicator1 = document.getElementById("step-1-indicator");
|
||||
const indicator2 = document.getElementById("step-2-indicator");
|
||||
const indicator3 = document.getElementById("step-3-indicator");
|
||||
|
||||
indicator1?.classList.add("active");
|
||||
indicator2?.classList.toggle("active", step >= 2);
|
||||
indicator3?.classList.toggle("active", step >= 3);
|
||||
line1?.classList.toggle("active", step >= 2);
|
||||
line2?.classList.toggle("active", step >= 3);
|
||||
}
|
||||
|
||||
function renderCheckout() {
|
||||
const summaryList = document.getElementById("checkout-summary-list");
|
||||
const totalDisplay = document.getElementById("checkout-total-display");
|
||||
const vatDisplay = document.getElementById("checkout-vat-display");
|
||||
const nextButton = document.getElementById("btn-next-step-2");
|
||||
|
||||
if (!summaryList) return;
|
||||
summaryList.innerHTML = "";
|
||||
|
||||
const total = cart.reduce((sum: number, item: any) => sum + Number(item.price || 0), 0);
|
||||
const vat = total - total / 1.19;
|
||||
|
||||
cart.forEach((item: any) => {
|
||||
const row = document.createElement("div");
|
||||
row.style.cssText = "display:flex; justify-content:space-between; gap:12px; margin-bottom:10px; font-size:0.95rem;";
|
||||
const infoText = item.category === "movie"
|
||||
? `Sitz ${item.seatId || "-"} | ${item.hall || "-"} | ${item.time || "-"} Uhr`
|
||||
: `${item.time || "Standard"} | ${item.hall || "-"}`;
|
||||
row.innerHTML = `<span>${item.title} (${infoText})</span><span>${formatCheckoutEuro(item.price)}</span>`;
|
||||
summaryList.appendChild(row);
|
||||
});
|
||||
|
||||
if (totalDisplay) totalDisplay.innerText = `Gesamtbetrag: ${formatCheckoutEuro(total)}`;
|
||||
if (vatDisplay) vatDisplay.innerText = `inkl. 19% MwSt: ${formatCheckoutEuro(vat)}`;
|
||||
|
||||
selectedPaymentMethod = "";
|
||||
document.querySelectorAll(".payment-method").forEach((method) => method.classList.remove("selected"));
|
||||
nextButton?.classList.add("hidden");
|
||||
setCheckoutStep(1);
|
||||
}
|
||||
|
||||
function generateTicket() {
|
||||
const ticketContainer = document.getElementById("ticket-container");
|
||||
if (!ticketContainer) return;
|
||||
|
||||
const moviesInCart = cart.filter((item: any) => item.category === "movie");
|
||||
if (!moviesInCart.length) {
|
||||
ticketContainer.innerHTML = "<p>Danke für deinen Einkauf!</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
const mainMovie = moviesInCart[0];
|
||||
const matchingMovieSeats = moviesInCart
|
||||
.filter((item: any) => item.title === mainMovie.title && item.time === mainMovie.time)
|
||||
.map((item: any) => item.seatId)
|
||||
.join(", ");
|
||||
|
||||
const qrData = encodeURIComponent(`EAGLE-IMAX|${mainMovie.title}|${mainMovie.hall}|${matchingMovieSeats}`);
|
||||
const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${qrData}&bgcolor=ffffff`;
|
||||
|
||||
ticketContainer.innerHTML = `
|
||||
<div class="luxury-ticket">
|
||||
<div class="ticket-left">
|
||||
<img src="${mainMovie.img || mainMovie.poster}" class="ticket-poster" alt="${mainMovie.title}">
|
||||
</div>
|
||||
<div class="ticket-right">
|
||||
<div class="ticket-brand">EAGLE'S IMAX PREMIUM</div>
|
||||
<h2 class="ticket-title">${mainMovie.title}</h2>
|
||||
<div class="ticket-details">
|
||||
<p><span>SAAL</span> <strong>${mainMovie.hall}</strong></p>
|
||||
<p><span>ZEIT</span> <strong>${mainMovie.time} Uhr</strong></p>
|
||||
<p><span>SITZE</span> <strong>${matchingMovieSeats || "-"}</strong></p>
|
||||
</div>
|
||||
<div class="ticket-footer">
|
||||
<img src="${qrUrl}" class="ticket-qr" alt="QR Code">
|
||||
<div class="ticket-code">#${Math.floor(Math.random() * 90000) + 10000}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function completeCheckout() {
|
||||
const orderItems = [...cart];
|
||||
const orderTotal = orderItems.reduce((sum, item) => sum + Number(item.price || 0), 0);
|
||||
|
||||
// Save order for current user
|
||||
if (currentUser && Array.isArray(users)) {
|
||||
const userIndex = users.findIndex((entry: any) => entry.email === currentUser.email);
|
||||
if (userIndex !== -1) {
|
||||
if (!Array.isArray(users[userIndex].orders)) users[userIndex].orders = [];
|
||||
users[userIndex].orders.push({
|
||||
date: new Date().toLocaleString("de-DE"),
|
||||
items: orderItems,
|
||||
total: orderTotal,
|
||||
paymentMethod: selectedPaymentMethod || "-"
|
||||
});
|
||||
localStorage.setItem("eagleUsers", JSON.stringify(users));
|
||||
}
|
||||
}
|
||||
|
||||
// Reserve seats
|
||||
orderItems.filter(item => item.category === "movie").forEach(item => {
|
||||
const key = `${item.hall}-${item.time}`;
|
||||
if (!occupiedSeatsData[key]) occupiedSeatsData[key] = [];
|
||||
occupiedSeatsData[key].push(item.seatId);
|
||||
});
|
||||
updateOccupiedSeats(occupiedSeatsData);
|
||||
|
||||
emptyCart();
|
||||
window.dispatchEvent(new CustomEvent("cart-updated"));
|
||||
}
|
||||
|
||||
function bindCheckoutEvents() {
|
||||
const nextButton = document.getElementById("btn-next-step-2");
|
||||
const backButton = document.getElementById("btn-back-to-step1");
|
||||
const payNowButton = document.getElementById("btn-pay-now") as HTMLButtonElement;
|
||||
|
||||
document.querySelectorAll(".payment-method").forEach((method) => {
|
||||
method.addEventListener("click", () => {
|
||||
document.querySelectorAll(".payment-method").forEach((entry) => entry.classList.remove("selected"));
|
||||
method.classList.add("selected");
|
||||
selectedPaymentMethod = (method as HTMLElement).dataset.method || "";
|
||||
nextButton?.classList.remove("hidden");
|
||||
});
|
||||
});
|
||||
|
||||
nextButton?.addEventListener("click", () => {
|
||||
if (!selectedPaymentMethod) {
|
||||
alert("Bitte wähle zuerst eine Zahlungsmethode aus.");
|
||||
return;
|
||||
}
|
||||
setCheckoutStep(2);
|
||||
});
|
||||
|
||||
backButton?.addEventListener("click", () => setCheckoutStep(1));
|
||||
|
||||
payNowButton?.addEventListener("click", () => {
|
||||
if (!cart.length) {
|
||||
alert("Dein Warenkorb ist leer.");
|
||||
return;
|
||||
}
|
||||
payNowButton.disabled = true;
|
||||
payNowButton.innerText = "Verarbeite...";
|
||||
payNowButton.style.opacity = "0.7";
|
||||
setTimeout(() => {
|
||||
setCheckoutStep(3);
|
||||
generateTicket();
|
||||
completeCheckout();
|
||||
payNowButton.disabled = false;
|
||||
payNowButton.innerText = "Jetzt Bezahlen";
|
||||
payNowButton.style.opacity = "1";
|
||||
}, 1200);
|
||||
});
|
||||
|
||||
document.getElementById("btn-back-home")?.addEventListener("click", () => {
|
||||
window.location.href = "/";
|
||||
});
|
||||
}
|
||||
|
||||
if (document.getElementById("checkout-view")) {
|
||||
renderCheckout();
|
||||
bindCheckoutEvents();
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user