Files
frontend/src/app/selected-seats.service.ts
Piet Ostendorp ade5479a74 Add functionality to cancel tickets
Introduces a cancel order confirmation dialog and integrates it into the order flow. Refactors error and success components to support singular/plural seat messaging and retry actions. Updates navigation and button behaviors for better user experience. Fixes minor UI and logic issues in reservation, purchase, and conversion flows.
2025-11-21 15:53:42 +01:00

89 lines
2.6 KiB
TypeScript

import { computed, Injectable, signal } from '@angular/core';
import { Sitzplatz } from '@infinimotion/model-frontend';
@Injectable({
providedIn: 'root',
})
export class SelectedSeatsService {
private selectedSeatsSignal = signal<Sitzplatz[]>([]);
private seatIsSelectableSignal = signal(true);
private committedSignal = signal(false);
private erroredSignal = signal(false);
private cancelledSignal = signal(false);
private debugSignal = signal(false);
private hadConflictSignal = signal(false);
readonly selectedSeats = this.selectedSeatsSignal.asReadonly();
readonly seatIsSelectable = this.seatIsSelectableSignal.asReadonly();
readonly committed = this.committedSignal.asReadonly();
readonly errored = this.erroredSignal.asReadonly();
readonly cancelled = this.cancelledSignal.asReadonly();
readonly debug = this.debugSignal.asReadonly();
readonly hadConflict = this.hadConflictSignal.asReadonly();
readonly totalSeats = computed(() => this.selectedSeats().length);
readonly totalPrice = computed(() => this.selectedSeats().reduce((sum, seat) => sum + seat.row.category.price, 0));
pushSelectedSeat(selectedSeat: Sitzplatz): void {
this.selectedSeatsSignal.update(seats => [...seats, selectedSeat]);
this.hadConflictSignal.set(false);
}
removeSelectedSeat(selectedSeat: Sitzplatz): void {
this.selectedSeatsSignal.update(seats => seats.filter(seat => seat.id !== selectedSeat.id));
this.hadConflictSignal.set(false);
}
getSeatsByCategory(categoryId: number): Sitzplatz[] {
return this.selectedSeats().filter(seat => seat.row.category.id === categoryId);
}
clearSelection(): void {
this.selectedSeatsSignal.set([]);
this.committedSignal.set(false);
this.cancelledSignal.set(false);
this.erroredSignal.set(false);
this.hadConflictSignal.set(false);
}
getSeatIsSelectable(): boolean{
return this.seatIsSelectable();
}
setSeatSelectable(selectable: boolean): void {
this.seatIsSelectableSignal.set(selectable);
if (selectable) {
this.committedSignal.set(false);
this.cancelledSignal.set(false);
this.erroredSignal.set(false);
}
}
commit(): void {
this.erroredSignal.set(false);
this.committedSignal.set(true);
}
error(): void {
this.erroredSignal.set(true);
}
cancel(): void {
this.erroredSignal.set(false);
this.cancelledSignal.set(true);
}
toggleDebug(): void {
this.debugSignal.update(debug => !debug);
}
isSeatSelected(seatId: number): boolean {
return this.selectedSeats().some(seat => seat.id === seatId);
}
setConflict(value: boolean): void {
this.hadConflictSignal.set(value);
}
}