diff --git a/src/app/http.service.ts b/src/app/http.service.ts index fb35901..bdc03ae 100644 --- a/src/app/http.service.ts +++ b/src/app/http.service.ts @@ -1,4 +1,4 @@ -import { Kinosaal } from '@infinimotion/model-frontend'; +import { Kinosaal, Vorstellung } from '@infinimotion/model-frontend'; import { HttpClient } from "@angular/common/http"; import { inject, Injectable } from "@angular/core"; import { Observable } from "rxjs"; @@ -6,7 +6,10 @@ import { Observable } from "rxjs"; @Injectable({providedIn: 'root'}) export class HttpService { private http = inject(HttpClient); - private baseUrl = 'https://infinimotion.de/api/'; + private baseUrl = '/api/'; + + + /* Kinosaal APIs */ /* GET /api/kinosaal */ getAllKinosaal(): Observable { @@ -32,4 +35,32 @@ export class HttpService { deleteKinosaal(id: number): Observable { return this.http.delete(`${this.baseUrl}kinosaal/${id}`); } + + + /* Vorstellung APIs */ + + /* GET /api/vorstellung */ + getPerformaces(): Observable { + return this.http.get(`${this.baseUrl}vorstellung`); + } + + /* GET /api/vorstellung/{id} */ + getPerformaceById(id: number): Observable { + return this.http.get(`${this.baseUrl}vorstellung/${id}`); + } + + /* POST /api/vorstellung */ + addPerformace(vorstellung: Omit): Observable { + return this.http.post(`${this.baseUrl}vorstellung`, vorstellung); + } + + /* PUT /api/vorstellung/{id} */ + updatePerformace(id: number, vorstellung: Partial): Observable { + return this.http.put(`${this.baseUrl}vorstellung/${id}`, vorstellung); + } + + /* DELETE /api/vorstellung/{id} */ + deletePerformace(id: number): Observable { + return this.http.delete(`${this.baseUrl}vorstellung/${id}`); + } } diff --git a/src/app/model/movie-group.model.ts b/src/app/model/movie-group.model.ts new file mode 100644 index 0000000..5e39fe5 --- /dev/null +++ b/src/app/model/movie-group.model.ts @@ -0,0 +1,7 @@ +import { Film } from '@infinimotion/model-frontend'; +import { Performance } from './performance.model'; + +export interface MovieGroup { + movie: Film; + performances: Performance[]; +} diff --git a/src/app/model/performance.model.ts b/src/app/model/performance.model.ts new file mode 100644 index 0000000..f9b29d3 --- /dev/null +++ b/src/app/model/performance.model.ts @@ -0,0 +1,6 @@ +export class Performance { + id!: number; + hall!: string; + start!: Date; + utilisation?: number; +} diff --git a/src/app/movie-category/movie-category.component.html b/src/app/movie-category/movie-category.component.html index 16df8eb..72757f5 100644 --- a/src/app/movie-category/movie-category.component.html +++ b/src/app/movie-category/movie-category.component.html @@ -1,3 +1,3 @@ - {{ getCategoryText() }} + {{ category() }} diff --git a/src/app/movie-category/movie-category.component.ts b/src/app/movie-category/movie-category.component.ts index 4b07e4a..888b365 100644 --- a/src/app/movie-category/movie-category.component.ts +++ b/src/app/movie-category/movie-category.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Component, input } from '@angular/core'; @Component({ selector: 'app-movie-category', @@ -7,9 +7,5 @@ import { Component, Input } from '@angular/core'; styleUrl: './movie-category.component.css' }) export class MovieCategoryComponent { - @Input() category: string = '-'; - - getCategoryText(): string { - return this.category; - } + category = input('-'); } diff --git a/src/app/movie-duration/movie-duration.component.html b/src/app/movie-duration/movie-duration.component.html index e41a4eb..73845a3 100644 --- a/src/app/movie-duration/movie-duration.component.html +++ b/src/app/movie-duration/movie-duration.component.html @@ -1,4 +1,4 @@ - {{ getDurationText() }} + {{ durationText() }} diff --git a/src/app/movie-duration/movie-duration.component.ts b/src/app/movie-duration/movie-duration.component.ts index e6a389f..4349449 100644 --- a/src/app/movie-duration/movie-duration.component.ts +++ b/src/app/movie-duration/movie-duration.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Component, input, computed } from '@angular/core'; @Component({ selector: 'app-movie-duration', @@ -7,9 +7,7 @@ import { Component, Input } from '@angular/core'; styleUrl: './movie-duration.component.css' }) export class MovieDurationComponent { - @Input() duration: number = 0; + duration = input(0); - getDurationText(): string { - return `${this.duration} Min.`; - } + durationText = computed(() => `${this.duration()} Min.`); } diff --git a/src/app/movie-performance/movie-performance.component.html b/src/app/movie-performance/movie-performance.component.html index 82dcac3..033cbae 100644 --- a/src/app/movie-performance/movie-performance.component.html +++ b/src/app/movie-performance/movie-performance.component.html @@ -1,14 +1,14 @@
-

Kino 1

+

{{ hall() }}

- 15:30 + {{ startTime() }}

-
+

Tickets

diff --git a/src/app/movie-performance/movie-performance.component.ts b/src/app/movie-performance/movie-performance.component.ts index 296204f..ff7ba26 100644 --- a/src/app/movie-performance/movie-performance.component.ts +++ b/src/app/movie-performance/movie-performance.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, input, computed } from '@angular/core'; @Component({ selector: 'app-movie-performance', @@ -7,5 +7,40 @@ import { Component } from '@angular/core'; styleUrl: './movie-performance.component.css' }) export class MoviePerformanceComponent { + id = input.required(); + hall = input.required(); + start = input.required(); + utilisation = input(); + + startTime = computed(() => + this.start().toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ); + + utilisationBackground = computed(() => { + const u = this.utilisation() ?? -1; + + const color_map = new Map([ + [100, '#da1414'], + [75, '#e76800'], + [50, '#efbe12'], + [25, '#8bbb00'], + [0, '#10a20b'] + ]); + + for (const [threshold, color] of color_map) { + if (u >= threshold) { + return color; + } + } + + return '#424242'; + }); + + fullStyle = computed(() => { + if (this.utilisation() === 100) { + return 'line-through'; + } + return ''; + }); } diff --git a/src/app/movie-poster/movie-poster.component.html b/src/app/movie-poster/movie-poster.component.html index 494579e..f7e3ea2 100644 --- a/src/app/movie-poster/movie-poster.component.html +++ b/src/app/movie-poster/movie-poster.component.html @@ -1,8 +1,8 @@
- Movie Poster + Movie Poster
- - - + + +
diff --git a/src/app/movie-poster/movie-poster.component.ts b/src/app/movie-poster/movie-poster.component.ts index 3e23ff5..33b1ccf 100644 --- a/src/app/movie-poster/movie-poster.component.ts +++ b/src/app/movie-poster/movie-poster.component.ts @@ -1,4 +1,5 @@ -import { Component } from '@angular/core'; +import { Component, input } from '@angular/core'; +import { Film } from '@infinimotion/model-frontend'; @Component({ selector: 'app-movie-poster', @@ -7,5 +8,5 @@ import { Component } from '@angular/core'; styleUrl: './movie-poster.component.css' }) export class MoviePosterComponent { - + movie = input.required(); } diff --git a/src/app/movie-rating/movie-rating.component.html b/src/app/movie-rating/movie-rating.component.html index fd273c8..a8e4c76 100644 --- a/src/app/movie-rating/movie-rating.component.html +++ b/src/app/movie-rating/movie-rating.component.html @@ -1,3 +1,3 @@ - - {{ getRatingText() }} + + {{ ratingText() }} diff --git a/src/app/movie-rating/movie-rating.component.ts b/src/app/movie-rating/movie-rating.component.ts index 1e87bc1..0643e68 100644 --- a/src/app/movie-rating/movie-rating.component.ts +++ b/src/app/movie-rating/movie-rating.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Component, input, computed } from '@angular/core'; @Component({ selector: 'app-movie-rating', @@ -7,23 +7,16 @@ import { Component, Input } from '@angular/core'; styleUrl: './movie-rating.component.css' }) export class MovieRatingComponent { - @Input() rating: number = 0; + rating = input(0); - getRatingColor(): string { - if (this.rating >= 18) { - return 'bg-red-500'; - } else if (this.rating >= 16) { - return 'bg-blue-500'; - } else if (this.rating >= 12) { - return 'bg-green-500'; - } else if (this.rating >= 6) { - return 'bg-yellow-300'; - } else { - return 'bg-white'; - } - } + ratingColor = computed(() => { + const r = this.rating(); + if (r >= 18) return 'bg-red-500'; + if (r >= 16) return 'bg-blue-500'; + if (r >= 12) return 'bg-green-500'; + if (r >= 6) return 'bg-yellow-300'; + return 'bg-white'; + }); - getRatingText(): string { - return `FSK ${this.rating}`; - } + ratingText = computed(() => `FSK ${this.rating()}`); } diff --git a/src/app/movie-schedule-info/movie-schedule-info.component.html b/src/app/movie-schedule-info/movie-schedule-info.component.html index d8ac521..fd18684 100644 --- a/src/app/movie-schedule-info/movie-schedule-info.component.html +++ b/src/app/movie-schedule-info/movie-schedule-info.component.html @@ -1,13 +1,13 @@ -
- +
+
-

Avengers: Endgame

-

- Long Movie description Long Movie description Long Movie description Long Movie description Long Movie description Long Movie descriptionLong Movie description Long Movie description Long Movie description +

{{ movie.title }}

+

+ {{ movie.description }}

- +
diff --git a/src/app/movie-schedule-info/movie-schedule-info.component.ts b/src/app/movie-schedule-info/movie-schedule-info.component.ts index 79b208b..71804a9 100644 --- a/src/app/movie-schedule-info/movie-schedule-info.component.ts +++ b/src/app/movie-schedule-info/movie-schedule-info.component.ts @@ -1,4 +1,5 @@ -import { Component } from '@angular/core'; +import { Component, input } from '@angular/core'; +import { MovieGroup } from '../model/movie-group.model'; @Component({ selector: 'app-movie-schedule-info', @@ -7,5 +8,13 @@ import { Component } from '@angular/core'; styleUrl: './movie-schedule-info.component.css' }) export class MovieScheduleInfoComponent { + readonly movieGroup = input.required(); + get movie() { + return this.movieGroup().movie; + } + + get performances() { + return this.movieGroup().performances; + } } diff --git a/src/app/movie-schedule-times/movie-schedule-times.component.html b/src/app/movie-schedule-times/movie-schedule-times.component.html index b46a6bb..b7b9720 100644 --- a/src/app/movie-schedule-times/movie-schedule-times.component.html +++ b/src/app/movie-schedule-times/movie-schedule-times.component.html @@ -1,5 +1,10 @@
- - - + @for (perf of performances(); track $index) { + + + }
diff --git a/src/app/movie-schedule-times/movie-schedule-times.component.ts b/src/app/movie-schedule-times/movie-schedule-times.component.ts index f15fb30..700eba1 100644 --- a/src/app/movie-schedule-times/movie-schedule-times.component.ts +++ b/src/app/movie-schedule-times/movie-schedule-times.component.ts @@ -1,4 +1,5 @@ -import { Component } from '@angular/core'; +import { Performance } from './../model/performance.model'; +import { Component, input } from '@angular/core'; @Component({ selector: 'app-movie-schedule-times', @@ -7,5 +8,5 @@ import { Component } from '@angular/core'; styleUrl: './movie-schedule-times.component.css' }) export class MovieScheduleTimesComponent { - + performances = input.required(); } diff --git a/src/app/schedule/schedule.component.html b/src/app/schedule/schedule.component.html index 0dfee55..cfcd93a 100644 --- a/src/app/schedule/schedule.component.html +++ b/src/app/schedule/schedule.component.html @@ -1,12 +1,12 @@ - @for (dateInfo of dates; track dateInfo.date; let i = $index) { + @for (dateInfo of dates; track dateInfo.date; let i = $index) { - @if (getMovieCount(i)> 0) { - @for (movie of [].constructor(getMovieCount(i)); track movie) { - + @if (getMovieCount(i) > 0) { + @for (group of dateInfo.performances; track group.movie.id) { + } } @else { - + } } diff --git a/src/app/schedule/schedule.component.ts b/src/app/schedule/schedule.component.ts index a69c67a..ec6b934 100644 --- a/src/app/schedule/schedule.component.ts +++ b/src/app/schedule/schedule.component.ts @@ -1,4 +1,8 @@ -import { Component } from '@angular/core'; +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'; @Component({ selector: 'app-schedule', @@ -6,16 +10,23 @@ import { Component } from '@angular/core'; templateUrl: './schedule.component.html', styleUrl: './schedule.component.css' }) -export class ScheduleComponent { -dates: { label: string; date: Date }[] = []; +export class ScheduleComponent implements OnInit { + dates: { label: string; date: Date; performances: MovieGroup[] }[] = []; + performaces: Vorstellung[] = []; + + private http = inject(HttpService); constructor() { this.generateDates(); } + ngOnInit() { + this.loadPerformances(); + } + generateDates() { const today = new Date(); - for (let i = 0; i < 31; i++) { + for (let i = 0; i < 14; i++) { const date = new Date(today); date.setDate(today.getDate() + i); @@ -28,12 +39,63 @@ dates: { label: string; date: Date }[] = []; label = date.toLocaleDateString('de-DE', { weekday: 'short' }) + '. ' + date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit'}); } - this.dates.push({ label, date }); + this.dates.push({ label, date, performances: []}); + } + } + + loadPerformances() { + this.http.getPerformaces().subscribe({ + next: (data) => { + this.performaces = Array.isArray(data) ? data : [data]; + this.assignPerformancesToDates(); + }, + error: (err) => console.error('Fehler beim Laden der Performances', err), + }); + } + + 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(); + + 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 { - // Hier kannst du später die echten Filmzahlen zurückgeben - return index === 0 ? 10 : index === 1 ? 0 : 4; + return this.dates[index].performances.length; } }