diff --git a/source/ticketAPI/api/Controllers/ScanController.cs b/source/ticketAPI/api/Controllers/ScanController.cs new file mode 100644 index 0000000..9d4ddb3 --- /dev/null +++ b/source/ticketAPI/api/Controllers/ScanController.cs @@ -0,0 +1,35 @@ +using api.Interfaces; +using Microsoft.AspNetCore.Mvc; +using models.Response; + +namespace api.Controllers; + +/// +/// Endpoints for Ticket Scanning +/// +/// Injected Ticket Manager Service +[ApiController] +[Route("[controller]")] +public class ScanController(ITicketManager ticketManager) : ControllerBase +{ + /// + /// Searches for a ticket with a given ticketId and validates it against the event associated with it. + /// + /// A string representing a GUID value + /// Ticket Search Result + [HttpGet] + public ActionResult Get(Guid ticketId) + { + //TODO: Protect Endpoint + + try + { + var result = ticketManager.SearchTicket(ticketId); + return Ok(result); + } + catch (Exception e) + { + return BadRequest(e.Message); + } + } +} \ No newline at end of file diff --git a/source/ticketAPI/api/Controllers/TicketController.cs b/source/ticketAPI/api/Controllers/TicketController.cs index 537debe..8270cab 100644 --- a/source/ticketAPI/api/Controllers/TicketController.cs +++ b/source/ticketAPI/api/Controllers/TicketController.cs @@ -62,19 +62,17 @@ public class TicketController( } /// - /// Searches for a ticket with a given ticketId and validates it against the event associated with it. + /// Gets the MintResponse for a saved ticket /// - /// A string representing a GUID value - /// Ticket Search Result + /// Ticket Id + /// [HttpGet] - public ActionResult Get(string ticketId) + public ActionResult Get(Guid ticketId) { - //TODO: Protect Endpoint - try { - var result = ticketManager.SearchTicket(ticketId); - return Ok(result); + var response = ticketManager.GetMintResponse(ticketId); + return Ok(response); } catch (Exception e) { diff --git a/source/ticketAPI/api/Interfaces/ITicketManager.cs b/source/ticketAPI/api/Interfaces/ITicketManager.cs index fc229f9..3264e21 100644 --- a/source/ticketAPI/api/Interfaces/ITicketManager.cs +++ b/source/ticketAPI/api/Interfaces/ITicketManager.cs @@ -7,5 +7,6 @@ public interface ITicketManager { void SaveMintedTicket(Ticket ticket); - TicketSearch SearchTicket(string ticketId); + TicketSearch SearchTicket(Guid ticketId); + MintResponse GetMintResponse(Guid ticketId); } \ No newline at end of file diff --git a/source/ticketAPI/api/RestFiles/scan.http b/source/ticketAPI/api/RestFiles/scan.http new file mode 100644 index 0000000..53961dd --- /dev/null +++ b/source/ticketAPI/api/RestFiles/scan.http @@ -0,0 +1,8 @@ +@api_HostAddress = http://localhost:5168 +@ticketId = fe21c683-b607-4da7-8e9b-76b199a4b76c + +### + +GET {{api_HostAddress}}/scan?ticketId={{ticketId}} +Accept: application/json +Content-Type: application/json \ No newline at end of file diff --git a/source/ticketAPI/api/RestFiles/ticket.http b/source/ticketAPI/api/RestFiles/ticket.http index cf347d9..90d2117 100644 --- a/source/ticketAPI/api/RestFiles/ticket.http +++ b/source/ticketAPI/api/RestFiles/ticket.http @@ -1,5 +1,5 @@ @api_HostAddress = http://localhost:5168 -@ticketId = 59ae05ea-fd07-481a-9a6b-663444cc426d +@ticketId = fe21c683-b607-4da7-8e9b-76b199a4b76c @eventId = b9f4478b-701b-4223-9aaa-042b6f53b83a POST {{api_HostAddress}}/ticket diff --git a/source/ticketAPI/api/Services/TicketManager.cs b/source/ticketAPI/api/Services/TicketManager.cs index f7b9ffd..4832aca 100644 --- a/source/ticketAPI/api/Services/TicketManager.cs +++ b/source/ticketAPI/api/Services/TicketManager.cs @@ -13,7 +13,7 @@ public class TicketManager : ITicketManager new data.Events.AddTicket().Execute(ticket.Id, ticket.EventId); } - public TicketSearch SearchTicket(string ticketId) + public TicketSearch SearchTicket(Guid ticketId) { var ticket = new data.Tickets.Find().Execute(ticketId); @@ -37,6 +37,22 @@ public class TicketManager : ITicketManager return result; } + + public MintResponse GetMintResponse(Guid ticketId) + { + var ticket = new data.Tickets.Find().Execute(ticketId); + + if (ticket == null) + { + throw new Exception("Ticket not found"); + } + + return new MintResponse() + { + QrCode = ticket.QrCode, + Type = ticket.Type, + }; + } private static TicketValidity DetermineValidity(Event @event) { diff --git a/source/ticketAPI/data/Tickets/Find.cs b/source/ticketAPI/data/Tickets/Find.cs index 09afd59..13a963e 100644 --- a/source/ticketAPI/data/Tickets/Find.cs +++ b/source/ticketAPI/data/Tickets/Find.cs @@ -5,11 +5,11 @@ namespace data.Tickets; public class Find { - public Ticket Execute(string ticketId) + public Ticket Execute(Guid ticketId) { var database = MongoFactory.GetDatabase(); var collection = database.GetCollection("tickets"); - var filter = Builders.Filter.Eq("Id", ticketId); + var filter = Builders.Filter.Eq(t => t.Id, ticketId); return collection.Find(filter).FirstOrDefault(); } } \ No newline at end of file diff --git a/source/ticketAPI/models/Response/MintResponse.cs b/source/ticketAPI/models/Response/MintResponse.cs index 1313c28..175f3f0 100644 --- a/source/ticketAPI/models/Response/MintResponse.cs +++ b/source/ticketAPI/models/Response/MintResponse.cs @@ -4,6 +4,6 @@ namespace models.Response; public class MintResponse { - public required string QrCode {get;set;} + public required string QrCode { get; set; } public TicketType Type { get; set; } } \ No newline at end of file diff --git a/source/ticketUI/src/app/page/scan/scan.component.ts b/source/ticketUI/src/app/page/scan/scan.component.ts index 9803faf..6e02164 100644 --- a/source/ticketUI/src/app/page/scan/scan.component.ts +++ b/source/ticketUI/src/app/page/scan/scan.component.ts @@ -1,6 +1,7 @@ -import { Component } from '@angular/core'; +import {Component, inject} from '@angular/core'; import {ZXingScannerModule} from '@zxing/ngx-scanner'; import {ScanResultComponent} from '../../scan-result/scan-result.component'; +import {ScanService} from '../../services/scan.service'; @Component({ selector: 'app-scan', @@ -10,9 +11,11 @@ import {ScanResultComponent} from '../../scan-result/scan-result.component'; }) export class ScanComponent { public hideScanner: boolean = false; + private scan = inject(ScanService); public onCodeResult(resultString: string): void { this.hideScanner = false; + this.scan.searchTicket(resultString); console.log(resultString); } } diff --git a/source/ticketUI/src/app/scan-result/scan-result.component.ts b/source/ticketUI/src/app/scan-result/scan-result.component.ts index 0a9cb97..103acb3 100644 --- a/source/ticketUI/src/app/scan-result/scan-result.component.ts +++ b/source/ticketUI/src/app/scan-result/scan-result.component.ts @@ -1,7 +1,7 @@ import {Component, inject} from '@angular/core'; -import {TicketService} from '../services/ticket.service'; import {TicketValidity} from '../../models/enums/ticket-validity.enum'; import {TicketTypeEnum} from '../../models/enums/ticket-type.enum'; +import {ScanService} from '../services/scan.service'; @Component({ selector: 'app-scan-result', @@ -10,9 +10,9 @@ import {TicketTypeEnum} from '../../models/enums/ticket-type.enum'; styleUrl: './scan-result.component.scss' }) export class ScanResultComponent { - private ticket = inject(TicketService); - public ticketValidity = this.ticket.ticketValid$; - public ticketType = this.ticket.ticketType$; + private scan = inject(ScanService); + public ticketValidity = this.scan.ticketValid$; + public ticketType = this.scan.ticketType$; protected readonly TicketValidity = TicketValidity; protected readonly TicketTypeEnum = TicketTypeEnum; } diff --git a/source/ticketUI/src/app/services/api-utils.ts b/source/ticketUI/src/app/services/api-utils.ts index 6599bde..8416aac 100644 --- a/source/ticketUI/src/app/services/api-utils.ts +++ b/source/ticketUI/src/app/services/api-utils.ts @@ -1,7 +1,7 @@ import {HttpHeaders, HttpParams} from '@angular/common/http'; export class ApiUtils { - public setHttpRequestOptions(params?: any): any { + protected setHttpRequestOptions(params?: any): any { let headers: HttpHeaders = new HttpHeaders(); headers = headers.set('Content-Type', 'application/json'); diff --git a/source/ticketUI/src/app/services/scan.service.ts b/source/ticketUI/src/app/services/scan.service.ts new file mode 100644 index 0000000..e7a15af --- /dev/null +++ b/source/ticketUI/src/app/services/scan.service.ts @@ -0,0 +1,41 @@ +import {inject, Injectable, signal, WritableSignal} from '@angular/core'; +import {TicketValidity} from '../../models/enums/ticket-validity.enum'; +import {TicketTypeEnum} from '../../models/enums/ticket-type.enum'; +import {HttpClient} from '@angular/common/http'; +import {environment} from '../../environments/environment'; +import {Endpoints} from '../../models/endpoints'; +import {TicketSearch} from '../../models/response/ticket-search'; +import {catchError, map, of} from 'rxjs'; +import {ApiUtils} from './api-utils'; + +@Injectable({ + providedIn: 'root' +}) +export class ScanService extends ApiUtils { + public ticketValid$: WritableSignal = signal(TicketValidity.Null); + public ticketType$: WritableSignal = signal(TicketTypeEnum.Null); + private httpClient = inject(HttpClient); + + constructor() { + super(); + } + + public searchTicket(ticketId: string): void { + const options = this.setHttpRequestOptions(); + const url = environment.apiBase + Endpoints.TICKET_SEARCH(ticketId); + + this.httpClient.get(url, options) + .pipe( + map((response: any) => response.body), + catchError(error => { + console.log(error); + return of(undefined); + }) + ).subscribe((res: TicketSearch) => { + if (res !== undefined) { + this.ticketType$.set(res.ticketType); + this.ticketValid$.set(res.ticketValidity) + } + }); + } +} diff --git a/source/ticketUI/src/app/services/ticket.service.ts b/source/ticketUI/src/app/services/ticket.service.ts index 07e0e8e..2d42f0d 100644 --- a/source/ticketUI/src/app/services/ticket.service.ts +++ b/source/ticketUI/src/app/services/ticket.service.ts @@ -6,8 +6,6 @@ import {MintResponse} from '../../models/response/mint-response'; import {Endpoints} from '../../models/endpoints'; import {MintRequest} from '../../models/request/mint-request'; import {ApiUtils} from './api-utils'; -import {TicketValidity} from '../../models/enums/ticket-validity.enum'; -import {TicketTypeEnum} from '../../models/enums/ticket-type.enum'; import {TicketSearch} from '../../models/response/ticket-search'; @Injectable({ @@ -15,8 +13,6 @@ import {TicketSearch} from '../../models/response/ticket-search'; }) export class TicketService extends ApiUtils { public dataSignal$: WritableSignal = signal(''); - public ticketValid$: WritableSignal = signal(TicketValidity.Null); - public ticketType$: WritableSignal = signal(TicketTypeEnum.Null); private httpClient = inject(HttpClient); constructor() { @@ -40,23 +36,4 @@ export class TicketService extends ApiUtils { } }); } - - public searchTicket(ticketId: string): void { - const options = this.setHttpRequestOptions(); - const url = environment.apiBase + Endpoints.TICKET_SEARCH(ticketId); - - this.httpClient.get(url, options) - .pipe( - map((response: any) => response.body), - catchError(error => { - console.log(error); - return of(undefined); - }) - ).subscribe((res: TicketSearch) => { - if (res !== undefined) { - this.ticketType$.set(res.ticketType); - this.ticketValid$.set(res.ticketValidity) - } - }); - } } diff --git a/source/ticketUI/src/models/endpoints.ts b/source/ticketUI/src/models/endpoints.ts index 3dcab34..a1098a9 100644 --- a/source/ticketUI/src/models/endpoints.ts +++ b/source/ticketUI/src/models/endpoints.ts @@ -2,9 +2,16 @@ export class Endpoints { /* Ticket Routes */ public static readonly TICKET: string = 'ticket'; + public static QR_CODE_SEARCH(ticketId: string): string { + return `${Endpoints.TICKET}?ticketId=${ticketId}`; + } + + /* Scan Routes */ + public static readonly SCAN: string = 'scan'; + /* Calculated Routes */ public static TICKET_SEARCH(ticketId: string): string { - return `${Endpoints.TICKET}?ticketId=${ticketId}`; + return `${Endpoints.SCAN}?ticketId=${ticketId}`; } /* Event Routes */