Files
frontend/src/app/schedule/schedule.component.ts
Piet Ostendorp 4f5a8e9661 Add IMDb movie importer feature and unify header
Introduces a new movie importer feature allowing admins to search and import movies from IMDb, including new components for search, result display, and error handling. Replaces the schedule header with a reusable menu header component. Updates routing, navigation, and HTTP service to support the new importer. Adds a poster placeholder image and improves poster error handling.
2025-11-07 01:57:42 +01:00

139 lines
4.2 KiB
TypeScript

import { Component, inject, OnInit } from '@angular/core';
import { HttpService } from '../http.service';
import { Vorstellung } from '@infinimotion/model-frontend';
import { Performance } from '../model/performance.model';
import { MovieGroup } from '../model/movie-group.model';
import { LoadingService } from '../loading.service';
import { catchError, of, tap } from 'rxjs';
@Component({
selector: 'app-schedule',
standalone: false,
templateUrl: './schedule.component.html',
styleUrl: './schedule.component.css'
})
export class ScheduleComponent implements OnInit {
dates: { label: string; date: Date; performances: MovieGroup[] }[] = [];
performaces: Vorstellung[] = [];
movieSearchResult: string = '';
private readonly bookableDays: number = 14;
private http = inject(HttpService);
private loading = inject(LoadingService)
constructor() {
this.generateDates(this.bookableDays);
}
ngOnInit() {
this.loadPerformances(this.bookableDays);
}
hasSearchResults(dateIndex: number): boolean {
if (!this.movieSearchResult) return true;
return this.dates[dateIndex].performances.some(group =>
group.movie.title.toLowerCase().includes(this.movieSearchResult.toLowerCase())
);
}
generateDates(bookableDays: number) {
const today = new Date();
for (let i = 0; i < bookableDays; i++) {
const date = new Date(today);
date.setDate(today.getDate() + i);
let label = '';
if (i === 0) {
label = 'Heute';
} else if (i === 1) {
label = 'Morgen';
} else {
label = date.toLocaleDateString('de-DE', { weekday: 'short' }) + '. ' + date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit'});
}
this.dates.push({ label, date, performances: []});
}
}
loadPerformances(bookableDays: number) {
this.loading.show();
const filter = this.generateDateFilter(bookableDays);
this.http.getPerformacesByFilter(filter).pipe(
tap(performaces => {
this.performaces = performaces;
this.assignPerformancesToDates();
this.loading.hide();
}),
catchError(err => {
this.loading.showError(err);
console.error('Fehler beim Laden der Vorstellungen', err);
return of([]);
})
).subscribe();
}
private generateDateFilter(bookableDays: number): string[] {
const startDate = new Date();
const endDate = new Date();
endDate.setDate(startDate.getDate() + bookableDays - 1);
const startStr = startDate.toISOString().split('T')[0] + 'T00:00:00';
const endStr = endDate.toISOString().split('T')[0] + 'T23:59:59';
return [
`ge;start;date;${startStr}`,
`le;start;date;${endStr}`,
];
}
assignPerformancesToDates() {
// Gruppieren nach Datum
const groupedByDate: { [key: string]: Vorstellung[] } = {};
for (const vorstellung of this.performaces) {
const dateKey = new Date(vorstellung.start).toDateString();
if (!groupedByDate[dateKey]) {
groupedByDate[dateKey] = [];
}
groupedByDate[dateKey].push(vorstellung);
}
// Gruppieren nach Film
for (const dateInfo of this.dates) {
const dateKey = dateInfo.date.toDateString();
const dailyPerformances: Vorstellung[] = groupedByDate[dateKey] || [];
const movieMap = new Map<number, { movie: typeof dailyPerformances[0]['movie']; performances: Performance[] }>();
for (const perf of dailyPerformances) {
const movieId = perf.movie.id;
if (!movieMap.has(movieId)) {
movieMap.set(movieId, { movie: perf.movie, performances: [] });
}
const performance: Performance = {
id: perf.id,
hall: perf.hall.name,
start: new Date(perf.start),
// utilisation: 0 // TODO: perf.utilisation einrichten
};
movieMap.get(movieId)!.performances.push(performance);
}
// MovieGroups erstellen
dateInfo.performances = Array.from(movieMap.values()).map((entry) => ({
movie: entry.movie,
performances: entry.performances.sort((a, b) => a.start.getTime() - b.start.getTime()),
})) as MovieGroup[];
}
}
getMovieCount(index: number): number {
return this.dates[index].performances.length;
}
}