import { seatLayouts, occupiedSeatsData, prices, cart } from "./main" import { renderCart, saveCart } from "./cart"; import { renderCheckout } from "./checkout"; let currentBookingContext: any = null; let currentHallLayout: any = null; export function openBooking(movie: string, hall: string, time: any) { const titleEl = document.getElementById("modal-movie-title"); const infoEl = document.getElementById("modal-info-text"); if (titleEl) { titleEl.innerText = movie; } if (infoEl) { infoEl.innerText = `${hall} • ${time} Uhr`; } currentBookingContext = { movie, hall, time }; createSeats(hall, time); renderBookingLegend(); updateBookingSummary(); document.getElementById("booking-modal")?.classList.remove("hidden"); } function getRowLabel(rowIndex: number) { return String(rowIndex + 1); } function buildHallLayout(hallName: string, baseConfig:any) { const rows = Number(baseConfig.rows || 0); const totalCols = Number(baseConfig.left || 0) + Number(baseConfig.right || 0); const isDeluxe = /deluxe/i.test(hallName); const left = isDeluxe ? Math.max(3, Number(baseConfig.left || 0) - 1) : Number(baseConfig.left || 0); const right = Math.max(0, totalCols - left); const vipRows = rows > 0 ? [rows] : []; const dboxMap = new Set(); const markDboxRange = (rowNumber: number, startCol: number, width: number) => { if (!rowNumber || width <= 0) { return; } const maxCol = Math.min(totalCols, startCol + width - 1); for (let col = startCol; col <= maxCol; col++) { dboxMap.add(`${rowNumber}-${col}`); } }; if (isDeluxe) { const configuredDboxSeats = Array.isArray(baseConfig.dbox) ? baseConfig.dbox.reduce((sum: number, section: any) => sum + Number(section.w || 0), 0) : 0; const totalDboxSeats = Math.max(4, configuredDboxSeats || 0); const firstRow = Math.max(1, rows - 2); const secondRow = Math.max(1, rows - 1); const targetRows = [firstRow, secondRow] .filter((rowNumber, index, arr) => arr.indexOf(rowNumber) === index) .filter((rowNumber) => !vipRows.includes(rowNumber)); const rowCount = Math.max(1, targetRows.length); const seatsPerFirstRows = Math.ceil(totalDboxSeats / rowCount); let remaining = totalDboxSeats; targetRows.forEach((rowNumber, index) => { const seatsForRow = index === targetRows.length - 1 ? remaining : Math.min(seatsPerFirstRows, remaining); remaining -= seatsForRow; const startCol = left + Math.max(1, Math.floor((right - seatsForRow) / 2) + 1); markDboxRange(rowNumber, startCol, seatsForRow); }); } else if (Array.isArray(baseConfig.dbox)) { baseConfig.dbox.forEach((section: any) => { const rowNumber = Number(section.r || 0); const width = Number(section.w || 0); const startCol = Number(section.c || 0); markDboxRange(rowNumber, startCol, width); }); } return { rows, left, right, totalCols, vipRows, dboxMap, isImax: Boolean(baseConfig.isImax) }; } function getSeatType(layout: any, rowNumber: number, colNumber: number) { if (layout.dboxMap.has(`${rowNumber}-${colNumber}`)) { return "dbox"; } if (layout.vipRows.includes(rowNumber)) { return "vip"; } if (layout.isImax) { return "imax"; } return "normal"; } function createSeatElement({seatId, seatType, occupiedSeats }:any) { const seat = document.createElement("button"); seat.type = "button"; seat.classList.add("seat", seatType); seat.dataset.seatId = seatId; seat.dataset.type = seatType; seat.title = `${seatId} (${seatType.toUpperCase()})`; if (occupiedSeats.has(seatId)) { seat.classList.add("occupied"); seat.disabled = true; seat.setAttribute("aria-label", `${seatId} belegt`); return seat; } seat.setAttribute("aria-label", `${seatId} frei`); seat.addEventListener("click", () => { seat.classList.toggle("selected"); updateBookingSummary(); }); return seat; } function createSeats(hallName: string, time: any) { const seatGrid = document.getElementById("seat-grid"); if (!seatGrid) { return; } seatGrid.innerHTML = ""; const arrIndex = hallName as keyof typeof seatLayouts; const baseConfig: any = seatLayouts[arrIndex]; if (!baseConfig) { currentHallLayout = null; return; } currentHallLayout = buildHallLayout(hallName, baseConfig); const occupiedKey = `${hallName}-${time}`; const occupiedSeats = new Set(Array.isArray(occupiedSeatsData?.[occupiedKey]) ? occupiedSeatsData[occupiedKey] : []); for (let rowIndex = 0; rowIndex < currentHallLayout.rows; rowIndex++) { const rowNumber = rowIndex + 1; const rowLabel = getRowLabel(rowIndex); const perspectiveFactor = (currentHallLayout.rows - rowNumber) / Math.max(currentHallLayout.rows - 1, 1); const rowIndent = Math.round(18 * perspectiveFactor); const row = document.createElement("div"); row.className = "seat-row cinema-row"; row.style.setProperty("--row-indent", `${rowIndent}px`); const leftLabel = document.createElement("div"); leftLabel.className = "row-label"; leftLabel.textContent = rowLabel; const rightLabel = document.createElement("div"); rightLabel.className = "row-label row-label-right"; rightLabel.textContent = rowLabel; const leftBlock = document.createElement("div"); leftBlock.className = "row-seat-block left-block"; const rightBlock = document.createElement("div"); rightBlock.className = "row-seat-block right-block"; for (let col = 1; col <= currentHallLayout.totalCols; col++) { const seatId = `R${rowNumber}-P${col}`; const seatType = getSeatType(currentHallLayout, rowNumber, col); const seat = createSeatElement({ seatId, seatType, occupiedSeats }); if (col <= currentHallLayout.left) { leftBlock.appendChild(seat); } else { rightBlock.appendChild(seat); } } const aisle = document.createElement("div"); aisle.className = "aisle-gap"; row.append(leftLabel, leftBlock, aisle, rightBlock, rightLabel); seatGrid.appendChild(row); } } function renderBookingLegend() { const legend = document.getElementById("dynamic-legend"); if (!legend || !currentHallLayout) { return; } const legendItems = [ { type: "normal", label: "Standard" }, { type: "selected", label: "Ausgewählt" }, { type: "occupied", label: "Belegt" } ]; if (currentHallLayout.isImax) { legendItems.unshift({ type: "imax", label: "IMAX" }); } if (currentHallLayout.vipRows.length > 0) { legendItems.unshift({ type: "vip", label: "VIP" }); } if (currentHallLayout.dboxMap.size > 0) { legendItems.unshift({ type: "dbox", label: "D-BOX" }); } legend.innerHTML = legendItems .map((item) => `
${item.label}
`) .join(""); } function updateBookingSummary() { const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected")) as HTMLElement[];; const summaryPanel = document.getElementById("booking-summary"); const summaryItems = document.getElementById("summary-items"); const totalEl = document.getElementById("total-price"); let total = 0; if (summaryItems) { summaryItems.innerHTML = selectedSeats .map((seat) => { const type = (seat.dataset.type || "normal") as keyof typeof prices; const seatPrice = Number(prices?.[type] ?? prices?.normal ?? 11); total += seatPrice; return `
${seat.dataset.seatId} ${seatPrice.toFixed(2).replace(".", ",")} EUR
`; }) .join(""); } else { selectedSeats.forEach((seat) => { const type = seat.dataset.type || "normal"; const seatPrice = Number(prices?.[type] ?? prices?.normal ?? 11); total += seatPrice; }); } if (totalEl) { totalEl.innerText = `${total.toFixed(2).replace(".", ",")} EUR`; } summaryPanel?.classList.toggle("hidden", selectedSeats.length === 0); } function findMoviePoster(movieTitle: string) { const cards = Array.from(document.querySelectorAll(".movie-card, .detailed-card")); const normalizedTarget = String(movieTitle || "").trim().toLowerCase(); for (const card of cards) { const currentCard = card.querySelector("h2, h3") as HTMLElement; const title = currentCard.innerText?.trim().toLowerCase(); if (title === normalizedTarget) { const imageSrc = card.querySelector("img")?.src; if (imageSrc) { return imageSrc; } } } return ""; } function confirmSelectedSeats() { const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected")) as HTMLElement[]; if (!currentBookingContext || selectedSeats.length === 0) { alert("Bitte waehle mindestens einen Platz aus."); return; } const moviePoster = findMoviePoster(currentBookingContext.movie); const addedSeats = []; selectedSeats.forEach((seat) => { const seatId = seat.dataset.seatId; const seatType = seat.dataset.type || "normal"; const alreadyInCart = cart.some((item: any) => item.category === "movie" && item.title === currentBookingContext.movie && item.hall === currentBookingContext.hall && item.time === currentBookingContext.time && item.seatId === seatId ); if (alreadyInCart) { return; } cart.push({ id: Date.now() + Math.random(), category: "movie", title: currentBookingContext.movie, hall: currentBookingContext.hall, time: currentBookingContext.time, seatId, type: seatType.toUpperCase(), price: Number(prices?.[seatType] ?? prices?.normal ?? 11), img: moviePoster }); addedSeats.push(seatId); }); if (!addedSeats.length) { alert("Diese Plaetze sind bereits im Warenkorb."); return; } saveCart?.(); renderCart?.(); renderCheckout?.(); document.getElementById("booking-modal")?.classList.add("hidden"); const snackOverlay = document.getElementById("snack-prompt-overlay"); snackOverlay?.classList.remove("hidden"); document.body.style.overflow = "hidden"; } document.addEventListener("DOMContentLoaded", () => { document.getElementById("btn-confirm-seats")?.addEventListener("click", confirmSelectedSeats); });