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>
|
</div>
|
||||||
}
|
}
|
||||||
@else {
|
@else {
|
||||||
<app-theater-layout [seatsPerRow]="seatsPerRow"></app-theater-layout>
|
<app-theater-layout [seatsPerRow]="seatsPerRow()"></app-theater-layout>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</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 {HttpService} from '../http.service';
|
||||||
import {LoadingService} from '../loading.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 {Sitzkategorie, Sitzplatz, Vorstellung} from '@infinimotion/model-frontend';
|
||||||
import {TheaterSeatState} from '../model/theater-seat-state.model';
|
import {TheaterSeatState} from '../model/theater-seat-state.model';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
import {SelectedSeatsService} from '../selected-seats.service';
|
import {SelectedSeatsService} from '../selected-seats.service';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
|
const POLLING_INTERVAL_MS = 5000;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-theater-overlay',
|
selector: 'app-theater-overlay',
|
||||||
@@ -13,43 +16,78 @@ import {SelectedSeatsService} from '../selected-seats.service';
|
|||||||
templateUrl: './theater-overlay.component.html',
|
templateUrl: './theater-overlay.component.html',
|
||||||
styleUrl: './theater-overlay.component.css'
|
styleUrl: './theater-overlay.component.css'
|
||||||
})
|
})
|
||||||
export class TheaterOverlayComponent implements OnInit {
|
export class TheaterOverlayComponent implements OnInit, OnDestroy {
|
||||||
private http = inject(HttpService);
|
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;
|
showId!: number;
|
||||||
seatsPerRow: { seat: Sitzplatz, state: TheaterSeatState }[][] = []
|
seatsPerRow = signal<{ seat: Sitzplatz, state: TheaterSeatState }[][]>([]);
|
||||||
performance: Vorstellung | undefined;
|
performance: Vorstellung | undefined;
|
||||||
seatCategories: Sitzkategorie[] = [];
|
seatCategories: Sitzkategorie[] = [];
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private selectedSeatService : SelectedSeatsService) {}
|
private isPollingEnabled = signal(true);
|
||||||
|
private isInitialLoad = signal(true);
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.showId = Number(this.route.snapshot.paramMap.get('id')!);
|
this.showId = Number(this.route.snapshot.paramMap.get('id')!);
|
||||||
this.selectedSeatService.clearSelection();
|
this.selectedSeatService.clearSelection();
|
||||||
this.selectedSeatService.setSeatSelectable(true);
|
this.selectedSeatService.setSeatSelectable(true);
|
||||||
this.loadPerformanceAndSeats();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadPerformanceAndSeats() {
|
this.startAutoRefresh();
|
||||||
this.loading.show();
|
}
|
||||||
|
|
||||||
forkJoin({
|
ngOnDestroy() {
|
||||||
performance: this.http.getPerformaceById(this.showId),
|
this.isPollingEnabled.set(false);
|
||||||
seats: this.http.getSeatsByShowId(this.showId)
|
}
|
||||||
}).pipe(
|
|
||||||
tap(({ performance, seats }) => {
|
private startAutoRefresh() {
|
||||||
this.performance = performance;
|
interval(POLLING_INTERVAL_MS).pipe(
|
||||||
this.seatsPerRow = this.converter(seats);
|
startWith(0),
|
||||||
this.loading.hide();
|
filter(() => this.isPollingEnabled()),
|
||||||
}),
|
filter(() => !this.selectedSeatService.committed()),
|
||||||
catchError(err => {
|
switchMap(() => this.loadPerformanceAndSeats()),
|
||||||
this.loading.showError(err);
|
takeUntilDestroyed(this.destroyRef)
|
||||||
console.error('Fehler beim Laden', err);
|
).subscribe();
|
||||||
return of({ performance: null, seats: [] });
|
}
|
||||||
})
|
|
||||||
).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.set(this.converter(seats));
|
||||||
|
|
||||||
|
if (this.isInitialLoad()) {
|
||||||
|
this.loading.hide();
|
||||||
|
this.isInitialLoad.set(false);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError(err => {
|
||||||
|
if (this.isInitialLoad()) {
|
||||||
|
this.loading.showError(err);
|
||||||
|
} 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: [] } });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
converter(resp: { seats: Sitzplatz[], reserved: Sitzplatz[], booked: Sitzplatz[] }): {
|
converter(resp: { seats: Sitzplatz[], reserved: Sitzplatz[], booked: Sitzplatz[] }): {
|
||||||
seat: Sitzplatz,
|
seat: Sitzplatz,
|
||||||
@@ -80,6 +118,18 @@ loadPerformanceAndSeats() {
|
|||||||
rows.forEach(row => row.sort((a, b) => a.seat.position - b.seat.position));
|
rows.forEach(row => row.sort((a, b) => a.seat.position - b.seat.position));
|
||||||
return rows;
|
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