kinosaal designer

This commit is contained in:
2025-11-23 16:43:22 +01:00
parent 2ecaf2d526
commit 3a8fc2cc63
9 changed files with 526 additions and 169 deletions

View File

@@ -0,0 +1,185 @@
import { Component, inject, OnInit } from '@angular/core';
import { Kinosaal, Sitzkategorie, Sitzplatz, Sitzreihe } from '@infinimotion/model-frontend';
import { TheaterSeatState } from '../model/theater-seat-state.model';
import { SelectedSeatsService } from '../selected-seats.service';
import { HttpService } from '../http.service';
import { first, firstValueFrom } from 'rxjs';
import { TheaterOverlayComponent } from '../theater-overlay/theater-overlay.component';
import { ActivatedRoute, Router } from '@angular/router';
import { LoadingService } from '../loading.service';
@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);
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<number, Sitzkategorie>();
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,
};
});
}
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;
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();
for (let row of TheaterLayoutDesignerComponent.seatsPerRow) {
let seatRow;
if (!row[0].seat) {
return;
} 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, state } of row) {
if (seat != null && seat.id == 0) {
seat.row = seatRow;
let createdSeat = await firstValueFrom(this.http.createSeat(seat));
seat.id = createdSeat.id;
}
}
}
this.loading.showError('Kinosaal erfolgreich aktualisiert');
}
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]);
}
}