master #9

Closed
Jannis wants to merge 22 commits from Jannis/Kino-Website-Framework:master into master
3 changed files with 173 additions and 67 deletions
Showing only changes of commit f7fc6e4387 - Show all commits

View File

@@ -1,5 +1,45 @@
--- ---
import { movieCatalog, timePatterns, hallRotation, weekdayShort } from "../scripts/bigConstants"; import {
timePatterns,
hallRotation,
weekdayShort,
type MovieInterface,
type ITMDBResponse,
} from "../scripts/bigConstants";
async function getTopMovies(): Promise<MovieInterface[]> {
const API_KEY = import.meta.env.TMDB_API_KEY;
console.log("Fetching with Key:", API_KEY ? "Key found" : "KEY MISSING!");
const IMAGE_BASE_URL = "https://image.tmdb.org/t/p/w500";
// 1. Corrected "discover" spelling
const response = await fetch(
`https://api.themoviedb.org/3/discover/movie?api_key=${API_KEY}&language=de-DE&sort_by=popularity.desc`,
);
console.log("Response Status:", response.status);
const data: ITMDBResponse = await response.json();
console.log("Results found:", data.results?.length);
if (!data.results) return [];
return data.results?.map((movie) => ({
id: movie.id,
title: movie.title || "Unknown Title",
poster: movie.poster_path
? `${IMAGE_BASE_URL}${movie.poster_path}`
: "/placeholder.jpg",
rating: movie.vote_average || 0,
// Add optional chaining (?.) and a fallback
year: movie.release_date?.split("-")[0] || "N/A",
genre: "Movie", // Discover doesn't provide the name, only an ID
duration: 120, // Discover doesn't provide duration
fsk: "12",
description: movie.overview || "No description available.",
backdrop: movie.backdrop_path,
}));
}
const formatDateShort = (dateObj: Date) => { const formatDateShort = (dateObj: Date) => {
const day = String(dateObj.getDate()).padStart(2, "0"); const day = String(dateObj.getDate()).padStart(2, "0");
@@ -15,20 +55,44 @@ const buildDayMeta = (offset: number) => {
const weekday = weekdayShort[date.getDay()]; const weekday = weekdayShort[date.getDay()];
const formattedDate = formatDateShort(date); const formattedDate = formatDateShort(date);
if (offset === 0) return { offset, date, short: "Heute", long: `Heute, ${formattedDate}` }; if (offset === 0)
if (offset === 1) return { offset, date, short: "Morgen", long: `Morgen, ${formattedDate}` }; return {
return { offset, date, short: weekday, long: `${weekday}, ${formattedDate}` }; offset,
date,
short: "Heute",
long: `Heute, ${formattedDate}`,
};
if (offset === 1)
return {
offset,
date,
short: "Morgen",
long: `Morgen, ${formattedDate}`,
};
return {
offset,
date,
short: weekday,
long: `${weekday}, ${formattedDate}`,
};
}; };
const buildScheduleForMovie = (movieIndex: number) => { const buildScheduleForMovie = (movieIndex: number) => {
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]; 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);
const showings = pattern.slice(0, showCount).map((time: string, slotIndex: number) => { const showings = pattern
const hall = hallRotation[(movieIndex + dayOffset + slotIndex) % hallRotation.length]; .slice(0, showCount)
.map((time: string, slotIndex: number) => {
const hall =
hallRotation[
(movieIndex + dayOffset + slotIndex) %
hallRotation.length
];
return { time, hall }; return { time, hall };
}); });
@@ -36,57 +100,97 @@ const buildScheduleForMovie = (movieIndex: number) => {
}); });
}; };
const movieProgram = movieCatalog.map((movie, movieIndex) => ({ let movieCatalog = await getTopMovies();
const movieProgram = movieCatalog?.map((movie, movieIndex) => ({
...movie, ...movie,
schedule: buildScheduleForMovie(movieIndex) schedule: buildScheduleForMovie(movieIndex),
})); }));
--- ---
<section id="movie-list-view"> <section id="movie-list-view">
<div class="container movie-list-shell"> <div class="container movie-list-shell">
<h1 class="list-title">Aktuelle Filme & Spielzeiten</h1> <h1 class="list-title">Aktuelle Filme & Spielzeiten</h1>
<p class="list-subtitle">Alle Filme mit 7 Tagen Spielplan. Erste Vorstellung täglich ab 13:00 Uhr.</p> <p class="list-subtitle">
Alle Filme mit 7 Tagen Spielplan. Erste Vorstellung täglich ab 13:00
Uhr.
</p>
<div id="movie-program-list" class="movie-program-list"> <div id="movie-program-list" class="movie-program-list">
{movieProgram.map((movie, programIndex) => ( {
<article class="detailed-card program-card reveal-on-scroll" data-program-index={programIndex}> movieProgram?.map((movie, programIndex) => (
<article
class="detailed-card program-card"
data-program-index={programIndex}
data-schedule={JSON.stringify(movie.schedule)}
>
<div class="card-left"> <div class="card-left">
<img src={movie.poster} alt={movie.title} /> <img src={movie.poster} alt={movie.title} />
<span class={`fsk fsk-${movie.fsk}`}>{movie.fsk}</span> <span class={`fsk fsk-${movie.fsk}`}>
{movie.fsk}
</span>
</div> </div>
<div class="card-right"> <div class="card-right">
<div class="card-header"> <div class="card-header">
<h2>{movie.title}</h2> <h2>{movie.title}</h2>
<span class="duration">{movie.duration} Min. | {movie.genre} | FSK: {movie.fsk}</span> <span class="duration">
{movie.duration} Min. | {movie.genre} | FSK:{" "}
{movie.fsk}
</span>
</div> </div>
<p class="description">{movie.description}</p> <p class="description">{movie.description}</p>
<div class="program-day-tabs"> <div class="program-day-tabs">
{movie.schedule.map((day, dayIndex) => ( {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>{day.short}</span> <span>{day.short}</span>
<small>{formatDateShort(day.date)}</small> <small>
{formatDateShort(day.date)}
</small>
</button> </button>
))} ))}
</div> </div>
<div class="schedule-container program-schedule-shell"> <div class="schedule-container program-schedule-shell">
<div class="schedule-header"> <div class="schedule-header">
<span>Tag</span><span>Kinosaal</span><span>Uhrzeit</span> <span>Tag</span>
<span>Kinosaal</span>
<span>Uhrzeit</span>
</div> </div>
<div id={`schedule-body-${programIndex}`} class="program-schedule-body"> <div
{movie.schedule[0].showings.map((showing) => ( id={`schedule-body-${programIndex}`}
<button class="schedule-row time-chip program-time-row" data-movie={movie.title} data-hall={showing.hall} data-time={showing.time}> class="program-schedule-body"
<span>{movie.schedule[0].long}</span> >
<span class="hall-pill">{showing.hall}</span> {movie.schedule[0].showings.map(
<span class="time-btn">{showing.time}</span> (showing) => (
<button
class="schedule-row time-chip program-time-row"
data-movie={movie.title}
data-hall={showing.hall}
data-time={showing.time}
>
<span>
{movie.schedule[0].long}
</span>
<span class="hall-pill">
{showing.hall}
</span>
<span class="time-btn">
{showing.time}
</span>
</button> </button>
))} ),
)}
</div> </div>
</div> </div>
</div> </div>
</article> </article>
))} ))
}
</div> </div>
</div> </div>
</section> </section>
@@ -97,19 +201,27 @@ const movieProgram = movieCatalog.map((movie, movieIndex) => ({
movieProgramList?.addEventListener("click", (event: any) => { movieProgramList?.addEventListener("click", (event: any) => {
const dayButton = event.target.closest(".program-day-tab"); const dayButton = event.target.closest(".program-day-tab");
if (dayButton) { if (dayButton) {
const tabs = dayButton.closest(".program-day-tabs"); const programIndex = dayButton.getAttribute("data-program-index");
tabs?.querySelectorAll(".program-day-tab").forEach((t: any) => t.classList.remove("active")); const dayIndex = parseInt(dayButton.getAttribute("data-day-index"));
dayButton.classList.add("active"); const card = dayButton.closest(".detailed-card");
} const scheduleData = JSON.parse(card.getAttribute("data-schedule"));
const selectedDay = scheduleData[dayIndex];
const chip = event.target.closest(".time-chip"); // Update the schedule body HTML
if (chip) { const body:any = document.getElementById(
const movie = chip.getAttribute("data-movie"); `schedule-body-${programIndex}`,
const hall = chip.getAttribute("data-hall"); );
const time = chip.getAttribute("data-time"); body.innerHTML = selectedDay.showings
if (movie && hall && time && (window as any).openBooking) { .map(
(window as any).openBooking(movie, hall, time); (showing:any) => `
} <button class="schedule-row time-chip" data-movie="${card.querySelector("h2").innerText}" data-hall="${showing.hall}" data-time="${showing.time}">
<span>${selectedDay.long}</span>
<span class="hall-pill">${showing.hall}</span>
<span class="time-btn">${showing.time}</span>
</button>
`,
)
.join("");
} }
}); });
@@ -117,7 +229,9 @@ const movieProgram = movieCatalog.map((movie, movieIndex) => ({
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const focusIndex = params.get("focus"); const focusIndex = params.get("focus");
if (focusIndex !== null) { if (focusIndex !== null) {
const target = document.querySelector(`[data-program-index="${focusIndex}"]`); const target = document.querySelector(
`[data-program-index="${focusIndex}"]`,
);
if (target) { if (target) {
target.scrollIntoView({ behavior: "smooth", block: "start" }); target.scrollIntoView({ behavior: "smooth", block: "start" });
target.classList.add("flash-focus"); target.classList.add("flash-focus");

View File

@@ -1,8 +0,0 @@
export default function topbar() {
return (
<div className="navbar bg-[rgba(29, 29, 31, 0.75)]">
<div className="leftButtonArray">Hallo</div>
<div className="rightButtonArray"></div>
</div>
)
}

View File

@@ -74,7 +74,7 @@ export interface User {
paymentMethods: any[]; paymentMethods: any[];
} }
export interface MovieCatalog { export interface MovieInterface {
id: number; id: number;
title: string; title: string;
genre: string; genre: string;