From 35ddedb5c30c97ad68c1a89e0c42a4239068ea6e Mon Sep 17 00:00:00 2001 From: Tara Wilson Date: Sat, 7 Dec 2024 17:25:55 -0500 Subject: [PATCH] Fixing bugs Refactoring scanning Adding data connections --- .../ticketAPI/api/Services/TicketManager.cs | 2 +- .../models/Enumerations/TicketValidity.cs | 4 +- .../event-browser.component.html | 18 +++-- .../event-browser.component.scss | 3 - .../event-browser/event-browser.component.ts | 14 +++- .../generated-ticket.component.html} | 0 .../generated-ticket.component.scss} | 0 .../generated-ticket.component.ts} | 8 +- .../patron-info/patron-info.component.html | 80 +++++++++---------- .../patron-info/patron-info.component.scss | 3 - .../patron-info/patron-info.component.ts | 32 ++++++-- .../scan-result/scan-result.component.html | 70 ++++------------ .../scan-result/scan-result.component.ts | 64 +++++++++++++-- .../season-browser.component.html | 18 +++-- .../season-browser.component.scss | 3 - .../season-browser.component.ts | 15 +++- .../ticket-type-selector.component.html | 17 ++-- .../ticket-type-selector.component.scss | 3 - .../ticket-type-selector.component.ts | 15 +++- .../src/app/page/event/event.component.html | 56 ++++++------- .../src/app/page/event/event.component.scss | 3 - .../src/app/page/event/event.component.ts | 33 ++++++-- .../src/app/page/scan/scan.component.html | 2 +- .../src/app/page/scan/scan.component.ts | 7 ++ .../src/app/page/ticket/ticket.component.html | 15 +++- .../src/app/page/ticket/ticket.component.ts | 27 ++++++- .../src/app/services/event.service.ts | 25 ++---- .../ticketUI/src/app/services/scan.service.ts | 10 ++- .../src/app/services/season.service.ts | 7 +- .../src/app/services/snackbar.service.ts | 10 +++ source/ticketUI/src/models/core/talent.ts | 5 ++ source/ticketUI/src/models/core/venue.ts | 10 +++ .../src/models/enums/ticket-type.enum.ts | 7 ++ .../src/models/enums/ticket-validity.enum.ts | 5 +- .../src/models/request/add-event-request.ts | 3 +- .../ticketUI/src/models/request/add-ticket.ts | 7 +- .../src/models/response/ticket-search.ts | 4 +- source/ticketUI/src/styles.scss | 45 +++++++++++ 38 files changed, 419 insertions(+), 231 deletions(-) rename source/ticketUI/src/app/components/{ticket/ticket.component.html => generated-ticket/generated-ticket.component.html} (100%) rename source/ticketUI/src/app/components/{ticket/ticket.component.scss => generated-ticket/generated-ticket.component.scss} (100%) rename source/ticketUI/src/app/components/{ticket/ticket.component.ts => generated-ticket/generated-ticket.component.ts} (56%) diff --git a/source/ticketAPI/api/Services/TicketManager.cs b/source/ticketAPI/api/Services/TicketManager.cs index a50fffa..9fbc1ac 100644 --- a/source/ticketAPI/api/Services/TicketManager.cs +++ b/source/ticketAPI/api/Services/TicketManager.cs @@ -61,7 +61,7 @@ public class TicketManager : ITicketManager return TicketValidity.Expired; } - if (@event.Date != DateTime.Today) return TicketValidity.Invalid; + if (@event.Date.Day != DateTime.Today.Day) return TicketValidity.Invalid; if (DateTime.Now.Hour < @event.Date.Hour - 2) { diff --git a/source/ticketAPI/models/Enumerations/TicketValidity.cs b/source/ticketAPI/models/Enumerations/TicketValidity.cs index 137f9db..7c31594 100644 --- a/source/ticketAPI/models/Enumerations/TicketValidity.cs +++ b/source/ticketAPI/models/Enumerations/TicketValidity.cs @@ -2,8 +2,8 @@ namespace models.Enumerations; public enum TicketValidity { - Valid, Expired, Early, - Invalid + Invalid, + Valid, } \ No newline at end of file diff --git a/source/ticketUI/src/app/components/event-browser/event-browser.component.html b/source/ticketUI/src/app/components/event-browser/event-browser.component.html index 96b7310..36ef5ef 100644 --- a/source/ticketUI/src/app/components/event-browser/event-browser.component.html +++ b/source/ticketUI/src/app/components/event-browser/event-browser.component.html @@ -1,9 +1,11 @@ -
- - +
+
+ + +
diff --git a/source/ticketUI/src/app/components/event-browser/event-browser.component.scss b/source/ticketUI/src/app/components/event-browser/event-browser.component.scss index 0a5d778..e69de29 100644 --- a/source/ticketUI/src/app/components/event-browser/event-browser.component.scss +++ b/source/ticketUI/src/app/components/event-browser/event-browser.component.scss @@ -1,3 +0,0 @@ -label { - padding-right: 15px; -} diff --git a/source/ticketUI/src/app/components/event-browser/event-browser.component.ts b/source/ticketUI/src/app/components/event-browser/event-browser.component.ts index 1664291..dcee879 100644 --- a/source/ticketUI/src/app/components/event-browser/event-browser.component.ts +++ b/source/ticketUI/src/app/components/event-browser/event-browser.component.ts @@ -1,17 +1,27 @@ -import {Component, inject, OnInit} from '@angular/core'; +import {Component, inject, OnInit, signal, WritableSignal} from '@angular/core'; import {EventService} from '../../services/event.service'; +import {ReactiveFormsModule} from '@angular/forms'; @Component({ selector: 'app-event-browser', - imports: [], + imports: [ + ReactiveFormsModule + ], templateUrl: './event-browser.component.html', styleUrl: './event-browser.component.scss' }) export class EventBrowserComponent implements OnInit { private eventService = inject(EventService); public events$ = this.eventService.events$; + public selectedEventId!: string; + public selectedEventId$: WritableSignal = signal(''); public ngOnInit() { this.eventService.searchAllEvents(); } + + public click(eventId: string): void { + this.selectedEventId = eventId; + this.selectedEventId$.set(eventId); + } } diff --git a/source/ticketUI/src/app/components/ticket/ticket.component.html b/source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.html similarity index 100% rename from source/ticketUI/src/app/components/ticket/ticket.component.html rename to source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.html diff --git a/source/ticketUI/src/app/components/ticket/ticket.component.scss b/source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.scss similarity index 100% rename from source/ticketUI/src/app/components/ticket/ticket.component.scss rename to source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.scss diff --git a/source/ticketUI/src/app/components/ticket/ticket.component.ts b/source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.ts similarity index 56% rename from source/ticketUI/src/app/components/ticket/ticket.component.ts rename to source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.ts index 55dbcf4..709457e 100644 --- a/source/ticketUI/src/app/components/ticket/ticket.component.ts +++ b/source/ticketUI/src/app/components/generated-ticket/generated-ticket.component.ts @@ -2,12 +2,12 @@ import {Component, inject} from '@angular/core'; import {TicketService} from '../../services/ticket.service'; @Component({ - selector: 'app-ticket', + selector: 'app-generated-ticket', imports: [], - templateUrl: './ticket.component.html', - styleUrl: './ticket.component.scss' + templateUrl: './generated-ticket.component.html', + styleUrl: './generated-ticket.component.scss' }) -export class TicketComponent { +export class GeneratedTicketComponent { private ticket = inject(TicketService); public qrCode = this.ticket.dataSignal$; } diff --git a/source/ticketUI/src/app/components/patron-info/patron-info.component.html b/source/ticketUI/src/app/components/patron-info/patron-info.component.html index b2e5a2a..425587d 100644 --- a/source/ticketUI/src/app/components/patron-info/patron-info.component.html +++ b/source/ticketUI/src/app/components/patron-info/patron-info.component.html @@ -1,45 +1,45 @@

Patron Information

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
diff --git a/source/ticketUI/src/app/components/patron-info/patron-info.component.scss b/source/ticketUI/src/app/components/patron-info/patron-info.component.scss index 0a5d778..e69de29 100644 --- a/source/ticketUI/src/app/components/patron-info/patron-info.component.scss +++ b/source/ticketUI/src/app/components/patron-info/patron-info.component.scss @@ -1,3 +0,0 @@ -label { - padding-right: 15px; -} diff --git a/source/ticketUI/src/app/components/patron-info/patron-info.component.ts b/source/ticketUI/src/app/components/patron-info/patron-info.component.ts index 902f735..0ab0c74 100644 --- a/source/ticketUI/src/app/components/patron-info/patron-info.component.ts +++ b/source/ticketUI/src/app/components/patron-info/patron-info.component.ts @@ -1,5 +1,6 @@ -import { Component } from '@angular/core'; +import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms'; +import {Patron} from '../../../models/core/patron'; @Component({ selector: 'app-patron-info', @@ -10,14 +11,29 @@ import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms'; styleUrl: './patron-info.component.scss' }) export class PatronInfoComponent { - public firstName = new FormControl('', [Validators.required]); + public firstName = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public middleName = new FormControl(''); - public lastName = new FormControl('', [Validators.required]); - public email = new FormControl('', [Validators.required]); + public lastName = new FormControl('', {nonNullable: true, validators: [Validators.required]}); + public email = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public phoneNumber = new FormControl(''); - public addressOne = new FormControl('', [Validators.required]); + public addressOne = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public addressTwo = new FormControl(''); - public city = new FormControl('', [Validators.required]); - public state = new FormControl('', [Validators.required]); - public zip = new FormControl('', [Validators.required]); + public city = new FormControl('', {nonNullable: true, validators: [Validators.required]}); + public state = new FormControl('', {nonNullable: true, validators: [Validators.required]}); + public zip = new FormControl('', {nonNullable: true, validators: [Validators.required]}); + + public buildPatron(): Patron { + return { + firstName: this.firstName.value, + middleName: this.middleName.value, + lastName: this.lastName.value, + email: this.email.value, + phoneNumber: this.phoneNumber.value, + addressOne: this.addressOne.value, + addressTwo: this.addressTwo.value, + city: this.city.value, + state: this.state.value, + zip: this.zip.value, + }; + } } diff --git a/source/ticketUI/src/app/components/scan-result/scan-result.component.html b/source/ticketUI/src/app/components/scan-result/scan-result.component.html index 95b29fd..4af61f7 100644 --- a/source/ticketUI/src/app/components/scan-result/scan-result.component.html +++ b/source/ticketUI/src/app/components/scan-result/scan-result.component.html @@ -1,57 +1,21 @@ -@if (ticketValidity() !== TicketValidity.Invalid && ticketType() !== TicketTypeEnum.Null) { -
-
- @if (ticketValidity() == TicketValidity.Valid) { - Ticket Valid - Valid - } @else { - Ticket Invalid - Invalid +@if (ticketSearch$() != null) { +
+ +
+
+ + {{getValidityText()}} +
+ @if(ticketValidity() === TicketValidity.Valid) { +
+ + {{getTypeText()}} +
+ @if(IsSeasonTicket(ticketType())) { + Season Ticket + Seasonal + } }
- @if (ticketValidity() == TicketValidity.Valid) { -
- @switch (ticketType()){ - @case (TicketTypeEnum.Family) { - Family - Family - } - @case (TicketTypeEnum.FamilySeason) { - Family - Family - } - @case (TicketTypeEnum.Single) { - Single - Single - } - @case (TicketTypeEnum.SingleSeason) { - Single - Single - } - @case (TicketTypeEnum.Senior) { - Senior - Senior - } - @case (TicketTypeEnum.SeniorSeason) { - Senior - Senior - } - } -
-
- @if (ticketType() !== TicketTypeEnum.FamilySeason) { - Family - Season - } - @if (ticketType() !== TicketTypeEnum.SingleSeason) { - Single - Season - } - @if (ticketType() !== TicketTypeEnum.SeniorSeason) { - Single - Season - } -
- }
} diff --git a/source/ticketUI/src/app/components/scan-result/scan-result.component.ts b/source/ticketUI/src/app/components/scan-result/scan-result.component.ts index 583c66c..9eb571a 100644 --- a/source/ticketUI/src/app/components/scan-result/scan-result.component.ts +++ b/source/ticketUI/src/app/components/scan-result/scan-result.component.ts @@ -1,14 +1,11 @@ import {Component, inject} from '@angular/core'; import {TicketValidity} from '../../../models/enums/ticket-validity.enum'; -import {TicketTypeEnum} from '../../../models/enums/ticket-type.enum'; +import {IsSeasonTicket, TicketTypeEnum} from '../../../models/enums/ticket-type.enum'; import {ScanService} from '../../services/scan.service'; -import {NgOptimizedImage} from '@angular/common'; @Component({ selector: 'app-scan-result', - imports: [ - NgOptimizedImage - ], + imports: [], templateUrl: './scan-result.component.html', styleUrl: './scan-result.component.scss' }) @@ -16,6 +13,61 @@ export class ScanResultComponent { private scan = inject(ScanService); public ticketValidity = this.scan.ticketValid$; public ticketType = this.scan.ticketType$; + public ticketSearch$ = this.scan.ticketSearch$; protected readonly TicketValidity = TicketValidity; - protected readonly TicketTypeEnum = TicketTypeEnum; + protected readonly IsSeasonTicket = IsSeasonTicket; + + public getValidityText(): string { + switch (this.ticketValidity()) { + case TicketValidity.Valid: + return 'Valid'; + case TicketValidity.Expired: + return 'Expired'; + case TicketValidity.Early: + return 'Early'; + default: + return 'Invalid'; + } + } + + public getValidityImage(): string { + switch (this.ticketValidity()) { + case TicketValidity.Valid: + return 'pass.svg'; + default: + return 'fail.svg'; + } + } + + public getTypeImage(): string { + switch (this.ticketType()) { + case TicketTypeEnum.SingleSeason: + case TicketTypeEnum.Single: + return 'single.svg'; + case TicketTypeEnum.FamilySeason: + case TicketTypeEnum.Family: + return 'group.svg'; + case TicketTypeEnum.SeniorSeason: + case TicketTypeEnum.Senior: + return 'senior.svg'; + default: + return ''; + } + } + + public getTypeText(): string { + switch (this.ticketType()) { + case TicketTypeEnum.SingleSeason: + case TicketTypeEnum.Single: + return 'Single Ticket'; + case TicketTypeEnum.FamilySeason: + case TicketTypeEnum.Family: + return 'Family Ticket'; + case TicketTypeEnum.SeniorSeason: + case TicketTypeEnum.Senior: + return 'Senior Ticket'; + default: + return ''; + } + } } diff --git a/source/ticketUI/src/app/components/season-browser/season-browser.component.html b/source/ticketUI/src/app/components/season-browser/season-browser.component.html index 650b32c..e293216 100644 --- a/source/ticketUI/src/app/components/season-browser/season-browser.component.html +++ b/source/ticketUI/src/app/components/season-browser/season-browser.component.html @@ -1,9 +1,11 @@ -
- - +
+
+ + +
diff --git a/source/ticketUI/src/app/components/season-browser/season-browser.component.scss b/source/ticketUI/src/app/components/season-browser/season-browser.component.scss index 0a5d778..e69de29 100644 --- a/source/ticketUI/src/app/components/season-browser/season-browser.component.scss +++ b/source/ticketUI/src/app/components/season-browser/season-browser.component.scss @@ -1,3 +0,0 @@ -label { - padding-right: 15px; -} diff --git a/source/ticketUI/src/app/components/season-browser/season-browser.component.ts b/source/ticketUI/src/app/components/season-browser/season-browser.component.ts index d296bee..ab612eb 100644 --- a/source/ticketUI/src/app/components/season-browser/season-browser.component.ts +++ b/source/ticketUI/src/app/components/season-browser/season-browser.component.ts @@ -1,17 +1,28 @@ -import {Component, inject, OnInit} from '@angular/core'; +import {Component, inject, OnInit, signal, WritableSignal} from '@angular/core'; import {SeasonService} from '../../services/season.service'; +import {Season} from '../../../models/core/season'; +import {ReactiveFormsModule} from '@angular/forms'; @Component({ selector: 'app-season-browser', - imports: [], + imports: [ + ReactiveFormsModule + ], templateUrl: './season-browser.component.html', styleUrl: './season-browser.component.scss' }) export class SeasonBrowserComponent implements OnInit { private seasonService = inject(SeasonService); public seasons$ = this.seasonService.seasons$; + public selectedSeasonId$: WritableSignal = signal(''); + public selectedSeasonId!: string; public ngOnInit() { this.seasonService.getSeasons(); } + + public click(selectedSeasonId: string): void { + this.selectedSeasonId$.set(selectedSeasonId); + this.selectedSeasonId = selectedSeasonId; + } } diff --git a/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.html b/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.html index d949c7b..2ffdc31 100644 --- a/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.html +++ b/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.html @@ -1,9 +1,10 @@ -
- - +
+
+ + +
diff --git a/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.scss b/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.scss index 0a5d778..e69de29 100644 --- a/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.scss +++ b/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.scss @@ -1,3 +0,0 @@ -label { - padding-right: 15px; -} diff --git a/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.ts b/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.ts index f7286be..040fdcf 100644 --- a/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.ts +++ b/source/ticketUI/src/app/components/ticket-type-selector/ticket-type-selector.component.ts @@ -1,15 +1,24 @@ -import { Component } from '@angular/core'; -import {TicketTypeEnumLabel} from '../../../models/enums/ticket-type.enum'; +import {Component, signal, WritableSignal} from '@angular/core'; +import {TicketTypeEnum, TicketTypeEnumLabel} from '../../../models/enums/ticket-type.enum'; import {KeyValuePipe} from '@angular/common'; +import {ReactiveFormsModule} from '@angular/forms'; @Component({ selector: 'app-ticket-type-selector', imports: [ - KeyValuePipe + KeyValuePipe, + ReactiveFormsModule ], templateUrl: './ticket-type-selector.component.html', styleUrl: './ticket-type-selector.component.scss' }) export class TicketTypeSelectorComponent { public ticketTypes = TicketTypeEnumLabel; + public selectedTicketType$: WritableSignal = signal(TicketTypeEnum.Null); + public selectedTicketType!: TicketTypeEnum; + + public click(ticketType: number): void { + this.selectedTicketType$.set(ticketType as TicketTypeEnum); + this.selectedTicketType = ticketType as TicketTypeEnum; + } } diff --git a/source/ticketUI/src/app/page/event/event.component.html b/source/ticketUI/src/app/page/event/event.component.html index f58d9a8..f6a5b29 100644 --- a/source/ticketUI/src/app/page/event/event.component.html +++ b/source/ticketUI/src/app/page/event/event.component.html @@ -2,22 +2,22 @@

Add Season

- - - - - - - - - - - - - - - - +
+ + +
+
+ + +
+
+ + +
+
+ + +
@@ -26,18 +26,18 @@

Add Event

- - - - - - - - - - - - +
+ + +
+
+ + +
+
+ + +
diff --git a/source/ticketUI/src/app/page/event/event.component.scss b/source/ticketUI/src/app/page/event/event.component.scss index 0a5d778..e69de29 100644 --- a/source/ticketUI/src/app/page/event/event.component.scss +++ b/source/ticketUI/src/app/page/event/event.component.scss @@ -1,3 +0,0 @@ -label { - padding-right: 15px; -} diff --git a/source/ticketUI/src/app/page/event/event.component.ts b/source/ticketUI/src/app/page/event/event.component.ts index fd6c089..b1e9bd5 100644 --- a/source/ticketUI/src/app/page/event/event.component.ts +++ b/source/ticketUI/src/app/page/event/event.component.ts @@ -1,8 +1,12 @@ -import {Component, inject} from '@angular/core'; +import {Component, inject, ViewChild} from '@angular/core'; import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms'; import {EventService} from '../../services/event.service'; import {SeasonService} from '../../services/season.service'; import {SeasonBrowserComponent} from '../../components/season-browser/season-browser.component'; +import {AddEventRequest} from '../../../models/request/add-event-request'; +import {AddSeason} from '../../../models/request/add-season'; +import {VALLEY_FORGE_HIGH_SCHOOL} from '../../../models/core/venue'; +import {PARMA_SYMPHONY_ORCHESTRA} from '../../../models/core/talent'; @Component({ selector: 'app-event', @@ -11,23 +15,40 @@ import {SeasonBrowserComponent} from '../../components/season-browser/season-bro styleUrl: './event.component.scss' }) export class EventComponent { - public eventName = new FormControl('', [Validators.required]); + @ViewChild(SeasonBrowserComponent) seasonBrowser!: SeasonBrowserComponent; + public eventName = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public eventDescription = new FormControl(''); - public eventDate = new FormControl(new Date, [Validators.required]); + public eventDate = new FormControl(new Date, {nonNullable: true, validators: [Validators.required]}); - public seasonName = new FormControl('', [Validators.required]); + public seasonName = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public seasonDescription = new FormControl(''); - public seasonStartDate = new FormControl(new Date, [Validators.required]); - public seasonEndDate = new FormControl(new Date, [Validators.required]); + public seasonStartDate = new FormControl(new Date, {nonNullable: true, validators: [Validators.required]}); + public seasonEndDate = new FormControl(new Date, {nonNullable: true, validators: [Validators.required]}); private eventService = inject(EventService); private seasonService = inject(SeasonService); public saveEvent(): void { + const request: AddEventRequest = { + date: this.eventDate.value, + name: this.eventName.value, + description: this.eventDescription.value, + venue: VALLEY_FORGE_HIGH_SCHOOL, + talent: PARMA_SYMPHONY_ORCHESTRA, + seasonId: this.seasonBrowser.selectedSeasonId + }; + this.eventService.addEvent(request); } public saveSeason(): void { + const request: AddSeason = { + startDate: this.seasonStartDate.value, + endDate: this.seasonEndDate.value, + name: this.seasonName.value, + description: this.seasonDescription.value, + }; + this.seasonService.saveSeason(request); } } diff --git a/source/ticketUI/src/app/page/scan/scan.component.html b/source/ticketUI/src/app/page/scan/scan.component.html index c55f3ea..af2b08f 100644 --- a/source/ticketUI/src/app/page/scan/scan.component.html +++ b/source/ticketUI/src/app/page/scan/scan.component.html @@ -1,4 +1,4 @@ -
+ +@if(qrCode().length > 0) { + +} diff --git a/source/ticketUI/src/app/page/ticket/ticket.component.ts b/source/ticketUI/src/app/page/ticket/ticket.component.ts index 3db80c2..53ef073 100644 --- a/source/ticketUI/src/app/page/ticket/ticket.component.ts +++ b/source/ticketUI/src/app/page/ticket/ticket.component.ts @@ -1,23 +1,46 @@ -import {Component, inject} from '@angular/core'; +import {Component, inject, ViewChild} from '@angular/core'; import {EventBrowserComponent} from '../../components/event-browser/event-browser.component'; import {TicketTypeSelectorComponent} from '../../components/ticket-type-selector/ticket-type-selector.component'; import {PatronInfoComponent} from '../../components/patron-info/patron-info.component'; import {TicketService} from '../../services/ticket.service'; +import {AddTicket} from '../../../models/request/add-ticket'; +import {SeasonBrowserComponent} from '../../components/season-browser/season-browser.component'; +import {IsSeasonTicket} from '../../../models/enums/ticket-type.enum'; +import {GeneratedTicketComponent} from '../../components/generated-ticket/generated-ticket.component'; @Component({ selector: 'app-ticket', imports: [ EventBrowserComponent, TicketTypeSelectorComponent, - PatronInfoComponent + PatronInfoComponent, + SeasonBrowserComponent, + GeneratedTicketComponent ], templateUrl: './ticket.component.html', styleUrl: './ticket.component.scss' }) export class TicketComponent { + @ViewChild(TicketTypeSelectorComponent) ticketTypeSelector!: TicketTypeSelectorComponent; + @ViewChild(PatronInfoComponent) patronInfoComponent!: PatronInfoComponent; + @ViewChild(EventBrowserComponent) eventBrowserComponent!: EventBrowserComponent; + @ViewChild(SeasonBrowserComponent) seasonBrowserComponent!: SeasonBrowserComponent; + public ticketService = inject(TicketService); + public qrCode = this.ticketService.dataSignal$; public saveTicket(): void { + const addTicket: AddTicket = { + eventId: this.eventBrowserComponent.selectedEventId, + type: this.ticketTypeSelector.selectedTicketType, + seasonId: + IsSeasonTicket(this.ticketTypeSelector.selectedTicketType) + ? this.seasonBrowserComponent.selectedSeasonId : '', + patron: this.patronInfoComponent.buildPatron() + } + this.ticketService.addTicket(addTicket); } + + protected readonly IsSeasonTicket = IsSeasonTicket; } diff --git a/source/ticketUI/src/app/services/event.service.ts b/source/ticketUI/src/app/services/event.service.ts index 76ef9d0..1eb34c9 100644 --- a/source/ticketUI/src/app/services/event.service.ts +++ b/source/ticketUI/src/app/services/event.service.ts @@ -22,32 +22,21 @@ export class EventService extends ApiUtils { public addEvent(request: AddEventRequest): void { //TODO: Remove hard coded venue and talent information - - request.talent = { - name: 'Parma Symphony Orchestra', - description: 'Parma Symphony Orchestra is a Northeast Ohio community orchestra with over 50 years of history bringing classical music to people of all ages, with opportunities for local students and professional guests to perform a wide ranging repertoire.', - }; - - request.venue = { - name: 'Valley Forge High School', - description: 'Auditorium', - addressOne: '9999 Independence Blvd', - addressTwo: null, - city: 'Parma', - state: 'Ohio', - zip: '44130' - }; - const options = this.setHttpRequestOptions(); const url = environment.apiBase + Endpoints.EVENT; - this.httpClient.post(url, JSON.stringify(request), options) + this.httpClient.post(url, JSON.stringify(request), options) .pipe( catchError(error => { this.snackbar.showError(error.error); return of(undefined); }) - ).subscribe(); + ).subscribe(res => { + if(res !== null) { + this.snackbar.showMessage('Event added successfully.'); + this.searchAllEvents(); + } + }); } public searchAllEvents(): void { diff --git a/source/ticketUI/src/app/services/scan.service.ts b/source/ticketUI/src/app/services/scan.service.ts index da3cc6a..adbeee9 100644 --- a/source/ticketUI/src/app/services/scan.service.ts +++ b/source/ticketUI/src/app/services/scan.service.ts @@ -13,8 +13,9 @@ import {SnackbarService} from './snackbar.service'; providedIn: 'root' }) export class ScanService extends ApiUtils { - public ticketValid$: WritableSignal = signal(TicketValidity.Null); - public ticketType$: WritableSignal = signal(TicketTypeEnum.Null); + public ticketValid$: WritableSignal = signal(TicketValidity.Invalid); + public ticketType$: WritableSignal = signal(TicketTypeEnum.Null); + public ticketSearch$: WritableSignal = signal(null); private httpClient = inject(HttpClient); private snackbar = inject(SnackbarService); @@ -35,8 +36,9 @@ export class ScanService extends ApiUtils { }) ).subscribe((res: TicketSearch) => { if (res !== undefined) { - this.ticketType$.set(res.ticketType); - this.ticketValid$.set(res.ticketValidity) + this.ticketSearch$.set(res); + this.ticketType$.set(res.type as TicketTypeEnum); + this.ticketValid$.set(res.validity as TicketValidity); } }); } diff --git a/source/ticketUI/src/app/services/season.service.ts b/source/ticketUI/src/app/services/season.service.ts index 19124a7..ba6b04d 100644 --- a/source/ticketUI/src/app/services/season.service.ts +++ b/source/ticketUI/src/app/services/season.service.ts @@ -48,7 +48,12 @@ export class SeasonService extends ApiUtils { this.snackbar.showError(error.error); return of(undefined); }) - ).subscribe(); + ).subscribe(res => { + if (res !== null) { + this.snackbar.showMessage('Season added successfully.'); + this.getSeasons(); + } + }); } public addEventToSeason(eventId: string, seasonId: string): void { diff --git a/source/ticketUI/src/app/services/snackbar.service.ts b/source/ticketUI/src/app/services/snackbar.service.ts index 382df8c..9a0935d 100644 --- a/source/ticketUI/src/app/services/snackbar.service.ts +++ b/source/ticketUI/src/app/services/snackbar.service.ts @@ -16,4 +16,14 @@ export class SnackbarService { this.snackbarMessage$.set(''); }, 5000); } + + public showMessage(message: string): void { + this.showSnackbar$.set(true); + this.snackbarMessage$.set(message); + + setTimeout(() => { + this.showSnackbar$.set(false); + this.snackbarMessage$.set(''); + }, 5000); + } } diff --git a/source/ticketUI/src/models/core/talent.ts b/source/ticketUI/src/models/core/talent.ts index 8badd9b..e0eaf3b 100644 --- a/source/ticketUI/src/models/core/talent.ts +++ b/source/ticketUI/src/models/core/talent.ts @@ -2,3 +2,8 @@ export interface Talent { name: string; description: string | null; } + +export const PARMA_SYMPHONY_ORCHESTRA: Talent = { + name: 'Parma Symphony Orchestra', + description: 'Parma Symphony Orchestra is a Northeast Ohio community orchestra with over 50 years of history bringing classical music to people of all ages, with opportunities for local students and professional guests to perform a wide ranging repertoire.', +} diff --git a/source/ticketUI/src/models/core/venue.ts b/source/ticketUI/src/models/core/venue.ts index 0fcb6a0..a2dcf58 100644 --- a/source/ticketUI/src/models/core/venue.ts +++ b/source/ticketUI/src/models/core/venue.ts @@ -7,3 +7,13 @@ export interface Venue { state: string, zip: string, } + +export const VALLEY_FORGE_HIGH_SCHOOL: Venue = { + name: 'Valley Forge High School', + description: 'Auditorium', + addressOne: '9999 Independence Blvd', + addressTwo: null, + city: 'Parma', + state: 'Ohio', + zip: '44130' +} diff --git a/source/ticketUI/src/models/enums/ticket-type.enum.ts b/source/ticketUI/src/models/enums/ticket-type.enum.ts index 3c29373..816b136 100644 --- a/source/ticketUI/src/models/enums/ticket-type.enum.ts +++ b/source/ticketUI/src/models/enums/ticket-type.enum.ts @@ -9,6 +9,7 @@ export enum TicketTypeEnum { } export const TicketTypeEnumLabel = new Map([ + [TicketTypeEnum.Null, 'Select'], [TicketTypeEnum.Single, 'Single'], [TicketTypeEnum.SingleSeason, 'Single Season'], [TicketTypeEnum.Family, 'Family'], @@ -16,3 +17,9 @@ export const TicketTypeEnumLabel = new Map([ [TicketTypeEnum.Senior, 'Senior'], [TicketTypeEnum.SeniorSeason, 'Senior Season'], ]); + +export function IsSeasonTicket(type: TicketTypeEnum): boolean { + return type === TicketTypeEnum.SingleSeason + || type === TicketTypeEnum.FamilySeason + || type === TicketTypeEnum.SeniorSeason; +} diff --git a/source/ticketUI/src/models/enums/ticket-validity.enum.ts b/source/ticketUI/src/models/enums/ticket-validity.enum.ts index 99b468a..9b7fbe6 100644 --- a/source/ticketUI/src/models/enums/ticket-validity.enum.ts +++ b/source/ticketUI/src/models/enums/ticket-validity.enum.ts @@ -1,7 +1,6 @@ export enum TicketValidity { - Null, - Valid, Expired, Early, - Invalid + Invalid, + Valid, } diff --git a/source/ticketUI/src/models/request/add-event-request.ts b/source/ticketUI/src/models/request/add-event-request.ts index 34c18f4..46a73f2 100644 --- a/source/ticketUI/src/models/request/add-event-request.ts +++ b/source/ticketUI/src/models/request/add-event-request.ts @@ -4,7 +4,8 @@ import {Talent} from '../core/talent'; export interface AddEventRequest { date: Date, name: string, - description: string, + description: string | null, venue: Venue, talent: Talent, + seasonId: string } diff --git a/source/ticketUI/src/models/request/add-ticket.ts b/source/ticketUI/src/models/request/add-ticket.ts index d27991a..1c890fb 100644 --- a/source/ticketUI/src/models/request/add-ticket.ts +++ b/source/ticketUI/src/models/request/add-ticket.ts @@ -1,6 +1,9 @@ import {TicketTypeEnum} from '../enums/ticket-type.enum'; +import {Patron} from '../core/patron'; export interface AddTicket { - ticketType: TicketTypeEnum, - eventId: string + type: TicketTypeEnum, + eventId: string, + seasonId: string | null, + patron: Patron, } diff --git a/source/ticketUI/src/models/response/ticket-search.ts b/source/ticketUI/src/models/response/ticket-search.ts index 78de130..b5752f8 100644 --- a/source/ticketUI/src/models/response/ticket-search.ts +++ b/source/ticketUI/src/models/response/ticket-search.ts @@ -2,6 +2,6 @@ import {TicketTypeEnum} from '../enums/ticket-type.enum'; import {TicketValidity} from '../enums/ticket-validity.enum'; export interface TicketSearch { - ticketType: TicketTypeEnum, - ticketValidity: TicketValidity + type: TicketTypeEnum, + validity: TicketValidity } diff --git a/source/ticketUI/src/styles.scss b/source/ticketUI/src/styles.scss index 46eecad..5105936 100644 --- a/source/ticketUI/src/styles.scss +++ b/source/ticketUI/src/styles.scss @@ -18,6 +18,10 @@ body { &-large { width: 250px; } + + &-fit-parent { + width: auto; + } } .button { @@ -39,18 +43,59 @@ body { } } +.select { + padding: 5px; + backdrop-filter: blur(25px) saturate(112%); + -webkit-backdrop-filter: blur(25px) saturate(112%); + background-color: rgba(255, 255, 255, 0.11); + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.125); + width: auto; + + &:hover { + background-color: rgba(255, 255, 255, 0.0); + } +} + +.input { + padding: 5px; + backdrop-filter: blur(25px) saturate(112%); + -webkit-backdrop-filter: blur(25px) saturate(112%); + background-color: rgba(255, 255, 255, 0.11); + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.125); + width: auto; + + &:hover { + background-color: rgba(255, 255, 255, 0.0); + } +} + +.label { + padding-right: 15px; +} + .row { display: flex; flex-direction: row; justify-content: center; + align-items: baseline; &-space-between { justify-content: space-between; } + + &-bottom-margin { + margin-bottom: 10px; + } } .column { display: flex; flex-direction: column; justify-content: center; + + &-space-between { + justify-content: space-between; + } }