Styling
This commit is contained in:
11
package-lock.json
generated
11
package-lock.json
generated
@@ -19,6 +19,7 @@
|
|||||||
"@infinimotion/model-frontend": "^0.0.102",
|
"@infinimotion/model-frontend": "^0.0.102",
|
||||||
"@tailwindcss/postcss": "^4.1.14",
|
"@tailwindcss/postcss": "^4.1.14",
|
||||||
"angularx-qrcode": "^20.0.0",
|
"angularx-qrcode": "^20.0.0",
|
||||||
|
"canvas-confetti": "^1.9.4",
|
||||||
"ngx-mask": "^20.0.3",
|
"ngx-mask": "^20.0.3",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
@@ -4431,6 +4432,16 @@
|
|||||||
],
|
],
|
||||||
"license": "CC-BY-4.0"
|
"license": "CC-BY-4.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/canvas-confetti": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"funding": {
|
||||||
|
"type": "donate",
|
||||||
|
"url": "https://www.paypal.me/kirilvatev"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "5.6.2",
|
"version": "5.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"@infinimotion/model-frontend": "^0.0.102",
|
"@infinimotion/model-frontend": "^0.0.102",
|
||||||
"@tailwindcss/postcss": "^4.1.14",
|
"@tailwindcss/postcss": "^4.1.14",
|
||||||
"angularx-qrcode": "^20.0.0",
|
"angularx-qrcode": "^20.0.0",
|
||||||
|
"canvas-confetti": "^1.9.4",
|
||||||
"ngx-mask": "^20.0.3",
|
"ngx-mask": "^20.0.3",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
|
|
||||||
<!-- Card Name -->
|
<!-- Card Name -->
|
||||||
<mat-form-field class="w-full">
|
<mat-form-field class="w-full">
|
||||||
<mat-label>Kartenname</mat-label>
|
<mat-label>Name des Besitzers</mat-label>
|
||||||
<input matInput formControlName="cardName" />
|
<input matInput formControlName="cardName" />
|
||||||
@if (fPayment['cardName'].hasError('minlength')) { <mat-error>Mindestens 3 Zeichen</mat-error> }
|
@if (fPayment['cardName'].hasError('minlength')) { <mat-error>Mindestens 3 Zeichen</mat-error> }
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ export class OrderComponent {
|
|||||||
private httpService = inject(HttpService)
|
private httpService = inject(HttpService)
|
||||||
private selectedSeatsService = inject(SelectedSeatsService);
|
private selectedSeatsService = inject(SelectedSeatsService);
|
||||||
|
|
||||||
|
confetti: any;
|
||||||
|
|
||||||
constructor(private fb: FormBuilder) {}
|
constructor(private fb: FormBuilder) {}
|
||||||
|
|
||||||
// Form-Validation
|
// Form-Validation
|
||||||
|
|
||||||
ngOnInit(): void {
|
async ngOnInit() {
|
||||||
this.paymentForm = this.fb.group({
|
this.paymentForm = this.fb.group({
|
||||||
cardNumber: ['', [Validators.required, Validators.pattern(/^\d{16}$/)]],
|
cardNumber: ['', [Validators.required, Validators.pattern(/^\d{16}$/)]],
|
||||||
cardName: ['', [Validators.required, Validators.minLength(3)]],
|
cardName: ['', [Validators.required, Validators.minLength(3)]],
|
||||||
@@ -43,6 +45,7 @@ export class OrderComponent {
|
|||||||
email: ['', [Validators.required, Validators.email]],
|
email: ['', [Validators.required, Validators.email]],
|
||||||
accept: ['', Validators.requiredTrue],
|
accept: ['', Validators.requiredTrue],
|
||||||
});
|
});
|
||||||
|
this.confetti = (await import('canvas-confetti')).default;
|
||||||
}
|
}
|
||||||
|
|
||||||
get fData() { return this.dataForm.controls; }
|
get fData() { return this.dataForm.controls; }
|
||||||
@@ -116,7 +119,6 @@ export class OrderComponent {
|
|||||||
const order = this.generateNewOrderObject(this.dataForm.value.email, false);
|
const order = this.generateNewOrderObject(this.dataForm.value.email, false);
|
||||||
const seats = this.selectedSeatsService.getSelectedSeatsList();
|
const seats = this.selectedSeatsService.getSelectedSeatsList();
|
||||||
const performance = this.performance()!;
|
const performance = this.performance()!;
|
||||||
this.successful = true;
|
|
||||||
this.sendToBackend(order, seats, performance);
|
this.sendToBackend(order, seats, performance);
|
||||||
this.seatsReserved = true;
|
this.seatsReserved = true;
|
||||||
}
|
}
|
||||||
@@ -128,7 +130,6 @@ export class OrderComponent {
|
|||||||
const order = this.generateNewOrderObject(this.dataForm.value.email, true);
|
const order = this.generateNewOrderObject(this.dataForm.value.email, true);
|
||||||
const seats = this.selectedSeatsService.getSelectedSeatsList();
|
const seats = this.selectedSeatsService.getSelectedSeatsList();
|
||||||
const performance = this.performance()!;
|
const performance = this.performance()!;
|
||||||
this.successful = true;
|
|
||||||
this.sendToBackend(order, seats, performance);
|
this.sendToBackend(order, seats, performance);
|
||||||
this.seatsPurchased = true;
|
this.seatsPurchased = true;
|
||||||
}
|
}
|
||||||
@@ -147,13 +148,28 @@ export class OrderComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(ticketCreations.map(obs => obs.toPromise()))
|
Promise.all(ticketCreations.map(obs => obs.toPromise()))
|
||||||
.then(createdTickets => {
|
.then(async createdTickets => {
|
||||||
this.createdTickets = createdTickets.filter(
|
this.createdTickets = createdTickets.filter(
|
||||||
(ticket): ticket is Eintrittskarte => ticket !== undefined
|
(ticket): ticket is Eintrittskarte => ticket !== undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.successful = true;
|
||||||
|
this.selectedSeatsService.setCommitedTrue();
|
||||||
this.loadingService.hide();
|
this.loadingService.hide();
|
||||||
this.enableInputs();
|
|
||||||
|
this.confetti({
|
||||||
|
particleCount: 100,
|
||||||
|
angle: 0,
|
||||||
|
spread: 180,
|
||||||
|
origin: { x: -0.1, y: 0.75 }
|
||||||
|
});
|
||||||
|
this.confetti({
|
||||||
|
particleCount: 100,
|
||||||
|
angle: 180,
|
||||||
|
spread: 180,
|
||||||
|
origin: { x: 1.1, y: 0.75 }
|
||||||
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
this.loadingService.showError(err);
|
this.loadingService.showError(err);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<button (click)="updateSelectedSeats(this.seat())" [disabled]="state() == TheaterSeatState.BOOKED || state() == TheaterSeatState.RESERVED || !seatService.getSeatIsSelectable()" class="mx-0.5">
|
<button (click)="updateSelectedSeats(this.seat())" [disabled]="state() == TheaterSeatState.BOOKED || state() == TheaterSeatState.RESERVED || !seatService.getSeatIsSelectable()" class="mx-0.5">
|
||||||
<mat-icon
|
<mat-icon
|
||||||
[class]="isHoverable()? 'hover:opacity-50' : ''"
|
[class]="isHoverable()? 'hover:opacity-50' : ''"
|
||||||
[ngStyle]="{color: isSelectedAndAvaliable() ? '#6366f1': getSeatStateColor() }"
|
[ngStyle]="{color : getSeatStateColor() }"
|
||||||
[style]="!seatService.getSeatIsSelectable()? 'transition: color 0.5s ease, transform 0.3s ease-in-out;' : ''"
|
[style]="!seatService.getSeatIsSelectable()? 'transition: color 0.5s ease, transform 0.3s ease-in-out;' : ''"
|
||||||
style="font-size: 30px; width: 30px; height: 30px;">
|
style="font-size: 30px; width: 30px; height: 30px;">
|
||||||
{{ seat().row.category.icon }}
|
{{ seat().row.category.icon }}
|
||||||
|
|||||||
@@ -19,15 +19,22 @@ export class SeatComponent{
|
|||||||
protected readonly TheaterSeatState = TheaterSeatState;
|
protected readonly TheaterSeatState = TheaterSeatState;
|
||||||
|
|
||||||
getSeatStateColor(): string {
|
getSeatStateColor(): string {
|
||||||
if (!this.seatService.getSeatIsSelectable()) return 'gray'
|
if (this.isSelectedAndAvaliable()) {
|
||||||
|
return this.seatService.getCommited()? '#00c951' : '#6366f1';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.seatService.getSeatIsSelectable()) {
|
||||||
|
return '#e0e0e0'
|
||||||
|
}
|
||||||
|
|
||||||
switch (this.state()) {
|
switch (this.state()) {
|
||||||
case TheaterSeatState.RESERVED:
|
case TheaterSeatState.RESERVED:
|
||||||
return '#d6c9a9';
|
return this.seatService.getDebug()? '#f7e8c3' : '#c0c0c0';
|
||||||
case TheaterSeatState.BOOKED:
|
case TheaterSeatState.BOOKED:
|
||||||
return '#d9abab';
|
return this.seatService.getDebug()? '#ffc9c9' : '#c0c0c0';
|
||||||
default:
|
default:
|
||||||
case TheaterSeatState.AVAILABLE:
|
case TheaterSeatState.AVAILABLE:
|
||||||
return 'black';
|
return '#1B1B23';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +57,6 @@ export class SeatComponent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.selected = !this.selected;
|
this.selected = !this.selected;
|
||||||
//console.log(this.selected)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isSelectedAndAvaliable(): boolean {
|
isSelectedAndAvaliable(): boolean {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import {Sitzplatz} from '@infinimotion/model-frontend';
|
|||||||
export class SelectedSeatsService {
|
export class SelectedSeatsService {
|
||||||
private selectedSeatsSignal = signal<Sitzplatz[]>([]);
|
private selectedSeatsSignal = signal<Sitzplatz[]>([]);
|
||||||
private seatIsSelectable: boolean = true;
|
private seatIsSelectable: boolean = true;
|
||||||
|
private commited = false;
|
||||||
|
private debug = false;
|
||||||
|
|
||||||
get selectedSeats() {
|
get selectedSeats() {
|
||||||
return this.selectedSeatsSignal;
|
return this.selectedSeatsSignal;
|
||||||
@@ -32,6 +34,7 @@ export class SelectedSeatsService {
|
|||||||
|
|
||||||
clearSelectedSeatsList(): void {
|
clearSelectedSeatsList(): void {
|
||||||
this.selectedSeatsSignal.set([]);
|
this.selectedSeatsSignal.set([]);
|
||||||
|
this.commited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSeatIsSelectable(): boolean{
|
getSeatIsSelectable(): boolean{
|
||||||
@@ -40,10 +43,27 @@ export class SelectedSeatsService {
|
|||||||
|
|
||||||
setSeatIsSelectableTrue(): void {
|
setSeatIsSelectableTrue(): void {
|
||||||
this.seatIsSelectable = true;
|
this.seatIsSelectable = true;
|
||||||
|
this.commited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSeatIsSelectableFalse(): void {
|
setSeatIsSelectableFalse(): void {
|
||||||
this.seatIsSelectable = false;
|
this.seatIsSelectable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCommited(): boolean {
|
||||||
|
return this.commited;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommitedTrue(): void {
|
||||||
|
this.commited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDebug(): boolean {
|
||||||
|
return this.debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDebug(): void {
|
||||||
|
this.debug = !this.debug;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="m-auto w-200 h-10 bg-gray-200 mb-22" style="clip-path: polygon(0% 0%,100% 0%,90% 100%,10% 100%);">
|
<div class="m-auto w-200 h-10 bg-gray-200 mb-22" style="clip-path: polygon(0% 0%,100% 0%,90% 100%,10% 100%);" (click)="selectedSeatsService.toggleDebug()">
|
||||||
<p class="flex justify-center text-lg font-bold p-1.5">
|
<p class="flex justify-center text-lg font-bold p-1.5">
|
||||||
Leinwand
|
Leinwand
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {Component, input} from '@angular/core';
|
import { SelectedSeatsService } from './../selected-seats.service';
|
||||||
|
import {Component, inject, input} from '@angular/core';
|
||||||
import {Sitzplatz} from '@infinimotion/model-frontend';
|
import {Sitzplatz} from '@infinimotion/model-frontend';
|
||||||
import {TheaterSeatState} from '../model/theater-seat-state.model';
|
import {TheaterSeatState} from '../model/theater-seat-state.model';
|
||||||
|
|
||||||
@@ -10,4 +11,6 @@ import {TheaterSeatState} from '../model/theater-seat-state.model';
|
|||||||
})
|
})
|
||||||
export class TheaterLayoutComponent {
|
export class TheaterLayoutComponent {
|
||||||
seatsPerRow = input.required<{ seat: Sitzplatz, state: TheaterSeatState }[][]>();
|
seatsPerRow = input.required<{ seat: Sitzplatz, state: TheaterSeatState }[][]>();
|
||||||
|
|
||||||
|
protected selectedSeatsService = inject(SelectedSeatsService);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,8 @@
|
|||||||
<div class="flex justify-between h-100">
|
<div class="flex justify-between h-100">
|
||||||
|
|
||||||
<div class="w-7/10 p-10 h-188">
|
<div class="w-7/10 p-10 h-188">
|
||||||
<!-- <div class="bg-linear-to-b from-indigo-300 to-pink-300 h-full rounded-lg"> -->
|
|
||||||
<div>
|
<div>
|
||||||
@if (loading.loading$ | async){
|
@if (!performance && (loading.loading$ | async)){
|
||||||
<div class="w-full h-full flex items-center justify-center mt-70">
|
<div class="w-full h-full flex items-center justify-center mt-70">
|
||||||
<mat-progress-spinner
|
<mat-progress-spinner
|
||||||
mode="indeterminate"
|
mode="indeterminate"
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
<div class="bg-white rounded-md shadow-sm w-full h-fit p-1 flex space-x-1 justify-between items-center">
|
<div class="bg-white rounded-md shadow-sm w-full h-fit p-1 flex space-x-1 justify-between items-center">
|
||||||
<mat-icon class="opacity-50" style="font-size: 40px; width: 40px; height: 40px">
|
<img src="assets/logo.png" class="h-10 border-r-2 pr-0.5 border-dotted border-gray-400" />
|
||||||
|
<!-- <mat-icon class="opacity-50 mx-1" style="font-size: 42px; width: 42px; height: 42px">
|
||||||
local_activity
|
local_activity
|
||||||
</mat-icon>
|
</mat-icon> -->
|
||||||
<div class="flex flex-col flex-1 text-sm leading-tight ml-1">
|
<div class="flex flex-col flex-1 text-sm leading-tight ml-1">
|
||||||
<p>{{ticket().seat.row.category.name}} • Reihe {{convertIntoRowName(ticket().seat.row.position)}} Platz {{ticket().seat.position}}</p>
|
<p>
|
||||||
|
{{ ticket().seat.row.category.name }}
|
||||||
|
@if (ticket().seat.row.category.name.length > 10) {
|
||||||
|
<br>
|
||||||
|
}
|
||||||
|
@else {
|
||||||
|
•
|
||||||
|
} Reihe
|
||||||
|
<span class="font-mono"><strong>{{ convertIntoRowName(ticket().seat.row.position) }}</strong></span>
|
||||||
|
Platz
|
||||||
|
<span class="font-mono"><strong>{{ ticket().seat.position }}</strong></span>
|
||||||
|
</p>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<p>Ticketcode:</p>
|
<p>Ticketcode:</p>
|
||||||
<p class="font-mono">
|
<p class="font-mono">
|
||||||
|
|||||||
1
src/typings.d.ts
vendored
Normal file
1
src/typings.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
declare module 'canvas-confetti';
|
||||||
Reference in New Issue
Block a user