Compare commits
1 Commits
40ee49aff5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| e13f35a9e0 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
dist/
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import type { User } from "./interfaces";
|
function readStorageJson(key, fallbackValue) {
|
||||||
|
|
||||||
function readStorageJson(key: string, fallbackValue: any) {
|
|
||||||
const raw = localStorage.getItem(key);
|
const raw = localStorage.getItem(key);
|
||||||
|
|
||||||
if (!raw || raw === "undefined" || raw === "null") {
|
if (!raw || raw === "undefined" || raw === "null") {
|
||||||
@@ -15,18 +13,22 @@ function readStorageJson(key: string, fallbackValue: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeUser(user: User): User {
|
function normalizeUser(user) {
|
||||||
|
if (!user || typeof user !== "object") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
firstName: user.firstName || "",
|
firstName: user.firstName || "",
|
||||||
lastName: user.lastName || "",
|
lastName: user.lastName || "",
|
||||||
email: user.email || "",
|
email: user.email || "",
|
||||||
hashedPassword: user.hashedPassword || "",
|
password: user.password || "",
|
||||||
orders: Array.isArray(user.orders) ? user.orders : [],
|
orders: Array.isArray(user.orders) ? user.orders : [],
|
||||||
paymentMethods: Array.isArray(user.paymentMethods) ? user.paymentMethods : []
|
paymentMethods: Array.isArray(user.paymentMethods) ? user.paymentMethods : []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeHtml(value: string) {
|
function escapeHtml(value) {
|
||||||
return String(value || "")
|
return String(value || "")
|
||||||
.replaceAll("&", "&")
|
.replaceAll("&", "&")
|
||||||
.replaceAll("<", "<")
|
.replaceAll("<", "<")
|
||||||
@@ -35,7 +37,7 @@ function escapeHtml(value: string) {
|
|||||||
.replaceAll("'", "'");
|
.replaceAll("'", "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatEuro(value: string) {
|
function formatEuro(value) {
|
||||||
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,21 +53,15 @@ function persistCurrentUser() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export let users = readStorageJson("eagleUsers", []);
|
let users = readStorageJson("eagleUsers", []);
|
||||||
if (!Array.isArray(users)) {
|
if (!Array.isArray(users)) {
|
||||||
users = [];
|
users = [];
|
||||||
}
|
}
|
||||||
users = users.map(normalizeUser).filter(Boolean);
|
users = users.map(normalizeUser).filter(Boolean);
|
||||||
|
|
||||||
const rawCurrentUser = readStorageJson("currentUser", null);
|
let currentUser = normalizeUser(readStorageJson("currentUser", null));
|
||||||
|
|
||||||
export var currentUser: User | null = rawCurrentUser ? normalizeUser(rawCurrentUser) : null;
|
|
||||||
|
|
||||||
if (currentUser && currentUser.email) {
|
if (currentUser && currentUser.email) {
|
||||||
const currentEmail = currentUser.email;
|
const storedMatch = users.find((user) => user.email === currentUser.email);
|
||||||
const storedMatch = users.find((user: { email: string; }) => {
|
|
||||||
return user.email === currentEmail;
|
|
||||||
});
|
|
||||||
if (storedMatch) {
|
if (storedMatch) {
|
||||||
currentUser = storedMatch;
|
currentUser = storedMatch;
|
||||||
} else {
|
} else {
|
||||||
@@ -74,23 +70,11 @@ if (currentUser && currentUser.email) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hashMessage(message: string) {
|
function registerUser() {
|
||||||
const msgBuffer = new TextEncoder().encode(message); // Encode as UTF-8
|
const firstName = document.getElementById("reg-firstname")?.value.trim() || "";
|
||||||
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); // Hash
|
const lastName = document.getElementById("reg-lastname")?.value.trim() || "";
|
||||||
const hashArray = Array.from(new Uint8Array(hashBuffer)); // Convert to bytes
|
const email = (document.getElementById("reg-email")?.value.trim() || "").toLowerCase();
|
||||||
return hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // Hex string
|
const password = document.getElementById("reg-password")?.value || "";
|
||||||
}
|
|
||||||
|
|
||||||
function getInputValue(id: string): string {
|
|
||||||
const el = document.getElementById(id) as HTMLInputElement | null;
|
|
||||||
return el?.value.trim() ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function registerUser() {
|
|
||||||
const firstName = getInputValue("reg-firstname");
|
|
||||||
const lastName = getInputValue("reg-lastname");
|
|
||||||
const email = getInputValue("reg-email").toLowerCase();
|
|
||||||
const password = document.querySelector<HTMLInputElement>("#reg-password")?.value ?? "";
|
|
||||||
|
|
||||||
if (!firstName || !lastName || !email || !password) {
|
if (!firstName || !lastName || !email || !password) {
|
||||||
alert("Bitte fuelle alle Felder aus.");
|
alert("Bitte fuelle alle Felder aus.");
|
||||||
@@ -102,19 +86,17 @@ const password = document.querySelector<HTMLInputElement>("#reg-password")?.valu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingUser = users.find((user: User) => user.email.toLowerCase() === email);
|
const existingUser = users.find((user) => user.email.toLowerCase() === email);
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
alert("E-Mail bereits registriert");
|
alert("E-Mail bereits registriert");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hashedPassword = await hashMessage(password);
|
|
||||||
|
|
||||||
const newUser = {
|
const newUser = {
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
email,
|
email,
|
||||||
hashedPassword,
|
password,
|
||||||
orders: [],
|
orders: [],
|
||||||
paymentMethods: []
|
paymentMethods: []
|
||||||
};
|
};
|
||||||
@@ -131,13 +113,12 @@ const password = document.querySelector<HTMLInputElement>("#reg-password")?.valu
|
|||||||
openAccountDashboard();
|
openAccountDashboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loginUser() {
|
function loginUser() {
|
||||||
const email = (document.querySelector<HTMLInputElement>("#login-email")?.value.trim() || "").toLowerCase();
|
const email = (document.getElementById("login-email")?.value.trim() || "").toLowerCase();
|
||||||
const password = document.querySelector<HTMLInputElement>("#login-password")?.value || "";
|
const password = document.getElementById("login-password")?.value || "";
|
||||||
const hashedPassword = await hashMessage(password);
|
|
||||||
|
|
||||||
const user = users.find(
|
const user = users.find(
|
||||||
(entry: User) => entry.email.toLowerCase() === email && entry.hashedPassword === hashedPassword
|
(entry) => entry.email.toLowerCase() === email && entry.password === password
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@@ -150,7 +131,7 @@ export async function loginUser() {
|
|||||||
openAccountDashboard();
|
openAccountDashboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openAccountDashboard() {
|
function openAccountDashboard() {
|
||||||
const accountView = document.getElementById("account-view");
|
const accountView = document.getElementById("account-view");
|
||||||
if (!accountView) {
|
if (!accountView) {
|
||||||
return;
|
return;
|
||||||
@@ -161,7 +142,7 @@ export function openAccountDashboard() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
accountView.innerHTML = /*html*/`
|
accountView.innerHTML = `
|
||||||
<div class="account-panel">
|
<div class="account-panel">
|
||||||
<div class="account-panel-header">
|
<div class="account-panel-header">
|
||||||
<h2>Mein Konto</h2>
|
<h2>Mein Konto</h2>
|
||||||
@@ -217,7 +198,7 @@ function renderOrders() {
|
|||||||
const orderHtml = orders
|
const orderHtml = orders
|
||||||
.map((order, index) => {
|
.map((order, index) => {
|
||||||
const movieItems = Array.isArray(order.items)
|
const movieItems = Array.isArray(order.items)
|
||||||
? order.items.filter((item: any) => item.category === "movie")
|
? order.items.filter((item) => item.category === "movie")
|
||||||
: [];
|
: [];
|
||||||
const previewItem = movieItems[0] || (Array.isArray(order.items) ? order.items[0] : null);
|
const previewItem = movieItems[0] || (Array.isArray(order.items) ? order.items[0] : null);
|
||||||
const previewTitle = previewItem?.title || "Bestellung";
|
const previewTitle = previewItem?.title || "Bestellung";
|
||||||
@@ -246,20 +227,20 @@ function renderOrders() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const detailTarget = document.getElementById("order-ticket-details");
|
const detailTarget = document.getElementById("order-ticket-details");
|
||||||
const orderButtons = Array.from(target.querySelectorAll<HTMLButtonElement>(".order-item-btn"));
|
const orderButtons = Array.from(target.querySelectorAll(".order-item-btn"));
|
||||||
|
|
||||||
const renderOrderTicket = (orderIndex: number) => {
|
const renderOrderTicket = (orderIndex) => {
|
||||||
const order = orders[orderIndex];
|
const order = orders[orderIndex];
|
||||||
if (!order || !detailTarget) {
|
if (!order || !detailTarget) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const movieItems = Array.isArray(order.items)
|
const movieItems = Array.isArray(order.items)
|
||||||
? order.items.filter((item: any) => item.category === "movie")
|
? order.items.filter((item) => item.category === "movie")
|
||||||
: [];
|
: [];
|
||||||
const primaryMovie = movieItems[0] || (Array.isArray(order.items) ? order.items[0] : null);
|
const primaryMovie = movieItems[0] || (Array.isArray(order.items) ? order.items[0] : null);
|
||||||
const poster = primaryMovie?.img || "";
|
const poster = primaryMovie?.img || "";
|
||||||
const seats = movieItems.map((item: any) => item.seatId).filter(Boolean).join(", ") || "-";
|
const seats = movieItems.map((item) => item.seatId).filter(Boolean).join(", ") || "-";
|
||||||
const ticketCount = movieItems.length || (Array.isArray(order.items) ? order.items.length : 0);
|
const ticketCount = movieItems.length || (Array.isArray(order.items) ? order.items.length : 0);
|
||||||
const hall = primaryMovie?.hall || "-";
|
const hall = primaryMovie?.hall || "-";
|
||||||
const time = primaryMovie?.time ? `${primaryMovie.time} Uhr` : "-";
|
const time = primaryMovie?.time ? `${primaryMovie.time} Uhr` : "-";
|
||||||
@@ -309,7 +290,7 @@ function renderPayments() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
target.innerHTML = /*html*/`
|
target.innerHTML = `
|
||||||
<div class="account-card">
|
<div class="account-card">
|
||||||
<h3>Zahlungsmethoden</h3>
|
<h3>Zahlungsmethoden</h3>
|
||||||
<p class="account-payments-note">Platzhalter zum Hinterlegen deiner Logos oder Anbieter-Informationen.</p>
|
<p class="account-payments-note">Platzhalter zum Hinterlegen deiner Logos oder Anbieter-Informationen.</p>
|
||||||
@@ -463,7 +444,7 @@ function renderPayments() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function logoutUser() {
|
function logoutUser() {
|
||||||
|
currentUser = null;
|
||||||
persistCurrentUser();
|
persistCurrentUser();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
import { seatLayouts, occupiedSeatsData, prices, cart } from "./main"
|
let currentBookingContext = null;
|
||||||
import { renderCart, saveCart } from "./cart";
|
let currentHallLayout = null;
|
||||||
import { renderCheckout } from "./checkout";
|
|
||||||
|
|
||||||
let currentBookingContext: any = null;
|
function openBooking(movie, hall, time) {
|
||||||
let currentHallLayout: any = null;
|
|
||||||
|
|
||||||
export function openBooking(movie: string, hall: string, time: any) {
|
|
||||||
const titleEl = document.getElementById("modal-movie-title");
|
const titleEl = document.getElementById("modal-movie-title");
|
||||||
const infoEl = document.getElementById("modal-info-text");
|
const infoEl = document.getElementById("modal-info-text");
|
||||||
|
|
||||||
@@ -24,13 +20,13 @@ export function openBooking(movie: string, hall: string, time: any) {
|
|||||||
updateBookingSummary();
|
updateBookingSummary();
|
||||||
|
|
||||||
document.getElementById("booking-modal")?.classList.remove("hidden");
|
document.getElementById("booking-modal")?.classList.remove("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRowLabel(rowIndex: number) {
|
function getRowLabel(rowIndex) {
|
||||||
return String(rowIndex + 1);
|
return String(rowIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildHallLayout(hallName: string, baseConfig:any) {
|
function buildHallLayout(hallName, baseConfig) {
|
||||||
const rows = Number(baseConfig.rows || 0);
|
const rows = Number(baseConfig.rows || 0);
|
||||||
const totalCols = Number(baseConfig.left || 0) + Number(baseConfig.right || 0);
|
const totalCols = Number(baseConfig.left || 0) + Number(baseConfig.right || 0);
|
||||||
const isDeluxe = /deluxe/i.test(hallName);
|
const isDeluxe = /deluxe/i.test(hallName);
|
||||||
@@ -43,7 +39,7 @@ function buildHallLayout(hallName: string, baseConfig:any) {
|
|||||||
const vipRows = rows > 0 ? [rows] : [];
|
const vipRows = rows > 0 ? [rows] : [];
|
||||||
|
|
||||||
const dboxMap = new Set();
|
const dboxMap = new Set();
|
||||||
const markDboxRange = (rowNumber: number, startCol: number, width: number) => {
|
const markDboxRange = (rowNumber, startCol, width) => {
|
||||||
if (!rowNumber || width <= 0) {
|
if (!rowNumber || width <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -56,7 +52,7 @@ function buildHallLayout(hallName: string, baseConfig:any) {
|
|||||||
|
|
||||||
if (isDeluxe) {
|
if (isDeluxe) {
|
||||||
const configuredDboxSeats = Array.isArray(baseConfig.dbox)
|
const configuredDboxSeats = Array.isArray(baseConfig.dbox)
|
||||||
? baseConfig.dbox.reduce((sum: number, section: any) => sum + Number(section.w || 0), 0)
|
? baseConfig.dbox.reduce((sum, section) => sum + Number(section.w || 0), 0)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const totalDboxSeats = Math.max(4, configuredDboxSeats || 0);
|
const totalDboxSeats = Math.max(4, configuredDboxSeats || 0);
|
||||||
@@ -81,7 +77,7 @@ function buildHallLayout(hallName: string, baseConfig:any) {
|
|||||||
markDboxRange(rowNumber, startCol, seatsForRow);
|
markDboxRange(rowNumber, startCol, seatsForRow);
|
||||||
});
|
});
|
||||||
} else if (Array.isArray(baseConfig.dbox)) {
|
} else if (Array.isArray(baseConfig.dbox)) {
|
||||||
baseConfig.dbox.forEach((section: any) => {
|
baseConfig.dbox.forEach((section) => {
|
||||||
const rowNumber = Number(section.r || 0);
|
const rowNumber = Number(section.r || 0);
|
||||||
const width = Number(section.w || 0);
|
const width = Number(section.w || 0);
|
||||||
const startCol = Number(section.c || 0);
|
const startCol = Number(section.c || 0);
|
||||||
@@ -100,7 +96,7 @@ function buildHallLayout(hallName: string, baseConfig:any) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSeatType(layout: any, rowNumber: number, colNumber: number) {
|
function getSeatType(layout, rowNumber, colNumber) {
|
||||||
if (layout.dboxMap.has(`${rowNumber}-${colNumber}`)) {
|
if (layout.dboxMap.has(`${rowNumber}-${colNumber}`)) {
|
||||||
return "dbox";
|
return "dbox";
|
||||||
}
|
}
|
||||||
@@ -116,7 +112,7 @@ function getSeatType(layout: any, rowNumber: number, colNumber: number) {
|
|||||||
return "normal";
|
return "normal";
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSeatElement({seatId, seatType, occupiedSeats }:any) {
|
function createSeatElement({ seatId, seatType, occupiedSeats }) {
|
||||||
const seat = document.createElement("button");
|
const seat = document.createElement("button");
|
||||||
seat.type = "button";
|
seat.type = "button";
|
||||||
seat.classList.add("seat", seatType);
|
seat.classList.add("seat", seatType);
|
||||||
@@ -140,7 +136,7 @@ function createSeatElement({seatId, seatType, occupiedSeats }:any) {
|
|||||||
return seat;
|
return seat;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSeats(hallName: string, time: any) {
|
function createSeats(hallName, time) {
|
||||||
const seatGrid = document.getElementById("seat-grid");
|
const seatGrid = document.getElementById("seat-grid");
|
||||||
if (!seatGrid) {
|
if (!seatGrid) {
|
||||||
return;
|
return;
|
||||||
@@ -148,8 +144,7 @@ function createSeats(hallName: string, time: any) {
|
|||||||
|
|
||||||
seatGrid.innerHTML = "";
|
seatGrid.innerHTML = "";
|
||||||
|
|
||||||
const arrIndex = hallName as keyof typeof seatLayouts;
|
const baseConfig = seatLayouts[hallName];
|
||||||
const baseConfig: any = seatLayouts[arrIndex];
|
|
||||||
if (!baseConfig) {
|
if (!baseConfig) {
|
||||||
currentHallLayout = null;
|
currentHallLayout = null;
|
||||||
return;
|
return;
|
||||||
@@ -240,7 +235,7 @@ function renderBookingLegend() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateBookingSummary() {
|
function updateBookingSummary() {
|
||||||
const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected")) as HTMLElement[];;
|
const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected"));
|
||||||
const summaryPanel = document.getElementById("booking-summary");
|
const summaryPanel = document.getElementById("booking-summary");
|
||||||
const summaryItems = document.getElementById("summary-items");
|
const summaryItems = document.getElementById("summary-items");
|
||||||
const totalEl = document.getElementById("total-price");
|
const totalEl = document.getElementById("total-price");
|
||||||
@@ -250,7 +245,7 @@ function updateBookingSummary() {
|
|||||||
if (summaryItems) {
|
if (summaryItems) {
|
||||||
summaryItems.innerHTML = selectedSeats
|
summaryItems.innerHTML = selectedSeats
|
||||||
.map((seat) => {
|
.map((seat) => {
|
||||||
const type = (seat.dataset.type || "normal") as keyof typeof prices;
|
const type = seat.dataset.type || "normal";
|
||||||
const seatPrice = Number(prices?.[type] ?? prices?.normal ?? 11);
|
const seatPrice = Number(prices?.[type] ?? prices?.normal ?? 11);
|
||||||
total += seatPrice;
|
total += seatPrice;
|
||||||
|
|
||||||
@@ -277,13 +272,12 @@ function updateBookingSummary() {
|
|||||||
summaryPanel?.classList.toggle("hidden", selectedSeats.length === 0);
|
summaryPanel?.classList.toggle("hidden", selectedSeats.length === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findMoviePoster(movieTitle: string) {
|
function findMoviePoster(movieTitle) {
|
||||||
const cards = Array.from(document.querySelectorAll(".movie-card, .detailed-card"));
|
const cards = Array.from(document.querySelectorAll(".movie-card, .detailed-card"));
|
||||||
const normalizedTarget = String(movieTitle || "").trim().toLowerCase();
|
const normalizedTarget = String(movieTitle || "").trim().toLowerCase();
|
||||||
|
|
||||||
for (const card of cards) {
|
for (const card of cards) {
|
||||||
const currentCard = card.querySelector("h2, h3") as HTMLElement;
|
const title = card.querySelector("h2, h3")?.innerText?.trim().toLowerCase();
|
||||||
const title = currentCard.innerText?.trim().toLowerCase();
|
|
||||||
if (title === normalizedTarget) {
|
if (title === normalizedTarget) {
|
||||||
const imageSrc = card.querySelector("img")?.src;
|
const imageSrc = card.querySelector("img")?.src;
|
||||||
if (imageSrc) {
|
if (imageSrc) {
|
||||||
@@ -296,7 +290,7 @@ function findMoviePoster(movieTitle: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function confirmSelectedSeats() {
|
function confirmSelectedSeats() {
|
||||||
const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected")) as HTMLElement[];
|
const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected"));
|
||||||
|
|
||||||
if (!currentBookingContext || selectedSeats.length === 0) {
|
if (!currentBookingContext || selectedSeats.length === 0) {
|
||||||
alert("Bitte waehle mindestens einen Platz aus.");
|
alert("Bitte waehle mindestens einen Platz aus.");
|
||||||
@@ -310,7 +304,7 @@ function confirmSelectedSeats() {
|
|||||||
const seatId = seat.dataset.seatId;
|
const seatId = seat.dataset.seatId;
|
||||||
const seatType = seat.dataset.type || "normal";
|
const seatType = seat.dataset.type || "normal";
|
||||||
|
|
||||||
const alreadyInCart = cart.some((item: any) =>
|
const alreadyInCart = cart.some((item) =>
|
||||||
item.category === "movie" &&
|
item.category === "movie" &&
|
||||||
item.title === currentBookingContext.movie &&
|
item.title === currentBookingContext.movie &&
|
||||||
item.hall === currentBookingContext.hall &&
|
item.hall === currentBookingContext.hall &&
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
import { cart } from "./main";
|
function formatEuro(value) {
|
||||||
|
|
||||||
function formatEuro(value: number) {
|
|
||||||
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeHtml(value: any) {
|
function escapeHtml(value) {
|
||||||
return String(value || "")
|
return String(value || "")
|
||||||
.replaceAll("&", "&")
|
.replaceAll("&", "&")
|
||||||
.replaceAll("<", "<")
|
.replaceAll("<", "<")
|
||||||
@@ -13,14 +11,14 @@ function escapeHtml(value: any) {
|
|||||||
.replaceAll("'", "'");
|
.replaceAll("'", "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCartKey(item: { category: string; seatId: any; hall: any; time: any; title: any; }) {
|
function buildCartKey(item) {
|
||||||
const infoText = item.category === "movie"
|
const infoText = item.category === "movie"
|
||||||
? `Sitz: ${item.seatId} (${item.hall})`
|
? `Sitz: ${item.seatId} (${item.hall})`
|
||||||
: item.time;
|
: item.time;
|
||||||
return `${item.title}-${item.hall}-${infoText}`;
|
return `${item.title}-${item.hall}-${infoText}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDrinkItem(item: { category: string; title: any; hall: any; }) {
|
function isDrinkItem(item) {
|
||||||
if (item.category !== "snack") {
|
if (item.category !== "snack") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -41,7 +39,7 @@ function isDrinkItem(item: { category: string; title: any; hall: any; }) {
|
|||||||
return drinkKeywords.some((word) => title.includes(word)) || size.includes("l");
|
return drinkKeywords.some((word) => title.includes(word)) || size.includes("l");
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildItemInfo(item: { category: any; seatId?: any; hall: any; time?: any; title: any; }) {
|
function buildItemInfo(item) {
|
||||||
if (item.category === "movie") {
|
if (item.category === "movie") {
|
||||||
return `
|
return `
|
||||||
<div>Sitzplatz: ${escapeHtml(item.seatId || "-")}</div>
|
<div>Sitzplatz: ${escapeHtml(item.seatId || "-")}</div>
|
||||||
@@ -67,7 +65,7 @@ function buildItemInfo(item: { category: any; seatId?: any; hall: any; time?: an
|
|||||||
function groupCartItems() {
|
function groupCartItems() {
|
||||||
const groups = new Map();
|
const groups = new Map();
|
||||||
|
|
||||||
cart.forEach((item: { price?: any; category: string; seatId: any; hall: any; time: any; title: any; }) => {
|
cart.forEach((item) => {
|
||||||
const key = buildCartKey(item);
|
const key = buildCartKey(item);
|
||||||
|
|
||||||
if (!groups.has(key)) {
|
if (!groups.has(key)) {
|
||||||
@@ -87,12 +85,12 @@ function groupCartItems() {
|
|||||||
return Array.from(groups.values());
|
return Array.from(groups.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveCart() {
|
function saveCart() {
|
||||||
localStorage.setItem("eagleCart", JSON.stringify(cart));
|
localStorage.setItem("eagleCart", JSON.stringify(cart));
|
||||||
updateCartBadge();
|
updateCartBadge();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCartBadge() {
|
function updateCartBadge() {
|
||||||
const cartBadge = document.getElementById("cart-badge");
|
const cartBadge = document.getElementById("cart-badge");
|
||||||
|
|
||||||
if (!cartBadge) {
|
if (!cartBadge) {
|
||||||
@@ -103,7 +101,7 @@ export function updateCartBadge() {
|
|||||||
cartBadge.classList.toggle("hidden", cart.length === 0);
|
cartBadge.classList.toggle("hidden", cart.length === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderCart() {
|
function renderCart() {
|
||||||
const cartList = document.getElementById("cart-items-list");
|
const cartList = document.getElementById("cart-items-list");
|
||||||
const totalEl = document.getElementById("cart-total-right");
|
const totalEl = document.getElementById("cart-total-right");
|
||||||
const vatEl = document.getElementById("cart-vat-right");
|
const vatEl = document.getElementById("cart-vat-right");
|
||||||
@@ -121,7 +119,7 @@ export function renderCart() {
|
|||||||
|
|
||||||
const groupedItems = groupCartItems();
|
const groupedItems = groupCartItems();
|
||||||
|
|
||||||
const header = /*html*/`
|
const header = `
|
||||||
<div class="cart-header-row">
|
<div class="cart-header-row">
|
||||||
<div class="col-amount">MENGE</div>
|
<div class="col-amount">MENGE</div>
|
||||||
<div class="col-img">VORSCHAU</div>
|
<div class="col-img">VORSCHAU</div>
|
||||||
@@ -135,11 +133,11 @@ export function renderCart() {
|
|||||||
const rows = groupedItems
|
const rows = groupedItems
|
||||||
.map((group) => {
|
.map((group) => {
|
||||||
const imageHtml = group.item.img
|
const imageHtml = group.item.img
|
||||||
? /*html*/`<img class="cart-img-small" src="${escapeHtml(group.item.img)}" alt="${escapeHtml(group.item.title)}">`
|
? `<img class="cart-img-small" src="${escapeHtml(group.item.img)}" alt="${escapeHtml(group.item.title)}">`
|
||||||
: /*html*/`<div class="cart-img-fallback">Kein Bild</div>`;
|
: `<div class="cart-img-fallback">Kein Bild</div>`;
|
||||||
const quantityHtml = group.item.category === "movie"
|
const quantityHtml = group.item.category === "movie"
|
||||||
? /*html*/`<div class="qty-static" aria-label="Feste Ticketanzahl">${group.quantity}x</div>`
|
? `<div class="qty-static" aria-label="Feste Ticketanzahl">${group.quantity}x</div>`
|
||||||
: /*html*/`
|
: `
|
||||||
<div class="qty-stepper">
|
<div class="qty-stepper">
|
||||||
<button class="btn-qty" data-action="minus" data-key="${escapeHtml(group.key)}">-</button>
|
<button class="btn-qty" data-action="minus" data-key="${escapeHtml(group.key)}">-</button>
|
||||||
<span>${group.quantity}</span>
|
<span>${group.quantity}</span>
|
||||||
@@ -147,7 +145,7 @@ export function renderCart() {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return /*html*/`
|
return `
|
||||||
<div class="cart-item-row">
|
<div class="cart-item-row">
|
||||||
<div class="col-amount">
|
<div class="col-amount">
|
||||||
${quantityHtml}
|
${quantityHtml}
|
||||||
@@ -174,23 +172,22 @@ export function renderCart() {
|
|||||||
|
|
||||||
saveCart();
|
saveCart();
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
|
||||||
window.removeItem = function removeItem(id: any) {
|
window.removeItem = function removeItem(id) {
|
||||||
var localCart = cart.filter((item: { id: any; }) => item.id !== id);
|
cart = cart.filter((item) => item.id !== id);
|
||||||
saveCart();
|
saveCart();
|
||||||
renderCart();
|
renderCart();
|
||||||
};
|
};
|
||||||
|
|
||||||
//@ts-ignore
|
window.changeQty = function changeQty(title, delta) {
|
||||||
window.changeQty = function changeQty(title, delta): void {
|
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
const item = cart.find((entry: { title: any; }) => entry.title === title);
|
const item = cart.find((entry) => entry.title === title);
|
||||||
if (item) {
|
if (item) {
|
||||||
cart.push({ ...item, id: Date.now() + Math.random() });
|
cart.push({ ...item, id: Date.now() + Math.random() });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const index = cart
|
const index = cart
|
||||||
.map((entry: { title: any; }) => entry.title)
|
.map((entry) => entry.title)
|
||||||
.lastIndexOf(title);
|
.lastIndexOf(title);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
cart.splice(index, 1);
|
cart.splice(index, 1);
|
||||||
@@ -200,4 +197,3 @@ window.changeQty = function changeQty(title, delta): void {
|
|||||||
saveCart();
|
saveCart();
|
||||||
renderCart();
|
renderCart();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
import { currentUser, users } from "./account";
|
function formatCheckoutEuro(value) {
|
||||||
import { renderCart, saveCart } from "./cart";
|
|
||||||
import { cart, emptyCart, occupiedSeatsData } from "./main";
|
|
||||||
|
|
||||||
function formatCheckoutEuro(value: number) {
|
|
||||||
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedPaymentMethod = "";
|
let selectedPaymentMethod = "";
|
||||||
let checkoutEventsBound = false;
|
let checkoutEventsBound = false;
|
||||||
|
|
||||||
function setCheckoutStep(step: number) {
|
function setCheckoutStep(step) {
|
||||||
const step1 = document.getElementById("checkout-step-1");
|
const step1 = document.getElementById("checkout-step-1");
|
||||||
const step2 = document.getElementById("checkout-step-2");
|
const step2 = document.getElementById("checkout-step-2");
|
||||||
const step3 = document.getElementById("checkout-step-3");
|
const step3 = document.getElementById("checkout-step-3");
|
||||||
@@ -31,7 +27,7 @@ function setCheckoutStep(step: number) {
|
|||||||
line2?.classList.toggle("active", step >= 3);
|
line2?.classList.toggle("active", step >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderCheckout() {
|
function renderCheckout() {
|
||||||
const summaryList = document.getElementById("checkout-summary-list");
|
const summaryList = document.getElementById("checkout-summary-list");
|
||||||
const totalDisplay = document.getElementById("checkout-total-display");
|
const totalDisplay = document.getElementById("checkout-total-display");
|
||||||
const vatDisplay = document.getElementById("checkout-vat-display");
|
const vatDisplay = document.getElementById("checkout-vat-display");
|
||||||
@@ -97,7 +93,7 @@ function generateTicket() {
|
|||||||
const qrData = encodeURIComponent(`EAGLE-IMAX|${mainMovie.title}|${mainMovie.hall}|${matchingMovieSeats}`);
|
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`;
|
const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${qrData}&bgcolor=ffffff`;
|
||||||
|
|
||||||
ticketContainer.innerHTML = /*html*/`
|
ticketContainer.innerHTML = `
|
||||||
<div class="luxury-ticket">
|
<div class="luxury-ticket">
|
||||||
<div class="ticket-left">
|
<div class="ticket-left">
|
||||||
<img src="${mainMovie.img}" class="ticket-poster" alt="${mainMovie.title}">
|
<img src="${mainMovie.img}" class="ticket-poster" alt="${mainMovie.title}">
|
||||||
@@ -119,7 +115,7 @@ function generateTicket() {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveOrderForCurrentUser(orderItems: any[], orderTotal: any) {
|
function saveOrderForCurrentUser(orderItems, orderTotal) {
|
||||||
if (typeof currentUser === "undefined" || !currentUser) {
|
if (typeof currentUser === "undefined" || !currentUser) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -135,7 +131,6 @@ function saveOrderForCurrentUser(orderItems: any[], orderTotal: any) {
|
|||||||
paymentMethod: selectedPaymentMethod || "-"
|
paymentMethod: selectedPaymentMethod || "-"
|
||||||
};
|
};
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
const userIndex = users.findIndex((entry) => entry.email === currentUser.email);
|
const userIndex = users.findIndex((entry) => entry.email === currentUser.email);
|
||||||
if (userIndex === -1) {
|
if (userIndex === -1) {
|
||||||
return;
|
return;
|
||||||
@@ -149,7 +144,7 @@ function saveOrderForCurrentUser(orderItems: any[], orderTotal: any) {
|
|||||||
localStorage.setItem("eagleUsers", JSON.stringify(users));
|
localStorage.setItem("eagleUsers", JSON.stringify(users));
|
||||||
}
|
}
|
||||||
|
|
||||||
function reserveSeatsAfterPayment(orderItems: any[]) {
|
function reserveSeatsAfterPayment(orderItems) {
|
||||||
const movieItems = orderItems.filter((item) => item.category === "movie");
|
const movieItems = orderItems.filter((item) => item.category === "movie");
|
||||||
|
|
||||||
movieItems.forEach((item) => {
|
movieItems.forEach((item) => {
|
||||||
@@ -171,7 +166,7 @@ function completeCheckout() {
|
|||||||
saveOrderForCurrentUser(orderItems, orderTotal);
|
saveOrderForCurrentUser(orderItems, orderTotal);
|
||||||
reserveSeatsAfterPayment(orderItems);
|
reserveSeatsAfterPayment(orderItems);
|
||||||
|
|
||||||
emptyCart?.()
|
cart = [];
|
||||||
saveCart?.();
|
saveCart?.();
|
||||||
renderCart?.();
|
renderCart?.();
|
||||||
}
|
}
|
||||||
@@ -185,7 +180,7 @@ function bindCheckoutEvents() {
|
|||||||
|
|
||||||
const nextButton = document.getElementById("btn-next-step-2");
|
const nextButton = document.getElementById("btn-next-step-2");
|
||||||
const backButton = document.getElementById("btn-back-to-step1");
|
const backButton = document.getElementById("btn-back-to-step1");
|
||||||
const payNowButton = document.getElementById("btn-pay-now") as HTMLButtonElement;
|
const payNowButton = document.getElementById("btn-pay-now");
|
||||||
|
|
||||||
document.querySelectorAll(".payment-method").forEach((method) => {
|
document.querySelectorAll(".payment-method").forEach((method) => {
|
||||||
method.addEventListener("click", () => {
|
method.addEventListener("click", () => {
|
||||||
@@ -194,7 +189,6 @@ function bindCheckoutEvents() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
method.classList.add("selected");
|
method.classList.add("selected");
|
||||||
//@ts-ignore
|
|
||||||
selectedPaymentMethod = method.dataset.method || "";
|
selectedPaymentMethod = method.dataset.method || "";
|
||||||
nextButton?.classList.remove("hidden");
|
nextButton?.classList.remove("hidden");
|
||||||
});
|
});
|
||||||
430
index.html
430
index.html
@@ -267,15 +267,208 @@
|
|||||||
<h1 class="list-title">Snacks & Getränke</h1>
|
<h1 class="list-title">Snacks & Getränke</h1>
|
||||||
|
|
||||||
<div class="category-tabs">
|
<div class="category-tabs">
|
||||||
<button class="tab-btn active" data-target="cat-getraenke">Getränke</button>
|
<button class="tab-btn active" data-target="cat-limited">Limitierte Specials</button>
|
||||||
|
<button class="tab-btn" data-target="cat-getraenke">Getränke</button>
|
||||||
<button class="tab-btn" data-target="cat-popcorn">Popcorn</button>
|
<button class="tab-btn" data-target="cat-popcorn">Popcorn</button>
|
||||||
<button class="tab-btn" data-target="cat-nachos">Nachos</button>
|
<button class="tab-btn" data-target="cat-nachos">Nachos</button>
|
||||||
<button class="tab-btn" data-target="cat-snacks">Snacks</button>
|
<button class="tab-btn" data-target="cat-snacks">Snacks</button>
|
||||||
<button class="tab-btn" data-target="cat-kombi">Kombi</button>
|
|
||||||
<button class="tab-btn" data-target="cat-eis">Eis</button>
|
<button class="tab-btn" data-target="cat-eis">Eis</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="cat-getraenke" class="snack-category active">
|
<div id="cat-limited" class="snack-category active limited-specials-category">
|
||||||
|
<div class="limited-specials-hero">
|
||||||
|
<div>
|
||||||
|
<span class="limited-kicker">Nur für kurze Zeit</span>
|
||||||
|
<h2>Limitierte Specials</h2>
|
||||||
|
<p>Filmbecher, Sammler-Eimer und Kids-Menüs als kleine Vitrine für besondere Aktionen.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="limited-special-block">
|
||||||
|
<div class="special-film-heading">
|
||||||
|
<img src="img/Zoomania-2.jpg" alt="Zoomania 2 Logo">
|
||||||
|
<div>
|
||||||
|
<span>Zoomania 2</span>
|
||||||
|
<h2>City Edition</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="limited-special-grid">
|
||||||
|
<div class="snack-card limited-special-card">
|
||||||
|
<div class="snack-img"><img src="img/zoomania-popcorn.jpg" alt="Zoomania 2 Metallbecher"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Metallbecher</span>
|
||||||
|
<h3>Limitierter Metallbecher - Zoomania 2</h3>
|
||||||
|
<p class="snack-card-note">Sammlerbecher mit Popcornfüllung, wahlweise süß oder salzig.</p>
|
||||||
|
<div class="option-group">
|
||||||
|
<button class="opt-btn active">Süß</button>
|
||||||
|
<button class="opt-btn">Salzig</button>
|
||||||
|
</div>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Special <span>12,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="snack-card limited-special-card wide-special">
|
||||||
|
<div class="snack-img"><img src="img/zoomaniakidsmenu.jpg" alt="Zoomania Kids Menu"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Kids Special</span>
|
||||||
|
<h3>Zoomania Kids Menü</h3>
|
||||||
|
<p class="snack-card-note">0,5L Getränk im Zoomania Becher + Zoomania Popcorn Schale + Figur zum Aussuchen.</p>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Menü-Preis <span>10,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="limited-special-block">
|
||||||
|
<div class="special-film-heading">
|
||||||
|
<img src="img/screamvii.jpg" alt="Scream VII Logo">
|
||||||
|
<div>
|
||||||
|
<span>Scream VII</span>
|
||||||
|
<h2>Horror Collectors</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="limited-special-grid compact-specials">
|
||||||
|
<div class="snack-card limited-special-card">
|
||||||
|
<div class="snack-img"><img src="img/screamdoorpopcorn.jpg" alt="Scream VII Sammelbecher"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Collector</span>
|
||||||
|
<h3>Limitierter Sammelbecher - Scream VII</h3>
|
||||||
|
<p class="snack-card-note">Dunkler Sammlerbecher passend zum Horrorabend.</p>
|
||||||
|
<div class="option-group">
|
||||||
|
<button class="opt-btn active">Süß</button>
|
||||||
|
<button class="opt-btn">Salzig</button>
|
||||||
|
</div>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Special <span>29,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="limited-special-block">
|
||||||
|
<div class="special-film-heading">
|
||||||
|
<img src="img/derAustronaut.jpg" alt="Der Austronaut Logo">
|
||||||
|
<div>
|
||||||
|
<span>Project Hail Mary</span>
|
||||||
|
<h2>Space Collection</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="limited-special-grid compact-specials">
|
||||||
|
<div class="snack-card limited-special-card">
|
||||||
|
<div class="snack-img"><img src="img/astronautpopcorn.jpg" alt="Der Austronaut Sammelbecher"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Space Cup</span>
|
||||||
|
<h3>Limitierter Sammelbecher - Der Austronaut</h3>
|
||||||
|
<p class="snack-card-note">Großer Sammlerbecher im Sci-Fi-Look für deine Mission ins Kino.</p>
|
||||||
|
<div class="option-group">
|
||||||
|
<button class="opt-btn active">Süß</button>
|
||||||
|
<button class="opt-btn">Salzig</button>
|
||||||
|
</div>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Special <span>34,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="limited-special-block">
|
||||||
|
<div class="special-film-heading">
|
||||||
|
<img src="img/hoppers.jpg" alt="Hoppers Logo">
|
||||||
|
<div>
|
||||||
|
<span>Hoppers</span>
|
||||||
|
<h2>Family Specials</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="limited-special-grid">
|
||||||
|
<div class="snack-card limited-special-card">
|
||||||
|
<div class="snack-img"><img src="img/hopperspopcornmetall.jpg" alt="Hoppers Metallbecher"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Metallbecher</span>
|
||||||
|
<h3>Limitierter Metallbecher - Hoppers</h3>
|
||||||
|
<p class="snack-card-note">Stabiler Becher mit Popcornfüllung.</p>
|
||||||
|
<div class="option-group">
|
||||||
|
<button class="opt-btn active">Süß</button>
|
||||||
|
<button class="opt-btn">Salzig</button>
|
||||||
|
</div>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Special <span>12,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="snack-card limited-special-card">
|
||||||
|
<div class="snack-img"><img src="img/hopperspopcornwood.png" alt="Hoppers Sammelbecher"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Collector</span>
|
||||||
|
<h3>Limitierter Sammelbecher - Hoppers</h3>
|
||||||
|
<p class="snack-card-note">Sammlerbecher mit warmem Popcornmoment.</p>
|
||||||
|
<div class="option-group">
|
||||||
|
<button class="opt-btn active">Süß</button>
|
||||||
|
<button class="opt-btn">Salzig</button>
|
||||||
|
</div>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Special <span>21,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="snack-card limited-special-card wide-special">
|
||||||
|
<div class="snack-img"><img src="img/hopperskidsmenu.jpg" alt="Hoppers Kids Menu"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Kids Special</span>
|
||||||
|
<h3>Hoppers Kids Menü</h3>
|
||||||
|
<p class="snack-card-note">0,5L Getränk im Hoppers Becher + Hoppers Popcorn Schale + Hoppers Figur.</p>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Menü-Preis <span>10,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="limited-special-block">
|
||||||
|
<div class="special-film-heading">
|
||||||
|
<img src="img/mariogalaxy.jpg" alt="Mario Galaxy Logo">
|
||||||
|
<div>
|
||||||
|
<span>Super Mario Galaxy</span>
|
||||||
|
<h2>Galaxy Specials</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="limited-special-grid">
|
||||||
|
<div class="snack-card limited-special-card">
|
||||||
|
<div class="snack-img"><img src="img/marioyoshipopcorn.png" alt="Yoshi Sammelbecher"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Yoshi Cup</span>
|
||||||
|
<h3>Limitierter Sammelbecher - Yoshi Becher</h3>
|
||||||
|
<p class="snack-card-note">Verspielter Sammlerbecher für Mario-Fans.</p>
|
||||||
|
<div class="option-group">
|
||||||
|
<button class="opt-btn active">Süß</button>
|
||||||
|
<button class="opt-btn">Salzig</button>
|
||||||
|
</div>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Special <span>35,90€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="snack-card limited-special-card wide-special">
|
||||||
|
<div class="snack-img"><img src="img/mariokidsmenu.png" alt="Mario Kids Menu"></div>
|
||||||
|
<div class="snack-info">
|
||||||
|
<span class="badge">Kids Special</span>
|
||||||
|
<h3>Mario Galaxy Kids Menü</h3>
|
||||||
|
<p class="snack-card-note">0,5L Getränk im Mario Galaxy Becher + Mario Galaxy Popcorn Schale.</p>
|
||||||
|
<div class="size-selector">
|
||||||
|
<button class="size-chip">Menü-Preis <span>10,00€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="cat-getraenke" class="snack-category hidden">
|
||||||
<div class="snack-grid">
|
<div class="snack-grid">
|
||||||
|
|
||||||
<div class="snack-card">
|
<div class="snack-card">
|
||||||
@@ -392,6 +585,11 @@
|
|||||||
</div> </div>
|
</div> </div>
|
||||||
|
|
||||||
<div id="cat-popcorn" class="snack-category hidden">
|
<div id="cat-popcorn" class="snack-category hidden">
|
||||||
|
<div class="snack-subsection">
|
||||||
|
<div class="snack-section-heading">
|
||||||
|
<span>Frisch gepoppt</span>
|
||||||
|
<h2>Einzelprodukte</h2>
|
||||||
|
</div>
|
||||||
<div class="snack-grid">
|
<div class="snack-grid">
|
||||||
<div class="snack-card">
|
<div class="snack-card">
|
||||||
<div class="snack-img"><img src="img/popcorn-klein.png" alt="Popcorn klein"></div>
|
<div class="snack-img"><img src="img/popcorn-klein.png" alt="Popcorn klein"></div>
|
||||||
@@ -402,7 +600,7 @@
|
|||||||
<button class="opt-btn">Salzig</button>
|
<button class="opt-btn">Salzig</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">3,50€</button>
|
<button class="size-chip">Klein <span>3,50€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -415,7 +613,7 @@
|
|||||||
<button class="opt-btn">Salzig</button>
|
<button class="opt-btn">Salzig</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">4,50€</button>
|
<button class="size-chip">Mittel <span>4,50€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -428,91 +626,56 @@
|
|||||||
<button class="opt-btn">Salzig</button>
|
<button class="opt-btn">Salzig</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">6,00€</button>
|
<button class="size-chip">Groß <span>6,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="snack-card">
|
</div>
|
||||||
<div class="snack-img"><img src="img/zoomania-popcorn.jpg" alt="Popcorn limited - zoomania 2"></div>
|
</div>
|
||||||
|
|
||||||
|
<div class="snack-subsection">
|
||||||
|
<div class="snack-section-heading popcorn-combo-heading">
|
||||||
|
<span>Für Filmabende</span>
|
||||||
|
<h2>Kombi Menü</h2>
|
||||||
|
</div>
|
||||||
|
<div class="snack-grid">
|
||||||
|
<div class="snack-card highlight">
|
||||||
<div class="snack-info">
|
<div class="snack-info">
|
||||||
<h3>Limitierter Metallbecher - Zoomania 2</h3>
|
<h3>Kleines Menü</h3>
|
||||||
<div class="option-group">
|
<p class="snack-card-note">0,33L Getränk + Popcorn klein</p>
|
||||||
<button class="opt-btn active">Süß</button>
|
|
||||||
<button class="opt-btn">Salzig</button>
|
|
||||||
</div>
|
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">12,00€</button>
|
<button class="size-chip">Menü-Preis <span>5,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="snack-card">
|
<div class="snack-card highlight">
|
||||||
<div class="snack-img"><img src="img/screamdoorpopcorn.jpg" alt="Popcorn limited - Scream VII"></div>
|
|
||||||
<div class="snack-info">
|
<div class="snack-info">
|
||||||
<h3>Limitierter Sammelbecher - Scream VII</h3>
|
<h3>Mittleres Menü</h3>
|
||||||
<div class="option-group">
|
<p class="snack-card-note">0,5L Getränk + Popcorn mittel</p>
|
||||||
<button class="opt-btn active">Süß</button>
|
|
||||||
<button class="opt-btn">Salzig</button>
|
|
||||||
</div>
|
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">29,00€</button>
|
<button class="size-chip">Menü-Preis <span>6,50€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="snack-card">
|
<div class="snack-card highlight">
|
||||||
<div class="snack-img"><img src="img/astronautpopcorn.jpg" alt="Popcorn limited - Der Austronaut"></div>
|
|
||||||
<div class="snack-info">
|
<div class="snack-info">
|
||||||
<h3>Limitierter Sammelbecher - Der Austronaut</h3>
|
<span class="badge">Bestseller</span>
|
||||||
<div class="option-group">
|
<h3>Großes Menü</h3>
|
||||||
<button class="opt-btn active">Süß</button>
|
<p class="snack-card-note">1L Getränk + Popcorn groß</p>
|
||||||
<button class="opt-btn">Salzig</button>
|
|
||||||
</div>
|
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">34,00€</button>
|
<button class="size-chip">Menü-Preis <span>8,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="snack-card">
|
|
||||||
<div class="snack-img"><img src="img/hopperspopcornmetall.jpg" alt="Popcorn limited - Hoppers"></div>
|
|
||||||
<div class="snack-info">
|
|
||||||
<h3>Limitierter Metallbecher - Hoppers</h3>
|
|
||||||
<div class="option-group">
|
|
||||||
<button class="opt-btn active">Süß</button>
|
|
||||||
<button class="opt-btn">Salzig</button>
|
|
||||||
</div>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">12,00€</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="snack-card">
|
|
||||||
<div class="snack-img"><img src="img/hopperspopcornwood.png" alt="Popcorn limited - Hoppers"></div>
|
|
||||||
<div class="snack-info">
|
|
||||||
<h3>Limitierter Sammelbecher - Hoppers</h3>
|
|
||||||
<div class="option-group">
|
|
||||||
<button class="opt-btn active">Süß</button>
|
|
||||||
<button class="opt-btn">Salzig</button>
|
|
||||||
</div>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">21,00€</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="snack-card">
|
|
||||||
<div class="snack-img"><img src="img/marioyoshipopcorn.png" alt="Popcorn limited - Yoshi"></div>
|
|
||||||
<div class="snack-info">
|
|
||||||
<h3>Limitierter Sammelbecher - Yoshi Becher</h3>
|
|
||||||
<div class="option-group">
|
|
||||||
<button class="opt-btn active">Süß</button>
|
|
||||||
<button class="opt-btn">Salzig</button>
|
|
||||||
</div>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">35,90€</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div id="cat-nachos" class="snack-category hidden">
|
<div id="cat-nachos" class="snack-category hidden">
|
||||||
|
<div class="snack-subsection">
|
||||||
|
<div class="snack-section-heading">
|
||||||
|
<span>Nachos</span>
|
||||||
|
<h2>Einzelprodukte</h2>
|
||||||
|
</div>
|
||||||
<div class="snack-grid">
|
<div class="snack-grid">
|
||||||
<div class="snack-card">
|
<div class="snack-card">
|
||||||
<div class="snack-img"><img src="img/nachosnormal.png" alt="Nachos"></div>
|
<div class="snack-img"><img src="img/nachosnormal.png" alt="Nachos"></div>
|
||||||
@@ -523,7 +686,7 @@
|
|||||||
<button class="opt-btn">Salsa-Dip</button>
|
<button class="opt-btn">Salsa-Dip</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">Klein<span>5,00€</span></button>
|
<button class="size-chip">Klein <span>5,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -536,7 +699,7 @@
|
|||||||
<button class="opt-btn">Salsa-Dip</button>
|
<button class="opt-btn">Salsa-Dip</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">Mittel<span>6,50€</span></button>
|
<button class="size-chip">Mittel <span>6,50€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -554,12 +717,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2 class="list-title"> </h2>
|
</div>
|
||||||
<br>
|
</div>
|
||||||
<h2 class="list-title">Dips</h2>
|
|
||||||
<br>
|
<div class="snack-subsection">
|
||||||
<br>
|
<div class="snack-section-heading">
|
||||||
<br>
|
<span>Extra dazu</span>
|
||||||
|
<h2>Dips</h2>
|
||||||
|
</div>
|
||||||
|
<div class="snack-grid">
|
||||||
<div class="snack-card">
|
<div class="snack-card">
|
||||||
<div class="snack-img"><img src="img/käsedip.png" alt="Käse-Dip"></div>
|
<div class="snack-img"><img src="img/käsedip.png" alt="Käse-Dip"></div>
|
||||||
<div class="snack-info">
|
<div class="snack-info">
|
||||||
@@ -569,7 +735,7 @@
|
|||||||
<button class="opt-btn">Scharf</button>
|
<button class="opt-btn">Scharf</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">Schale<span>2,00€</span></button>
|
<button class="size-chip">Schale <span>2,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -581,7 +747,7 @@
|
|||||||
<button class="opt-btn active">Normal</button>
|
<button class="opt-btn active">Normal</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">Schale<span>2,00€</span></button>
|
<button class="size-chip">Schale <span>2,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -593,25 +759,32 @@
|
|||||||
<button class="opt-btn active">Normal</button>
|
<button class="opt-btn active">Normal</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">Schale<span>2,00€</span></button>
|
<button class="size-chip">Schale <span>2,00€</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2 class="list-title">Nacho Kombi-Menüs</h2>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="snack-subsection">
|
||||||
|
<div class="snack-section-heading">
|
||||||
|
<span>Alles drin</span>
|
||||||
|
<h2>Kombi Menü</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="snack-card">
|
<div class="snack-grid">
|
||||||
|
<div class="snack-card highlight">
|
||||||
<div class="snack-img"><img src="img/nachokombiklein.png" alt="Nacho Kombi Klein"></div>
|
<div class="snack-img"><img src="img/nachokombiklein.png" alt="Nacho Kombi Klein"></div>
|
||||||
<div class="snack-info">
|
<div class="snack-info">
|
||||||
<h3>Nacho Menü Klein - Nachos klein + 1 Dip + 1 0,33L Getränk</h3>
|
<h3>Nacho Menü Klein</h3>
|
||||||
|
<p class="snack-card-note">Nachos klein + 1 Dip + 1x 0,33L Getränk</p>
|
||||||
<div class="option-group">
|
<div class="option-group">
|
||||||
<button class="opt-btn active">Klein</button>
|
<button class="opt-btn active">Klein</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="size-selector">
|
<div class="size-selector">
|
||||||
<button class="size-chip">Kombi<span>6,90€</span></button>
|
<button class="size-chip">Kombi <span>6,90€</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -647,75 +820,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="cat-kombi" class="snack-category hidden">
|
|
||||||
<div class="snack-grid">
|
|
||||||
<div class="snack-card highlight">
|
|
||||||
<div class="snack-info">
|
|
||||||
<h3>Kleines Menü</h3>
|
|
||||||
<p style="font-size: 0.8rem; color: #86868b; margin-bottom: 10px;">0,33L Getränk + Popcorn Klein</p>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">Menü-Preis <span>5,00€</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="snack-card highlight">
|
|
||||||
<div class="snack-info">
|
|
||||||
<h3>Mittleres Menü</h3>
|
|
||||||
<p style="font-size: 0.8rem; color: #86868b; margin-bottom: 10px;">0,5L Getränk + Popcorn Mittel</p>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">Menü-Preis <span>6,50€</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="snack-card highlight">
|
|
||||||
<div class="snack-info">
|
|
||||||
<span class="badge">Bestseller</span>
|
|
||||||
<h3>Großes Menü</h3>
|
|
||||||
<p style="font-size: 0.8rem; color: #86868b; margin-bottom: 10px;">1L Getränk + Popcorn Groß</p>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">Menü-Preis <span>8,00€</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="snack-card highlight">
|
|
||||||
<div class="snack-info">
|
|
||||||
<div class="snack-img"><img src="img/hopperskidsmenu.jpg" alt="Hoppers Kids Menu"></div>
|
|
||||||
<span class="badge">SPECIAL</span>
|
|
||||||
<h3>Limitiertes Menü</h3>
|
|
||||||
<p style="font-size: 0.8rem; color: #86868b; margin-bottom: 10px;">0,5L Getränk im HOPPERS Becher + HOPPERS Popcorn Schale<br>+HOPPERS Figur</p>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">Menü-Preis <span>10,00€</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="snack-card highlight">
|
|
||||||
<div class="snack-info">
|
|
||||||
<div class="snack-img"><img src="img/mariokidsmenu.png" alt="Mario Kids Menu"></div>
|
|
||||||
<br>
|
|
||||||
<span class="badge">SPECIAL</span>
|
|
||||||
<h3>Limitiertes Menü</h3>
|
|
||||||
<p style="font-size: 0.8rem; color: #86868b; margin-bottom: 10px;">0,5L Getränk im MARIO GALXY Becher + MARIO GALAXY Popcorn Schale</p>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">Menü-Preis <span>10,00€</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="snack-card highlight">
|
|
||||||
<div class="snack-info">
|
|
||||||
<div class="snack-img"><img src="img/zoomaniakidsmenu.jpg" alt="Zoomania Kids Menu"></div>
|
|
||||||
<br>
|
|
||||||
<span class="badge">SPECIAL</span>
|
|
||||||
<h3>Limitiertes Menü</h3>
|
|
||||||
<p style="font-size: 0.8rem; color: #86868b; margin-bottom: 10px;">0,5L Getränk im ZOOMANIA Becher + ZOOMANIA Popcorn Schale<br>+ Figur zum aussuchen</p>
|
|
||||||
<div class="size-selector">
|
|
||||||
<button class="size-chip">Menü-Preis <span>10,00€</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="cat-eis" class="snack-category hidden">
|
<div id="cat-eis" class="snack-category hidden">
|
||||||
<div class="coming-soon-banner">
|
<div class="coming-soon-banner">
|
||||||
<h2>Eiscreme & Shakes</h2>
|
<h2>Eiscreme & Shakes</h2>
|
||||||
@@ -735,8 +839,8 @@
|
|||||||
<div class="header-sub-info">
|
<div class="header-sub-info">
|
||||||
<p id="modal-info-text">Saal • Zeit</p>
|
<p id="modal-info-text">Saal • Zeit</p>
|
||||||
<div id="tech-badges" class="tech-badges-container hidden">
|
<div id="tech-badges" class="tech-badges-container hidden">
|
||||||
<img src="img/Dolby.png" alt="Dolby" class="tech-badge">
|
<img src="img/dolby.png" alt="Dolby" class="tech-badge">
|
||||||
<img src="img/dbox.jpg" alt="D-Box" class="tech-badge">
|
<img src="img/dbox.png" alt="D-Box" class="tech-badge">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -948,11 +1052,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="src/main.js"></script>
|
<script src="account.js"></script>
|
||||||
<script src="src/cart.js"></script>
|
<script src="cart.js"></script>
|
||||||
<script src="src/booking.js"></script>
|
<script src="booking.js"></script>
|
||||||
<script src="src/checkout.js"></script>
|
<script src="checkout.js"></script>
|
||||||
<script type="module" src="dist/account.js"></script>
|
<script src="main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
import { currentUser, loginUser, openAccountDashboard, registerUser } from "./account";
|
// Shared app state for legacy script files (account.js, booking.js, cart.js, checkout.js)
|
||||||
import { openBooking } from "./booking";
|
var prices = { normal: 11.0, imax: 15.0, vip: 12.0, dbox: 16.0 };
|
||||||
import { renderCart, saveCart, updateCartBadge } from "./cart";
|
var seatLayouts = {
|
||||||
import { renderCheckout } from "./checkout";
|
|
||||||
|
|
||||||
// Shared app state for legacy script files (account.js, booking.js, cart.js, checkout.js)
|
|
||||||
export const prices: Record<string, number> = { normal: 11.0, imax: 15.0, vip: 12.0, dbox: 16.0 };
|
|
||||||
export var seatLayouts = {
|
|
||||||
"Kino 1": { rows: 6, left: 3, right: 7, vipRows: [5], dbox: [] },
|
"Kino 1": { rows: 6, left: 3, right: 7, vipRows: [5], dbox: [] },
|
||||||
"Kino 2": { rows: 7, left: 5, right: 5, vipRows: [6], dbox: [] },
|
"Kino 2": { rows: 7, left: 5, right: 5, vipRows: [6], dbox: [] },
|
||||||
"Deluxe 1": { rows: 10, left: 7, right: 8, vipRows: [9], dbox: [{ r: 4, c: 5, w: 4 }] },
|
"Deluxe 1": { rows: 10, left: 7, right: 8, vipRows: [9], dbox: [{ r: 4, c: 5, w: 4 }] },
|
||||||
IMAX: { rows: 15, left: 10, right: 10, vipRows: [], dbox: [], isImax: true }
|
IMAX: { rows: 15, left: 10, right: 10, vipRows: [], dbox: [], isImax: true }
|
||||||
};
|
};
|
||||||
export var cart = JSON.parse(localStorage.getItem("eagleCart") || '{}');
|
var cart = JSON.parse(localStorage.getItem("eagleCart")) || [];
|
||||||
export var occupiedSeatsData = JSON.parse(localStorage.getItem("eagleOccupied") || '{}');
|
var occupiedSeatsData = JSON.parse(localStorage.getItem("eagleOccupied")) || {};
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const views = {
|
const views = {
|
||||||
@@ -331,10 +326,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
["13:00", "16:00", "18:20", "20:40"]
|
["13:00", "16:00", "18:20", "20:40"]
|
||||||
];
|
];
|
||||||
|
|
||||||
let movieProgram: any = []; // TODO: Find type
|
let movieProgram = [];
|
||||||
let heroItems: any = []; // TODO: find Type
|
let heroItems = [];
|
||||||
let heroIndex = 0;
|
let heroIndex = 0;
|
||||||
let heroTimer:any = null; // TODO: find type
|
let heroTimer = null;
|
||||||
|
|
||||||
const weekdayShort = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
|
const weekdayShort = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
|
||||||
|
|
||||||
@@ -353,7 +348,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
};
|
};
|
||||||
|
|
||||||
const showMovieList = (programIndexToFocus:number = NaN) => {
|
const showMovieList = (programIndexToFocus = null) => {
|
||||||
hideAllViews();
|
hideAllViews();
|
||||||
views.list?.classList.remove("hidden");
|
views.list?.classList.remove("hidden");
|
||||||
|
|
||||||
@@ -370,7 +365,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showStaticView = (viewElement: HTMLElement) => {
|
const showStaticView = (viewElement) => {
|
||||||
if (!viewElement) {
|
if (!viewElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -399,20 +394,20 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
ui.bookingModal?.classList.add("hidden");
|
ui.bookingModal?.classList.add("hidden");
|
||||||
};
|
};
|
||||||
|
|
||||||
const escapeHtml = (value: string) => String(value || "")
|
const escapeHtml = (value) => String(value || "")
|
||||||
.replaceAll("&", "&")
|
.replaceAll("&", "&")
|
||||||
.replaceAll("<", "<")
|
.replaceAll("<", "<")
|
||||||
.replaceAll(">", ">")
|
.replaceAll(">", ">")
|
||||||
.replaceAll('"', """)
|
.replaceAll('"', """)
|
||||||
.replaceAll("'", "'");
|
.replaceAll("'", "'");
|
||||||
|
|
||||||
const formatDateShort = (dateObj: any) => {
|
const formatDateShort = (dateObj) => {
|
||||||
const day = String(dateObj.getDate()).padStart(2, "0");
|
const day = String(dateObj.getDate()).padStart(2, "0");
|
||||||
const month = String(dateObj.getMonth() + 1).padStart(2, "0");
|
const month = String(dateObj.getMonth() + 1).padStart(2, "0");
|
||||||
return `${day}.${month}.`;
|
return `${day}.${month}.`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildDayMeta = (offset: number) => {
|
const buildDayMeta = (offset) => {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
date.setHours(0, 0, 0, 0);
|
date.setHours(0, 0, 0, 0);
|
||||||
date.setDate(date.getDate() + offset);
|
date.setDate(date.getDate() + offset);
|
||||||
@@ -446,15 +441,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildScheduleForMovie = (movieIndex: number) => {
|
const buildScheduleForMovie = (movieIndex) => {
|
||||||
return Array.from({ length: 7 }, (_, dayOffset) => {
|
return Array.from({ length: 7 }, (_, dayOffset) => {
|
||||||
const dayMeta = buildDayMeta(dayOffset);
|
const dayMeta = buildDayMeta(dayOffset);
|
||||||
const pattern = timePatterns[(movieIndex + dayOffset) % timePatterns.length] || "Error reading";
|
const pattern = timePatterns[(movieIndex + dayOffset) % timePatterns.length];
|
||||||
const desiredCount = 4 + ((movieIndex + dayOffset) % 2);
|
const desiredCount = 4 + ((movieIndex + dayOffset) % 2);
|
||||||
const showCount = Math.min(pattern.length, desiredCount);
|
const showCount = Math.min(pattern.length, desiredCount);
|
||||||
|
|
||||||
//@ts-ignore
|
const showings = pattern.slice(0, showCount).map((time, slotIndex) => {
|
||||||
const showings = pattern.slice(0, showCount).map((time: any, slotIndex: number) => { // TODO: fix map issue
|
|
||||||
const hall = hallRotation[(movieIndex + dayOffset + slotIndex) % hallRotation.length];
|
const hall = hallRotation[(movieIndex + dayOffset + slotIndex) % hallRotation.length];
|
||||||
return { time, hall };
|
return { time, hall };
|
||||||
});
|
});
|
||||||
@@ -474,7 +468,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
heroItems = movieProgram.slice(0, 5);
|
heroItems = movieProgram.slice(0, 5);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setHeroSlide = (index: number) => {
|
const setHeroSlide = (index) => {
|
||||||
if (!heroItems.length || !ui.heroSlider) {
|
if (!heroItems.length || !ui.heroSlider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -503,18 +497,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.heroSlider.innerHTML = heroItems.map((movie: any, index: number) => `
|
ui.heroSlider.innerHTML = heroItems.map((movie, index) => `
|
||||||
<div class="hero-slide ${index === 0 ? "active" : ""}" style="background-image: linear-gradient(118deg, rgba(0,0,0,0.34), rgba(0,0,0,0.04)), url('${escapeHtml(movie.backdrop || movie.poster)}');"></div>
|
<div class="hero-slide ${index === 0 ? "active" : ""}" style="background-image: linear-gradient(118deg, rgba(0,0,0,0.34), rgba(0,0,0,0.04)), url('${escapeHtml(movie.backdrop || movie.poster)}');"></div>
|
||||||
`).join("");
|
`).join("");
|
||||||
|
|
||||||
if (ui.heroDots) {
|
if (ui.heroDots) {
|
||||||
ui.heroDots.innerHTML = heroItems.map((_:any, index: number) => `
|
ui.heroDots.innerHTML = heroItems.map((_, index) => `
|
||||||
<button type="button" class="hero-dot ${index === 0 ? "active" : ""}" data-hero-index="${index}"></button>
|
<button type="button" class="hero-dot ${index === 0 ? "active" : ""}" data-hero-index="${index}"></button>
|
||||||
`).join("");
|
`).join("");
|
||||||
|
|
||||||
ui.heroDots.addEventListener("click", (event: any) => {
|
ui.heroDots.addEventListener("click", (event) => {
|
||||||
const dotTarget = event.target || 0;
|
const dot = event.target.closest(".hero-dot");
|
||||||
const dot = dotTarget.closest(".hero-dot");
|
|
||||||
if (!dot) {
|
if (!dot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -545,8 +538,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement movie interface
|
ui.nowRunningRow.innerHTML = movieProgram.map((movie, index) => `
|
||||||
ui.nowRunningRow.innerHTML = movieProgram.map((movie: any, index: number) => /*html*/`
|
|
||||||
<article class="running-poster">
|
<article class="running-poster">
|
||||||
<img src="${escapeHtml(movie.poster)}" alt="${escapeHtml(movie.title)}">
|
<img src="${escapeHtml(movie.poster)}" alt="${escapeHtml(movie.title)}">
|
||||||
<div class="running-meta">
|
<div class="running-meta">
|
||||||
@@ -558,7 +550,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
`).join("");
|
`).join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderScheduleRows = (programIndex: number, dayIndex: number) => {
|
const renderScheduleRows = (programIndex, dayIndex) => {
|
||||||
const movie = movieProgram[programIndex];
|
const movie = movieProgram[programIndex];
|
||||||
if (!movie) {
|
if (!movie) {
|
||||||
return;
|
return;
|
||||||
@@ -570,7 +562,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.innerHTML = day.showings.map((showing: { hall: string; time: string; }) => /*html*/`
|
body.innerHTML = day.showings.map((showing) => `
|
||||||
<button class="schedule-row time-chip program-time-row" data-movie="${escapeHtml(movie.title)}" data-hall="${escapeHtml(showing.hall)}" data-time="${escapeHtml(showing.time)}">
|
<button class="schedule-row time-chip program-time-row" data-movie="${escapeHtml(movie.title)}" data-hall="${escapeHtml(showing.hall)}" data-time="${escapeHtml(showing.time)}">
|
||||||
<span>${escapeHtml(day.long)}</span>
|
<span>${escapeHtml(day.long)}</span>
|
||||||
<span class="hall-pill">${escapeHtml(showing.hall)}</span>
|
<span class="hall-pill">${escapeHtml(showing.hall)}</span>
|
||||||
@@ -584,15 +576,15 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.movieProgramList.innerHTML = movieProgram.map((movie: { schedule: any[]; poster: string; title: string; fsk: string; duration: any; genre: string; description: string; }, programIndex: any) => {
|
ui.movieProgramList.innerHTML = movieProgram.map((movie, programIndex) => {
|
||||||
const dayTabs = movie.schedule.map((day, dayIndex) => /*html*/`
|
const dayTabs = movie.schedule.map((day, dayIndex) => `
|
||||||
<button type="button" class="program-day-tab ${dayIndex === 0 ? "active" : ""}" data-program-index="${programIndex}" data-day-index="${dayIndex}">
|
<button type="button" class="program-day-tab ${dayIndex === 0 ? "active" : ""}" data-program-index="${programIndex}" data-day-index="${dayIndex}">
|
||||||
<span>${escapeHtml(day.short)}</span>
|
<span>${escapeHtml(day.short)}</span>
|
||||||
<small>${escapeHtml(formatDateShort(day.date))}</small>
|
<small>${escapeHtml(formatDateShort(day.date))}</small>
|
||||||
</button>
|
</button>
|
||||||
`).join("");
|
`).join("");
|
||||||
|
|
||||||
return /*html*/`
|
return `
|
||||||
<article class="detailed-card program-card reveal-on-scroll" data-program-index="${programIndex}">
|
<article class="detailed-card program-card reveal-on-scroll" data-program-index="${programIndex}">
|
||||||
<div class="card-left">
|
<div class="card-left">
|
||||||
<img src="${escapeHtml(movie.poster)}" alt="${escapeHtml(movie.title)}">
|
<img src="${escapeHtml(movie.poster)}" alt="${escapeHtml(movie.title)}">
|
||||||
@@ -618,7 +610,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
`;
|
`;
|
||||||
}).join("");
|
}).join("");
|
||||||
|
|
||||||
movieProgram.forEach((_: any, programIndex: number) => {
|
movieProgram.forEach((_, programIndex) => {
|
||||||
renderScheduleRows(programIndex, 0);
|
renderScheduleRows(programIndex, 0);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -666,16 +658,12 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
ui.linkSnacks?.addEventListener("click", (event) => {
|
ui.linkSnacks?.addEventListener("click", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (views.snacks) {
|
|
||||||
showStaticView(views.snacks);
|
showStaticView(views.snacks);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.linkAbout?.addEventListener("click", (event) => {
|
ui.linkAbout?.addEventListener("click", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (views.about) {
|
|
||||||
showStaticView(views.about);
|
showStaticView(views.about);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.linkCart?.addEventListener("click", (event) => {
|
ui.linkCart?.addEventListener("click", (event) => {
|
||||||
@@ -705,17 +693,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const bindProgramActions = () => {
|
const bindProgramActions = () => {
|
||||||
views.moviesGrid?.addEventListener("click", (event:any) => {
|
views.moviesGrid?.addEventListener("click", (event) => {
|
||||||
const trigger = event.target.closest(".open-program-btn");
|
const trigger = event.target.closest(".open-program-btn");
|
||||||
if (!trigger) {
|
if (!trigger) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const programIndex = Number(trigger.dataset.programIndex) || 0;
|
const programIndex = Number(trigger.dataset.programIndex || 0);
|
||||||
showMovieList(programIndex);
|
showMovieList(programIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.movieProgramList?.addEventListener("click", (event:any) => {
|
ui.movieProgramList?.addEventListener("click", (event) => {
|
||||||
const dayButton = event.target.closest(".program-day-tab");
|
const dayButton = event.target.closest(".program-day-tab");
|
||||||
if (!dayButton) {
|
if (!dayButton) {
|
||||||
return;
|
return;
|
||||||
@@ -725,7 +713,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
const dayIndex = Number(dayButton.dataset.dayIndex || 0);
|
const dayIndex = Number(dayButton.dataset.dayIndex || 0);
|
||||||
|
|
||||||
const tabRow = dayButton.closest(".program-day-tabs");
|
const tabRow = dayButton.closest(".program-day-tabs");
|
||||||
tabRow?.querySelectorAll(".program-day-tab").forEach((tab: { classList: { remove: (arg0: string) => any; }; }) => tab.classList.remove("active"));
|
tabRow?.querySelectorAll(".program-day-tab").forEach((tab) => tab.classList.remove("active"));
|
||||||
dayButton.classList.add("active");
|
dayButton.classList.add("active");
|
||||||
|
|
||||||
renderScheduleRows(programIndex, dayIndex);
|
renderScheduleRows(programIndex, dayIndex);
|
||||||
@@ -751,7 +739,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
openButtons.forEach((button) => {
|
openButtons.forEach((button) => {
|
||||||
button.addEventListener("click", () => {
|
button.addEventListener("click", () => {
|
||||||
const targetId = button.getAttribute("data-home-view-open") as keyof typeof targetMap;
|
const targetId = button.getAttribute("data-home-view-open");
|
||||||
const target = targetId ? targetMap[targetId] : null;
|
const target = targetId ? targetMap[targetId] : null;
|
||||||
if (target) {
|
if (target) {
|
||||||
showStaticView(target);
|
showStaticView(target);
|
||||||
@@ -804,11 +792,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
const THEME_KEY = "eagleTheme";
|
const THEME_KEY = "eagleTheme";
|
||||||
|
|
||||||
const applyTheme = (theme: any) => {
|
const applyTheme = (theme) => {
|
||||||
const isLight = theme === "light";
|
const isLight = theme === "light";
|
||||||
document.body.classList.toggle("theme-light", isLight);
|
document.body.classList.toggle("theme-light", isLight);
|
||||||
document.body.classList.toggle("theme-dark", !isLight);
|
document.body.classList.toggle("theme-dark", !isLight);
|
||||||
//@ts-ignore
|
|
||||||
ui.themeToggle.classList.toggle("is-light", isLight);
|
ui.themeToggle.classList.toggle("is-light", isLight);
|
||||||
localStorage.setItem(THEME_KEY, isLight ? "light" : "dark");
|
localStorage.setItem(THEME_KEY, isLight ? "light" : "dark");
|
||||||
};
|
};
|
||||||
@@ -825,14 +812,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
const bindAccountActions = () => {
|
const bindAccountActions = () => {
|
||||||
const registerModal = document.getElementById("register-modal");
|
const registerModal = document.getElementById("register-modal");
|
||||||
const forgotModal = document.getElementById("forgot-modal");
|
const forgotModal = document.getElementById("forgot-modal");
|
||||||
const forgotEmailInput = document.getElementById("forgot-email") as HTMLInputElement;
|
const forgotEmailInput = document.getElementById("forgot-email");
|
||||||
const resetMessage = document.getElementById("reset-message");
|
const resetMessage = document.getElementById("reset-message");
|
||||||
const loginError = document.getElementById("login-error");
|
const loginError = document.getElementById("login-error");
|
||||||
const loginEmailInput = document.getElementById("login-email");
|
const loginEmailInput = document.getElementById("login-email");
|
||||||
const loginPasswordInput = document.getElementById("login-password");
|
const loginPasswordInput = document.getElementById("login-password");
|
||||||
|
|
||||||
const openModal = (modal: HTMLElement | null) => modal?.classList.remove("hidden");
|
const openModal = (modal) => modal?.classList.remove("hidden");
|
||||||
const closeModal = (modal: HTMLElement | null) => modal?.classList.add("hidden");
|
const closeModal = (modal) => modal?.classList.add("hidden");
|
||||||
const triggerLogin = () => {
|
const triggerLogin = () => {
|
||||||
loginError?.classList.add("hidden");
|
loginError?.classList.add("hidden");
|
||||||
if (typeof loginUser === "function") {
|
if (typeof loginUser === "function") {
|
||||||
@@ -868,7 +855,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("btn-forgot-password")?.addEventListener("click", () => {
|
document.getElementById("btn-forgot-password")?.addEventListener("click", () => {
|
||||||
if (forgotEmailInput != null) {
|
if (forgotEmailInput) {
|
||||||
forgotEmailInput.value = "";
|
forgotEmailInput.value = "";
|
||||||
}
|
}
|
||||||
resetMessage?.classList.add("hidden");
|
resetMessage?.classList.add("hidden");
|
||||||
@@ -913,10 +900,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const bindGlobalDocumentClicks = () => {
|
const bindGlobalDocumentClicks = () => {
|
||||||
document.addEventListener("click", (event: any) => {
|
document.addEventListener("click", (event) => {
|
||||||
if (event.target.classList.contains("opt-btn")) {
|
if (event.target.classList.contains("opt-btn")) {
|
||||||
const optionGroup = event.target.parentElement;
|
const optionGroup = event.target.parentElement;
|
||||||
optionGroup?.querySelectorAll(".opt-btn").forEach((button: { classList: { remove: (arg0: string) => any; }; }) => button.classList.remove("active"));
|
optionGroup?.querySelectorAll(".opt-btn").forEach((button) => button.classList.remove("active"));
|
||||||
event.target.classList.add("active");
|
event.target.classList.add("active");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,17 +912,15 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
const row = deleteBtn.closest(".cart-item-row");
|
const row = deleteBtn.closest(".cart-item-row");
|
||||||
if (row) {
|
if (row) {
|
||||||
row.classList.add("slide-out-left");
|
row.classList.add("slide-out-left");
|
||||||
row.querySelectorAll("button").forEach((button: { disabled: boolean; }) => {
|
row.querySelectorAll("button").forEach((button) => {
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
//@ts-ignore
|
removeFromCartByKey(deleteBtn.dataset.key);
|
||||||
removeFromCartByKey(deleteBtn.dataset.key); //TODO: removeFromCartByKey doesnt exist
|
|
||||||
}, 380);
|
}, 380);
|
||||||
} else {
|
} else {
|
||||||
//@ts-ignore
|
removeFromCartByKey(deleteBtn.dataset.key);
|
||||||
removeFromCartByKey(deleteBtn.dataset.key); //TODO: removeFromCartByKey doesnt exist
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -964,7 +949,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const relatedItem = cart.find((item: { category: string; seatId: any; hall: any; time: any; title: any; }) => {
|
const relatedItem = cart.find((item) => {
|
||||||
const infoText = item.category === "movie"
|
const infoText = item.category === "movie"
|
||||||
? `Sitz: ${item.seatId} (${item.hall})`
|
? `Sitz: ${item.seatId} (${item.hall})`
|
||||||
: item.time;
|
: item.time;
|
||||||
@@ -978,7 +963,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
if (action === "plus") {
|
if (action === "plus") {
|
||||||
cart.push({ ...relatedItem, id: Date.now() + Math.random() });
|
cart.push({ ...relatedItem, id: Date.now() + Math.random() });
|
||||||
} else {
|
} else {
|
||||||
const keyList = cart.map((item: { category: string; seatId: any; hall: any; time: any; title: any; }) => {
|
const keyList = cart.map((item) => {
|
||||||
const infoText = item.category === "movie"
|
const infoText = item.category === "movie"
|
||||||
? `Sitz: ${item.seatId} (${item.hall})`
|
? `Sitz: ${item.seatId} (${item.hall})`
|
||||||
: item.time;
|
: item.time;
|
||||||
@@ -997,7 +982,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const bindSnacksActions = () => {
|
const bindSnacksActions = () => {
|
||||||
ui.snacksView?.addEventListener("click", (event:any) => {
|
ui.snacksView?.addEventListener("click", (event) => {
|
||||||
const sizeChip = event.target.closest(".size-chip");
|
const sizeChip = event.target.closest(".size-chip");
|
||||||
if (!sizeChip) {
|
if (!sizeChip) {
|
||||||
return;
|
return;
|
||||||
@@ -1041,7 +1026,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}, 800);
|
}, 800);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelectorAll(".tab-btn").forEach((button: any) => {
|
document.querySelectorAll(".tab-btn").forEach((button) => {
|
||||||
button.addEventListener("click", () => {
|
button.addEventListener("click", () => {
|
||||||
document.querySelectorAll(".tab-btn").forEach((tab) => tab.classList.remove("active"));
|
document.querySelectorAll(".tab-btn").forEach((tab) => tab.classList.remove("active"));
|
||||||
button.classList.add("active");
|
button.classList.add("active");
|
||||||
@@ -1078,9 +1063,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// @ts-ignore
|
|
||||||
window.removeFromCartByKey = function removeFromCartByKey(key: string) {
|
window.removeFromCartByKey = function removeFromCartByKey(key) {
|
||||||
cart = cart.filter((item: { category: string; seatId: any; hall: any; time: any; title: any; }) => {
|
cart = cart.filter((item) => {
|
||||||
const infoText = item.category === "movie"
|
const infoText = item.category === "movie"
|
||||||
? `Sitz: ${item.seatId} (${item.hall})`
|
? `Sitz: ${item.seatId} (${item.hall})`
|
||||||
: item.time;
|
: item.time;
|
||||||
@@ -1105,8 +1090,3 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
updateCartBadge?.();
|
updateCartBadge?.();
|
||||||
renderCheckout?.();
|
renderCheckout?.();
|
||||||
});
|
});
|
||||||
|
|
||||||
export function emptyCart() {
|
|
||||||
cart = []
|
|
||||||
return
|
|
||||||
}
|
|
||||||
3093
package-lock.json
generated
3093
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "p1---kino",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "main.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"watch": "tsc --watch",
|
|
||||||
"serve": "serve .",
|
|
||||||
"run": "npm-run-all --parallel watch serve"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "ssh://git@gitea.starfour.de:2222/Aaron/Kino-Website.git"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Aaron und Jannis",
|
|
||||||
"license": "ISC",
|
|
||||||
"type": "commonjs",
|
|
||||||
"devDependencies": {
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"serve": "^14.2.6",
|
|
||||||
"typescript": "^6.0.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
export interface User {
|
|
||||||
firstName: string;
|
|
||||||
lastName: string;
|
|
||||||
email: string;
|
|
||||||
hashedPassword: string;
|
|
||||||
orders: any[]; // TODO: figure out proper array type of orders. Probably smartest do create an Order interface which this would be an array of
|
|
||||||
paymentMethods: any[]; // TODO: figure out proper array type of paymentMethods. create paymentMethod interface and make this an array of it
|
|
||||||
}
|
|
||||||
379
style.css
379
style.css
@@ -2902,15 +2902,15 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inline-halls .inline-media {
|
.inline-halls .inline-media {
|
||||||
background-image: linear-gradient(120deg, rgba(0, 113, 227, 0.3), rgba(7, 10, 16, 0.55)), url('img/shelter.jpg');
|
background-image: linear-gradient(120deg, rgba(0, 113, 227, 0.3), rgba(7, 10, 16, 0.55)), url('img/placeholder-hall.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-dbox .inline-media {
|
.inline-dbox .inline-media {
|
||||||
background-image: linear-gradient(120deg, rgba(255, 176, 0, 0.2), rgba(8, 12, 18, 0.62)), url('img/dbox.jpg');
|
background-image: linear-gradient(120deg, rgba(255, 176, 0, 0.2), rgba(8, 12, 18, 0.62)), url('img/placeholder-dbox.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-collectors .inline-media {
|
.inline-collectors .inline-media {
|
||||||
background-image: linear-gradient(120deg, rgba(185, 124, 255, 0.15), rgba(8, 12, 18, 0.62)), url('img/popcorn.jpg');
|
background-image: linear-gradient(120deg, rgba(185, 124, 255, 0.15), rgba(8, 12, 18, 0.62)), url('img/placeholder-collector.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-content {
|
.inline-content {
|
||||||
@@ -3865,3 +3865,376 @@ body.theme-light .about-card {
|
|||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- 2026-04-29 account/about/snack readability polish --- */
|
||||||
|
.snack-subsection {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snack-subsection:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snack-section-heading {
|
||||||
|
margin: 0 0 16px;
|
||||||
|
padding: 16px 18px;
|
||||||
|
border-left: 4px solid var(--accent-blue);
|
||||||
|
border-radius: 18px;
|
||||||
|
background:
|
||||||
|
linear-gradient(135deg, rgba(0, 113, 227, 0.18), rgba(255, 255, 255, 0.035)),
|
||||||
|
rgba(255, 255, 255, 0.035);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snack-section-heading span {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
color: #9ed0ff;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 1.7px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snack-section-heading h2 {
|
||||||
|
margin: 0;
|
||||||
|
color: #f5f8ff;
|
||||||
|
font-size: clamp(1.35rem, 2vw, 2rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.snack-card-note {
|
||||||
|
margin: 4px 0 12px;
|
||||||
|
color: #aeb8c6;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .account-orders-shell h3,
|
||||||
|
body.theme-dark .order-item-head h4,
|
||||||
|
body.theme-dark .order-box p,
|
||||||
|
body.theme-dark .order-box strong,
|
||||||
|
body.theme-dark .order-ticket-content h4,
|
||||||
|
body.theme-dark .order-ticket-grid strong {
|
||||||
|
color: #f4f8ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .order-box {
|
||||||
|
background: linear-gradient(145deg, #18202d 0%, #10151f 100%);
|
||||||
|
border-color: rgba(130, 180, 235, 0.2);
|
||||||
|
box-shadow: 0 14px 34px rgba(0, 0, 0, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .order-box p {
|
||||||
|
color: #d2dbe8;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .order-item-btn:hover,
|
||||||
|
body.theme-dark .order-item-btn.active {
|
||||||
|
background: linear-gradient(145deg, #1d3148 0%, #111a27 100%);
|
||||||
|
border-color: rgba(110, 185, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .order-item-head span {
|
||||||
|
color: #a9d7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .order-ticket-card {
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 18% 0%, rgba(0, 113, 227, 0.2), transparent 30%),
|
||||||
|
linear-gradient(155deg, #172235 0%, #0b111b 100%);
|
||||||
|
border-color: rgba(146, 194, 255, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-dark .order-ticket-grid span,
|
||||||
|
body.theme-dark .order-ticket-brand {
|
||||||
|
color: #b9c9dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-hero-block {
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 8% 0%, rgba(0, 113, 227, 0.12), transparent 36%),
|
||||||
|
linear-gradient(130deg, #ffffff 0%, #edf5ff 100%);
|
||||||
|
box-shadow: 0 22px 55px rgba(35, 67, 108, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-hero-content h1,
|
||||||
|
body.theme-light .about-stats-grid h3,
|
||||||
|
body.theme-light .about-card h3 {
|
||||||
|
color: #0e1b31 !important;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-hero-content p,
|
||||||
|
body.theme-light .about-stats-grid p {
|
||||||
|
color: #314763 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-pill-row span {
|
||||||
|
background: rgba(0, 113, 227, 0.11);
|
||||||
|
border-color: rgba(0, 113, 227, 0.28);
|
||||||
|
color: #064b90;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-stats-grid article {
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
border-color: rgba(24, 52, 88, 0.18);
|
||||||
|
box-shadow: 0 12px 28px rgba(42, 70, 106, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card {
|
||||||
|
border-color: rgba(22, 47, 80, 0.22);
|
||||||
|
box-shadow: 0 18px 42px rgba(31, 61, 98, 0.13);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card-halls {
|
||||||
|
background-image: url('img/zoomania-2.jpg') !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card-dbox {
|
||||||
|
background-image: url('img/shelter.jpg') !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card-tech {
|
||||||
|
background-image: url('img/spidermannewday.jpg') !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card::before {
|
||||||
|
background:
|
||||||
|
linear-gradient(175deg, rgba(255, 255, 255, 0.42) 0%, rgba(255, 255, 255, 0.93) 74%),
|
||||||
|
linear-gradient(90deg, rgba(0, 113, 227, 0.1), transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card p {
|
||||||
|
color: #263f5f !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card .story-more-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.84);
|
||||||
|
border-color: rgba(0, 83, 170, 0.24);
|
||||||
|
color: #0d3563;
|
||||||
|
box-shadow: 0 10px 24px rgba(26, 57, 95, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .about-card .story-more-btn:hover {
|
||||||
|
background: #0071e3;
|
||||||
|
border-color: #0071e3;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .snack-section-heading {
|
||||||
|
background:
|
||||||
|
linear-gradient(135deg, rgba(0, 113, 227, 0.12), rgba(255, 255, 255, 0.94)),
|
||||||
|
#ffffff;
|
||||||
|
border-color: #0071e3;
|
||||||
|
box-shadow: 0 12px 26px rgba(34, 74, 121, 0.09);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .snack-section-heading span {
|
||||||
|
color: #0057ae;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .snack-section-heading h2 {
|
||||||
|
color: #10213a;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .snack-card-note {
|
||||||
|
color: #4a5d79;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- 2026-04-29 limited snack specials --- */
|
||||||
|
.limited-specials-category {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-specials-hero {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 28px;
|
||||||
|
padding: clamp(24px, 4vw, 42px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.13);
|
||||||
|
border-radius: 28px;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 14% 16%, rgba(0, 113, 227, 0.42), transparent 34%),
|
||||||
|
radial-gradient(circle at 82% 10%, rgba(255, 178, 84, 0.2), transparent 30%),
|
||||||
|
linear-gradient(135deg, rgba(12, 18, 31, 0.96), rgba(5, 8, 14, 0.96));
|
||||||
|
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-specials-hero::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: auto -10% -45% 42%;
|
||||||
|
height: 180px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
transform: rotate(-8deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-kicker {
|
||||||
|
display: inline-flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 7px 12px;
|
||||||
|
border: 1px solid rgba(158, 208, 255, 0.38);
|
||||||
|
border-radius: 999px;
|
||||||
|
color: #9ed0ff;
|
||||||
|
font-size: 0.76rem;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-specials-hero h2 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: clamp(2rem, 5vw, 4.6rem);
|
||||||
|
letter-spacing: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-specials-hero p {
|
||||||
|
max-width: 620px;
|
||||||
|
color: #d4dfec;
|
||||||
|
line-height: 1.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-special-block {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-film-heading {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||||
|
border-radius: 22px;
|
||||||
|
background:
|
||||||
|
linear-gradient(115deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.025)),
|
||||||
|
rgba(255, 255, 255, 0.035);
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-film-heading img {
|
||||||
|
width: 76px;
|
||||||
|
height: 76px;
|
||||||
|
border-radius: 18px;
|
||||||
|
object-fit: cover;
|
||||||
|
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-film-heading span {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
color: #9ed0ff;
|
||||||
|
font-size: 0.74rem;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-film-heading h2 {
|
||||||
|
margin: 0;
|
||||||
|
color: #f8fbff;
|
||||||
|
font-size: clamp(1.35rem, 2vw, 2.2rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-special-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-special-grid.compact-specials {
|
||||||
|
grid-template-columns: minmax(230px, 420px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-special-card {
|
||||||
|
border-color: rgba(0, 113, 227, 0.3);
|
||||||
|
background:
|
||||||
|
linear-gradient(160deg, rgba(0, 113, 227, 0.15), transparent 42%),
|
||||||
|
var(--card-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-special-card .snack-img {
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.11), transparent 34%),
|
||||||
|
#090d14;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-special-card .badge {
|
||||||
|
display: inline-flex;
|
||||||
|
width: max-content;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wide-special {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(130px, 42%) 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wide-special .snack-img {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wide-special .snack-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .limited-specials-hero {
|
||||||
|
border-color: rgba(31, 67, 110, 0.14);
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 12% 16%, rgba(0, 113, 227, 0.18), transparent 34%),
|
||||||
|
radial-gradient(circle at 84% 12%, rgba(255, 188, 104, 0.26), transparent 32%),
|
||||||
|
linear-gradient(135deg, #ffffff, #edf5ff);
|
||||||
|
box-shadow: 0 24px 60px rgba(35, 67, 108, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .limited-specials-hero h2 {
|
||||||
|
color: #0e1b31;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .limited-specials-hero p {
|
||||||
|
color: #314763;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .limited-kicker {
|
||||||
|
background: rgba(0, 113, 227, 0.1);
|
||||||
|
border-color: rgba(0, 113, 227, 0.28);
|
||||||
|
color: #0759aa;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .special-film-heading {
|
||||||
|
background: rgba(255, 255, 255, 0.86);
|
||||||
|
border-color: rgba(28, 56, 94, 0.14);
|
||||||
|
box-shadow: 0 14px 32px rgba(33, 67, 107, 0.09);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .special-film-heading span {
|
||||||
|
color: #0057ae;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .special-film-heading h2 {
|
||||||
|
color: #10213a;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .limited-special-card {
|
||||||
|
background:
|
||||||
|
linear-gradient(160deg, rgba(0, 113, 227, 0.08), transparent 42%),
|
||||||
|
#ffffff !important;
|
||||||
|
border-color: rgba(0, 113, 227, 0.16) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px) {
|
||||||
|
.wide-special {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wide-special .snack-img {
|
||||||
|
min-height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-film-heading {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
{
|
|
||||||
// Visit https://aka.ms/tsconfig to read more about this file
|
|
||||||
"compilerOptions": {
|
|
||||||
// File Layout
|
|
||||||
"rootDir": "./src",
|
|
||||||
"outDir": "./dist",
|
|
||||||
|
|
||||||
// Environment Settings
|
|
||||||
// See also https://aka.ms/tsconfig/module
|
|
||||||
"module": "ES2020",
|
|
||||||
"target": "ES2021",
|
|
||||||
"types": [],
|
|
||||||
// For nodejs:
|
|
||||||
// "lib": ["esnext"],
|
|
||||||
// "types": ["node"],
|
|
||||||
// and npm install -D @types/node
|
|
||||||
|
|
||||||
// Other Outputs
|
|
||||||
"sourceMap": true,
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
|
|
||||||
// Stricter Typechecking Options
|
|
||||||
"noUncheckedIndexedAccess": true,
|
|
||||||
"exactOptionalPropertyTypes": true,
|
|
||||||
|
|
||||||
// Style Options
|
|
||||||
// "noImplicitReturns": true,
|
|
||||||
// "noImplicitOverride": true,
|
|
||||||
// "noUnusedLocals": true,
|
|
||||||
// "noUnusedParameters": true,
|
|
||||||
// "noFallthroughCasesInSwitch": true,
|
|
||||||
// "noPropertyAccessFromIndexSignature": true,
|
|
||||||
|
|
||||||
// Recommended Options
|
|
||||||
"strict": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"verbatimModuleSyntax": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"noUncheckedSideEffectImports": true,
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
},
|
|
||||||
"include": ["src/*"]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user