Handle empty seats and rows in theater layout

Updated seat and row data structures to allow null values for seats and states, enabling the display of empty seat spaces and rows. Adjusted rendering logic and styles to visually represent gaps in seating, and enhanced the converter to fill missing seats and rows with placeholders.
This commit is contained in:
2025-11-15 16:34:20 +01:00
parent be680da692
commit bd56f3242e
5 changed files with 63 additions and 11 deletions

View File

@@ -1 +1,6 @@
.empty-seat-space {
width: 30px;
/* Keine Ahnung, wo die zusätzlichen 6.5px herkommen müssen. Wir sonst dünner angezeigt */
height: 36.5px;
/* height: 30px; */
}

View File

@@ -1,3 +1,8 @@
@for (entry of rowSeatList(); track $index) { @for (entry of rowSeatList(); track $index) {
<app-seat class="my-1" [state]="entry.state" [seat]="entry.seat"></app-seat>
@if (entry.seat != null && entry.state != null) {
<app-seat class="my-1" [seat]="entry.seat" [state]="entry.state" ></app-seat>
} @else {
<div class="empty-seat-space my-1 mx-0.5"></div>
}
} }

View File

@@ -9,5 +9,5 @@ import {TheaterSeatState} from '../model/theater-seat-state.model';
styleUrl: './seat-row.component.css' styleUrl: './seat-row.component.css'
}) })
export class SeatRowComponent { export class SeatRowComponent {
rowSeatList = input.required<{ seat: Sitzplatz, state: TheaterSeatState }[]>(); rowSeatList = input.required<{ seat: Sitzplatz | null, state: TheaterSeatState | null }[]>();
} }

View File

@@ -10,7 +10,7 @@ import {TheaterSeatState} from '../model/theater-seat-state.model';
styleUrl: './theater-layout.component.css' styleUrl: './theater-layout.component.css'
}) })
export class TheaterLayoutComponent { export class TheaterLayoutComponent {
seatsPerRow = input.required<{ seat: Sitzplatz, state: TheaterSeatState }[][]>(); seatsPerRow = input.required<{ seat: Sitzplatz | null, state: TheaterSeatState | null }[][]>();
protected selectedSeatsService = inject(SelectedSeatsService); protected selectedSeatsService = inject(SelectedSeatsService);
} }

View File

@@ -25,7 +25,7 @@ export class TheaterOverlayComponent implements OnInit, OnDestroy {
readonly loading = inject(LoadingService); readonly loading = inject(LoadingService);
showId!: number; showId!: number;
seatsPerRow = signal<{ seat: Sitzplatz, state: TheaterSeatState }[][]>([]); seatsPerRow = signal<{ seat: Sitzplatz | null, state: TheaterSeatState | null }[][]>([]);
performance: Vorstellung | undefined; performance: Vorstellung | undefined;
seatCategories: Sitzkategorie[] = []; seatCategories: Sitzkategorie[] = [];
@@ -90,12 +90,13 @@ export class TheaterOverlayComponent implements OnInit, OnDestroy {
} }
converter(resp: { seats: Sitzplatz[], reserved: Sitzplatz[], booked: Sitzplatz[] }): { converter(resp: { seats: Sitzplatz[], reserved: Sitzplatz[], booked: Sitzplatz[] }): {
seat: Sitzplatz, seat: Sitzplatz | null,
state: TheaterSeatState state: TheaterSeatState | null
}[][] { }[][] {
let rows: { seat: Sitzplatz, state: TheaterSeatState }[][] = []; let rows: { seat: Sitzplatz | null, state: TheaterSeatState | null }[][] = [];
const categoryMap = new Map<number, Sitzkategorie>(); const categoryMap = new Map<number, Sitzkategorie>();
// Sitzplätze sammeln
resp.seats.forEach(seat => { resp.seats.forEach(seat => {
if (!rows[seat.row.position]) { if (!rows[seat.row.position]) {
rows[seat.row.position] = []; rows[seat.row.position] = [];
@@ -114,9 +115,50 @@ export class TheaterOverlayComponent implements OnInit, OnDestroy {
this.seatCategories = Array.from(categoryMap.values()).sort((a, b) => a.id - b.id); this.seatCategories = Array.from(categoryMap.values()).sort((a, b) => a.id - b.id);
rows = rows.filter(row => row.length > 0).sort((a, b) => a[0].seat.row.position - b[0].seat.row.position); rows = rows.filter(row => row && row.length > 0).sort((a, b) => a[0].seat!.row.position - b[0].seat!.row.position);
rows.forEach(row => row.sort((a, b) => a.seat.position - b.seat.position));
return rows; if (rows.length === 0) {
return [];
}
// Leere Plätze auffüllen
const filledSeats: { seat: Sitzplatz | null, state: TheaterSeatState | null }[][] = [];
rows.forEach(row => {
row.sort((a, b) => a.seat!.position - b.seat!.position)
const minPos = row[0].seat!.position;
const maxPos = row[row.length - 1].seat!.position;
const filledRow: { seat: Sitzplatz | null, state: TheaterSeatState | null }[] = [];
for (let pos = minPos; pos <= maxPos; pos++) {
const existingSeat = row.find(s => s.seat!.position === pos);
if (existingSeat) {
filledRow.push(existingSeat);
} else {
filledRow.push({ seat: null, state: null });
}
}
filledSeats.push(filledRow);
});
// Leere Reihen auffüllen
const minRowPos = rows[0][0].seat!.row.position;
const maxRowPos = rows[rows.length - 1][0].seat!.row.position;
const filledRows: { seat: Sitzplatz | null, state: TheaterSeatState | null }[][] = [];
let processedIndex = 0;
for (let rowPos = minRowPos; rowPos <= maxRowPos; rowPos++) {
if (processedIndex < filledSeats.length && filledSeats[processedIndex][0].seat!.row.position === rowPos) {
filledRows.push(filledSeats[processedIndex]);
processedIndex++;
} else {
filledRows.push([{ seat: null, state: null }]);
}
}
return filledRows;
} }
refreshSeats(): void { refreshSeats(): void {