Add auto-refresh polling to theater overlay
Introduces periodic polling to refresh seat and performance data in TheaterOverlayComponent using RxJS interval and Angular signals. Polling is paused when the component is destroyed or manually via new methods, and the template is updated to use the seatsPerRow signal.
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
}
|
||||
@else {
|
||||
<app-theater-layout [seatsPerRow]="seatsPerRow"></app-theater-layout>
|
||||
<app-theater-layout [seatsPerRow]="seatsPerRow()"></app-theater-layout>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import {Component, inject, OnInit} from '@angular/core';
|
||||
import {Component, DestroyRef, inject, OnDestroy, OnInit, signal} from '@angular/core';
|
||||
import {HttpService} from '../http.service';
|
||||
import {LoadingService} from '../loading.service';
|
||||
import {catchError, forkJoin, of, tap} from 'rxjs';
|
||||
import {catchError, filter, forkJoin, interval, of, startWith, switchMap, tap} from 'rxjs';
|
||||
import {Sitzkategorie, Sitzplatz, Vorstellung} from '@infinimotion/model-frontend';
|
||||
import {TheaterSeatState} from '../model/theater-seat-state.model';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {SelectedSeatsService} from '../selected-seats.service';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
|
||||
const POLLING_INTERVAL_MS = 5000;
|
||||
|
||||
@Component({
|
||||
selector: 'app-theater-overlay',
|
||||
@@ -13,42 +16,77 @@ import {SelectedSeatsService} from '../selected-seats.service';
|
||||
templateUrl: './theater-overlay.component.html',
|
||||
styleUrl: './theater-overlay.component.css'
|
||||
})
|
||||
export class TheaterOverlayComponent implements OnInit {
|
||||
export class TheaterOverlayComponent implements OnInit, OnDestroy {
|
||||
private http = inject(HttpService);
|
||||
loading = inject(LoadingService)
|
||||
private route = inject(ActivatedRoute);
|
||||
private destroyRef = inject(DestroyRef);
|
||||
private selectedSeatService = inject(SelectedSeatsService);
|
||||
|
||||
readonly loading = inject(LoadingService);
|
||||
|
||||
showId!: number;
|
||||
seatsPerRow: { seat: Sitzplatz, state: TheaterSeatState }[][] = []
|
||||
seatsPerRow = signal<{ seat: Sitzplatz, state: TheaterSeatState }[][]>([]);
|
||||
performance: Vorstellung | undefined;
|
||||
seatCategories: Sitzkategorie[] = [];
|
||||
|
||||
constructor(private route: ActivatedRoute, private selectedSeatService : SelectedSeatsService) {}
|
||||
private isPollingEnabled = signal(true);
|
||||
private isInitialLoad = signal(true);
|
||||
|
||||
ngOnInit() {
|
||||
this.showId = Number(this.route.snapshot.paramMap.get('id')!);
|
||||
this.selectedSeatService.clearSelection();
|
||||
this.selectedSeatService.setSeatSelectable(true);
|
||||
this.loadPerformanceAndSeats();
|
||||
|
||||
this.startAutoRefresh();
|
||||
}
|
||||
|
||||
loadPerformanceAndSeats() {
|
||||
this.loading.show();
|
||||
ngOnDestroy() {
|
||||
this.isPollingEnabled.set(false);
|
||||
}
|
||||
|
||||
forkJoin({
|
||||
private startAutoRefresh() {
|
||||
interval(POLLING_INTERVAL_MS).pipe(
|
||||
startWith(0),
|
||||
filter(() => this.isPollingEnabled()),
|
||||
filter(() => !this.selectedSeatService.committed()),
|
||||
switchMap(() => this.loadPerformanceAndSeats()),
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
).subscribe();
|
||||
}
|
||||
|
||||
private loadPerformanceAndSeats() {
|
||||
if (this.isInitialLoad()) {
|
||||
this.loading.show();
|
||||
}
|
||||
|
||||
return forkJoin({
|
||||
performance: this.http.getPerformaceById(this.showId),
|
||||
seats: this.http.getSeatsByShowId(this.showId)
|
||||
}).pipe(
|
||||
tap(({ performance, seats }) => {
|
||||
this.performance = performance;
|
||||
this.seatsPerRow = this.converter(seats);
|
||||
this.seatsPerRow.set(this.converter(seats));
|
||||
|
||||
if (this.isInitialLoad()) {
|
||||
this.loading.hide();
|
||||
this.isInitialLoad.set(false);
|
||||
}
|
||||
}),
|
||||
catchError(err => {
|
||||
if (this.isInitialLoad()) {
|
||||
this.loading.showError(err);
|
||||
console.error('Fehler beim Laden', err);
|
||||
return of({ performance: null, seats: [] });
|
||||
} else {
|
||||
console.warn('Fehler beim Aktualisieren der Sitze:', err);
|
||||
}
|
||||
|
||||
if (this.isInitialLoad()) {
|
||||
this.loading.hide();
|
||||
this.isInitialLoad.set(false);
|
||||
}
|
||||
|
||||
return of({ performance: null, seats: { seats: [], reserved: [], booked: [] } });
|
||||
})
|
||||
).subscribe();
|
||||
);
|
||||
}
|
||||
|
||||
converter(resp: { seats: Sitzplatz[], reserved: Sitzplatz[], booked: Sitzplatz[] }): {
|
||||
@@ -80,6 +118,18 @@ loadPerformanceAndSeats() {
|
||||
rows.forEach(row => row.sort((a, b) => a.seat.position - b.seat.position));
|
||||
return rows;
|
||||
}
|
||||
|
||||
refreshSeats(): void {
|
||||
this.loadPerformanceAndSeats().subscribe();
|
||||
}
|
||||
|
||||
pausePolling(): void { //TODO: Ab Stepper Schritt 2 Polling pausieren
|
||||
this.isPollingEnabled.set(false);
|
||||
}
|
||||
|
||||
resumePolling(): void {
|
||||
this.isPollingEnabled.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user