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.
139 lines
4.2 KiB
TypeScript
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;
|
|
}
|
|
}
|