From 84431ede36102cf87ca2ed849316cbc0a2b6931d Mon Sep 17 00:00:00 2001 From: Tara Wilson Date: Wed, 18 Dec 2024 15:59:36 -0500 Subject: [PATCH] Adding Emailing Adding Email Verification on Patron Form Addressing #1 - tickets will span next to ticket form --- .gitignore | 2 + source/ticketAPI/api/Assets/pso-logo.png | Bin 0 -> 28915 bytes .../api/Controllers/TicketController.cs | 5 ++ .../api/IServiceCollectionExtensions.cs | 1 + .../ticketAPI/api/Interfaces/IEmailService.cs | 9 +++ source/ticketAPI/api/Services/EmailService.cs | 71 ++++++++++++++++++ source/ticketAPI/api/api.csproj | 4 + .../patron-info/patron-info.component.html | 3 +- .../patron-info/patron-info.component.ts | 8 +- .../src/app/page/ticket/ticket.component.html | 30 ++++---- .../src/app/page/ticket/ticket.component.ts | 11 ++- source/ticketUI/src/styles.scss | 4 + 12 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 source/ticketAPI/api/Assets/pso-logo.png create mode 100644 source/ticketAPI/api/Interfaces/IEmailService.cs create mode 100644 source/ticketAPI/api/Services/EmailService.cs diff --git a/.gitignore b/.gitignore index 56d3edb..9ae288a 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,5 @@ testem.log # System files .DS_Store Thumbs.db +source/ticketAPI/api/appsettings.Development.json +source/ticketAPI/api/appsettings.json diff --git a/source/ticketAPI/api/Assets/pso-logo.png b/source/ticketAPI/api/Assets/pso-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fe4967e3b5b5d5d5f12c4f16cd3ed913de1c9833 GIT binary patch literal 28915 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 literal 0 HcmV?d00001 diff --git a/source/ticketAPI/api/Controllers/TicketController.cs b/source/ticketAPI/api/Controllers/TicketController.cs index 4edaca8..e2a47ac 100644 --- a/source/ticketAPI/api/Controllers/TicketController.cs +++ b/source/ticketAPI/api/Controllers/TicketController.cs @@ -56,6 +56,11 @@ public class TicketController( Details = eventManager.GetEvent(ticket.EventId) }; + if (!string.IsNullOrEmpty(ticket.Patron.Email)) + { + + } + return Ok(response); } catch (Exception e) diff --git a/source/ticketAPI/api/IServiceCollectionExtensions.cs b/source/ticketAPI/api/IServiceCollectionExtensions.cs index 7f49db6..0c9d745 100644 --- a/source/ticketAPI/api/IServiceCollectionExtensions.cs +++ b/source/ticketAPI/api/IServiceCollectionExtensions.cs @@ -11,5 +11,6 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); } } \ No newline at end of file diff --git a/source/ticketAPI/api/Interfaces/IEmailService.cs b/source/ticketAPI/api/Interfaces/IEmailService.cs new file mode 100644 index 0000000..bfda7e6 --- /dev/null +++ b/source/ticketAPI/api/Interfaces/IEmailService.cs @@ -0,0 +1,9 @@ +using models.Core; +using models.Response; + +namespace api.Interfaces; + +public interface IEmailService +{ + void SendEmail(Ticket ticket, EventDetails details); +} \ No newline at end of file diff --git a/source/ticketAPI/api/Services/EmailService.cs b/source/ticketAPI/api/Services/EmailService.cs new file mode 100644 index 0000000..4ba86fc --- /dev/null +++ b/source/ticketAPI/api/Services/EmailService.cs @@ -0,0 +1,71 @@ +using System.Net; +using System.Net.Mail; +using System.Text; +using api.Interfaces; +using models.Core; +using models.Response; + +namespace api.Services; + +public class EmailService(IConfiguration config) : IEmailService +{ + public void SendEmail(Ticket ticket, EventDetails @event) + { + using var client = new SmtpClient(config.GetSection("Email:Server").Value); + + client.UseDefaultCredentials = false; + var auth = new NetworkCredential(config.GetSection("Email:UserName").Value, + config.GetSection("Email:Password").Value); + + client.Credentials = auth; + var from = new MailAddress(config.GetSection("Email:From").Value); + var to = new MailAddress(ticket.Patron.Email); + + var emailMessage = new MailMessage(from, to); + emailMessage.ReplyToList.Add(from); + emailMessage.Subject = $"Tickets - {@event.Name}"; + emailMessage.SubjectEncoding = Encoding.UTF8; + + emailMessage.IsBodyHtml = true; + emailMessage.Body = GenerateTicketBody(ticket, @event); + + client.Send(emailMessage); + } + + private string GenerateTicketBody(Ticket ticket, EventDetails @event) + { + var sb = new StringBuilder(); + const string cardStyle = "margin: 15px; 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: 12px; border: 1px solid rgba(255, 255, 255, 0.125); width: fit-content;"; + const string columnStyle = "display: flex; flex-direction: column; justify-content: center;"; + const string rowStyle = "display: flex; flex-direction: row; justify-content: center; align-items: baseline;"; + const string qrCodeStyle = "height: 150px; width: 150px; padding: 10px;"; + const string imagePath = "Assets/pso-logo.png"; + + sb.AppendLine($"
"); + + sb.AppendLine($"
"); + sb.AppendLine($"\"Parma"); + sb.AppendLine("
"); //closes #talentLogo + + sb.AppendLine($"
"); + sb.AppendLine($"\"QR"); + sb.AppendLine("
"); //closes #qrCode + + sb.AppendLine($"
"); + sb.AppendLine($"
"); + sb.AppendLine($"{@event.Talent.Name}"); + sb.AppendLine($"{@event.Name}"); + sb.AppendLine($"{@event.Description}"); + sb.AppendLine($"{@event.Date.ToString("F")}"); + sb.AppendLine($"{@event.Venue.Name}"); + sb.AppendLine($"{@event.Venue.Description}"); + sb.AppendLine($"{@event.Venue.AddressOne}"); + sb.AppendLine($"{@event.Venue.City} {@event.Venue.State} {@event.Venue.Zip}"); + sb.AppendLine("
"); //closes #venue nested card + sb.AppendLine("
"); //closes #venue + + sb.AppendLine("
"); //closes #ticket + + return sb.ToString(); + } +} \ No newline at end of file diff --git a/source/ticketAPI/api/api.csproj b/source/ticketAPI/api/api.csproj index eef141a..86777b5 100644 --- a/source/ticketAPI/api/api.csproj +++ b/source/ticketAPI/api/api.csproj @@ -21,4 +21,8 @@ + + + + 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 425587d..7aad8ab 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 @@ -15,7 +15,8 @@
- +
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 0ab0c74..32c0127 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,11 +1,13 @@ import {Component} from '@angular/core'; import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms'; import {Patron} from '../../../models/core/patron'; +import {NgClass} from '@angular/common'; @Component({ selector: 'app-patron-info', imports: [ - ReactiveFormsModule + ReactiveFormsModule, + NgClass ], templateUrl: './patron-info.component.html', styleUrl: './patron-info.component.scss' @@ -14,7 +16,9 @@ export class PatronInfoComponent { public firstName = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public middleName = new FormControl(''); public lastName = new FormControl('', {nonNullable: true, validators: [Validators.required]}); - public email = new FormControl('', {nonNullable: true, validators: [Validators.required]}); + public email = new FormControl('', { + nonNullable: true, validators: [Validators.required, Validators.email] + }); public phoneNumber = new FormControl(''); public addressOne = new FormControl('', {nonNullable: true, validators: [Validators.required]}); public addressTwo = new FormControl(''); diff --git a/source/ticketUI/src/app/page/ticket/ticket.component.html b/source/ticketUI/src/app/page/ticket/ticket.component.html index ffc7b0b..e78ac4c 100644 --- a/source/ticketUI/src/app/page/ticket/ticket.component.html +++ b/source/ticketUI/src/app/page/ticket/ticket.component.html @@ -1,16 +1,18 @@ -
-

Generate Tickets

-
- - - @if(IsSeasonTicket(ticketType.selectedTicketType$())) { - - } - +
+
+

Generate Tickets

+
+ + + @if(IsSeasonTicket(ticketType.selectedTicketType$())) { + + } + +
+
- -
-@if(ticket$() !== null) { - -} + @if(ticket$() !== null) { + + } +
diff --git a/source/ticketUI/src/app/page/ticket/ticket.component.ts b/source/ticketUI/src/app/page/ticket/ticket.component.ts index 5be922f..2f85196 100644 --- a/source/ticketUI/src/app/page/ticket/ticket.component.ts +++ b/source/ticketUI/src/app/page/ticket/ticket.component.ts @@ -8,6 +8,8 @@ import {SeasonBrowserComponent} from '../../components/season-browser/season-bro import {IsSeasonTicket} from '../../../models/enums/ticket-type.enum'; import {GeneratedTicketComponent} from '../../components/generated-ticket/generated-ticket.component'; import {Guid} from 'guid-typescript'; +import {SnackbarService} from '../../services/snackbar.service'; +import {NgClass} from '@angular/common'; @Component({ selector: 'app-ticket', @@ -16,7 +18,8 @@ import {Guid} from 'guid-typescript'; TicketTypeSelectorComponent, PatronInfoComponent, SeasonBrowserComponent, - GeneratedTicketComponent + GeneratedTicketComponent, + NgClass ], templateUrl: './ticket.component.html', styleUrl: './ticket.component.scss' @@ -28,9 +31,15 @@ export class TicketComponent { @ViewChild(SeasonBrowserComponent) seasonBrowserComponent!: SeasonBrowserComponent; public ticketService = inject(TicketService); + public snackBar = inject(SnackbarService); public ticket$ = this.ticketService.mintResponse$; public saveTicket(): void { + if(this.patronInfoComponent.email.invalid && this.patronInfoComponent.email.dirty) { + this.snackBar.showMessage("Please enter a valid email address"); + return; + } + const addTicket: AddTicket = { eventId: this.eventBrowserComponent.selectedEventId, type: this.ticketTypeSelector.selectedTicketType, diff --git a/source/ticketUI/src/styles.scss b/source/ticketUI/src/styles.scss index 5105936..c152b24 100644 --- a/source/ticketUI/src/styles.scss +++ b/source/ticketUI/src/styles.scss @@ -99,3 +99,7 @@ body { justify-content: space-between; } } + +.invalid { + border: 1px solid rgba(255, 43, 43, 0.5); +}