Introduces a success snackbar notification when the theater layout is successfully saved in the designer component. Also adds a custom style for the success snackbar in the theme.
229 lines
6.7 KiB
TypeScript
229 lines
6.7 KiB
TypeScript
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<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,
|
|
};
|
|
});
|
|
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]);
|
|
}
|
|
}
|