import { Component, inject, OnInit } from '@angular/core'; import { Kinosaal, Sitzkategorie, Sitzplatz } from '@infinimotion/model-frontend'; import { TheaterSeatState } from '../model/theater-seat-state.model'; import { SelectedSeatsService } from '../selected-seats.service'; import { HttpService } from '../http.service'; import { firstValueFrom } from 'rxjs'; import { TheaterOverlayComponent } from '../theater-overlay/theater-overlay.component'; import { ActivatedRoute, Router } from '@angular/router'; import { LoadingService } from '../loading.service'; import { MatSnackBar } from '@angular/material/snack-bar'; @Component({ selector: 'app-theater-layout-designer', standalone: false, templateUrl: './theater-layout-designer.component.html', styleUrl: './theater-layout-designer.component.css', }) export class TheaterLayoutDesignerComponent implements OnInit { public static seatsPerRow: { seat: Sitzplatz | null; state: TheaterSeatState | null }[][] = []; addRow: { seat: Sitzplatz | null; state: TheaterSeatState | null }[] = []; protected selectedSeatsService = inject(SelectedSeatsService); protected http = inject(HttpService); protected route = inject(ActivatedRoute); protected loading = inject(LoadingService); protected router = inject(Router); constructor(private snackBar: MatSnackBar) {} getHallId() { return parseInt(this.route.snapshot.paramMap.get('hallId') ?? '-1'); } async ngOnInit() { let hallId = this.getHallId(); if (hallId == -1) { return; } let seats = await firstValueFrom(this.http.getSeatsByHallId(hallId)); let rows: { seat: Sitzplatz | null; state: TheaterSeatState | null }[][] = []; const categoryMap = new Map(); seats.forEach((seat) => { if (!rows[seat.row.position]) { rows[seat.row.position] = []; } rows[seat.row.position].push({ seat: seat, state: TheaterSeatState.RESERVED, }); if (seat.row.category && !categoryMap.has(seat.row.category.id)) { categoryMap.set(seat.row.category.id, seat.row.category); } }); TheaterLayoutDesignerComponent.seatsPerRow = TheaterOverlayComponent.fillSeatsPerRow(rows); let rowCounter = 0; TheaterLayoutDesignerComponent.seatsPerRow.forEach( (row) => (rowCounter = TheaterLayoutDesignerComponent.fillRowWithSettings(rowCounter, row)) ); let realCategories = await firstValueFrom(this.http.getSeatCategories()); this.addRow = realCategories.map((category) => { return { seat: { id: -2, position: 1, row: { id: 0, hall: { id: hallId } as Kinosaal, category: category, position: -1, }, }, state: TheaterSeatState.AVAILABLE, }; }); this.addRow.splice(0, 0, { seat: { id: -2, position: 1, row: { id: -1, hall: { id: hallId } as Kinosaal, category: { id: -1, name: '', price: -1, icon: 'check_box_outline_blank' }, position: -1, }, }, state: TheaterSeatState.AVAILABLE, }); } seatsPerRow() { return TheaterLayoutDesignerComponent.seatsPerRow; } public static fillRowWithSettings( rowCounter: number, row: { seat: Sitzplatz | null; state: TheaterSeatState | null; }[] ) { if (!row[0].seat) { return rowCounter + 1; } let categories: Sitzkategorie[] = [ { id: 0, name: '', price: -1, icon: 'check_box_outline_blank' }, { id: 1, name: '', price: -1, icon: 'add' }, ]; categories.forEach((category) => { row.push({ seat: { id: -1, position: row.length, row: { id: -1, hall: undefined as unknown as Kinosaal, position: rowCounter, category: category, }, }, state: TheaterSeatState.AVAILABLE, }); }); return rowCounter + 1; } static addSeatDesigner(selectedSeat: Sitzplatz): void { let row = TheaterLayoutDesignerComponent.seatsPerRow[selectedSeat.row.position]; if (selectedSeat.row.category.id == 0) { row.splice(row.length - 2, 0, { seat: null, state: null, }); } else { row.splice(row.length - 2, 0, { seat: { id: 0, position: row.length - 1, row: row[0].seat!.row }, state: TheaterSeatState.RESERVED, }); } } static addRowDesigner(selectedSeat: Sitzplatz): void { let rows = TheaterLayoutDesignerComponent.seatsPerRow; let firstSeat = { seat: { id: 0, position: 1, row: { ...selectedSeat.row } }, state: TheaterSeatState.RESERVED, }; firstSeat.seat!.row.position = rows.length + 1; if (selectedSeat.row.id == -1) { rows.push([{ seat: null, state: null }]); } else { rows.push([firstSeat]); } TheaterLayoutDesignerComponent.fillRowWithSettings(rows.length - 1, rows[rows.length - 1]); } public static interceptSeatSelection(selectedSeat: Sitzplatz) { if (selectedSeat.id == -1) { this.addSeatDesigner(selectedSeat); } else if (selectedSeat.id == -2) { this.addRowDesigner(selectedSeat); } else { console.log('Fehler: unerwartete Seat-ID: ' + selectedSeat.id); } } async save() { this.loading.show(); try { for (let row of TheaterLayoutDesignerComponent.seatsPerRow) { let seatRow; if (!row[0].seat) { continue; } else if (row[0].seat.row.id === 0) { seatRow = await firstValueFrom( this.http.createSeatRow(row[0].seat.row) ); } else { seatRow = row[0].seat.row; } for (const { seat } of row) { if (seat && seat.id === 0) { seat.row = seatRow; const createdSeat = await firstValueFrom(this.http.createSeat(seat)); seat.id = createdSeat.id; } } } this.snackBar.open( 'Kinosaal wurde erfolgreich aktualisiert.', 'Schließen', { duration: 5000, panelClass: ['success-snackbar'], horizontalPosition: 'right', verticalPosition: 'top' } ); this.loading.hide(); } catch (err) { console.error('Fehler beim Speichern des Kinosaals', err); this.loading.showError(err); } } hallName: string = ''; async navigate() { let halls = await firstValueFrom(this.http.getAllKinosaal()); let hall = halls.filter((hall) => hall.name == this.hallName); if (hall.length == 0) { hall[0] = await firstValueFrom(this.http.addKinosaal({ name: this.hallName })); } this.router.navigate(['/admin/designer', hall[0].id]); } }