Compare commits
3 Commits
main
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
| a98b05f14b | |||
| 903e562e42 | |||
|
|
50efe0f310 |
|
|
@ -1,31 +0,0 @@
|
|||
name: Build
|
||||
run-name: ${{gitea.actor}} is building 🚀
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
BuildUI:
|
||||
runs-on: osx
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Restoring Node Packages
|
||||
run: |
|
||||
cd source
|
||||
cd ticketUI
|
||||
yarn install --frozen-lockfile
|
||||
- name: Build
|
||||
run: |
|
||||
cd source
|
||||
cd ticketUI
|
||||
yarn run build
|
||||
BuildAPI:
|
||||
runs-on: osx
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setting up .Net CLI
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
- name: Build API
|
||||
run: dotnet build ./source/ticketAPI/ticketAPI.sln
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
name: Deploy
|
||||
run-name: ${{gitea.actor}} is deploying 🚀
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
BuildUI:
|
||||
runs-on: osx
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Restoring Node Packages
|
||||
run: |
|
||||
cd source
|
||||
cd ticketUI
|
||||
yarn install --frozen-lockfile
|
||||
- name: Build
|
||||
run: |
|
||||
cd source
|
||||
cd ticketUI
|
||||
yarn run build
|
||||
- name: Saving build artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ticketUI
|
||||
path: source/ticketUI/dist/ticket-ui
|
||||
BuildAPI:
|
||||
runs-on: osx
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setting up .Net CLI
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
- name: Build API
|
||||
run: dotnet publish -c release -o artifacts/api /p:DebugType=None /p:DebugSymbols=false ./source/ticketAPI/ticketAPI.sln
|
||||
- name: Saving build artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ticketAPI
|
||||
path: artifacts/api
|
||||
PublishUI:
|
||||
runs-on: osx
|
||||
needs: [BuildUI, BuildAPI]
|
||||
name: Publish UI Docker Image
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Getting Artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ticketUI
|
||||
path: source/ticketUI/dist/ticket-ui
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: source/ticketUI/Dockerfile
|
||||
push: true
|
||||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/ticket-ui:${{ github.ref_name }}
|
||||
PublishAPI:
|
||||
runs-on: osx
|
||||
needs: [BuildAPI, PublishUI]
|
||||
name: Publish API Docker Image
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Getting Artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ticketAPI
|
||||
path: artifacts/api
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: source/ticketAPI/Dockerfile
|
||||
push: true
|
||||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/ticket-api:${{ github.ref_name }}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -47,5 +47,3 @@ testem.log
|
|||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
source/ticketAPI/api/appsettings.Development.json
|
||||
source/ticketAPI/api/appsettings.json
|
||||
|
|
|
|||
|
|
@ -2,61 +2,38 @@
|
|||
|
||||
```mermaid
|
||||
classDiagram
|
||||
Ticket
|
||||
Event
|
||||
Patron
|
||||
Season
|
||||
Talent
|
||||
Ticket
|
||||
Venue
|
||||
|
||||
Event : Guid Id
|
||||
Event : Guid SeasonId
|
||||
Event : Date Date
|
||||
Event : String Name
|
||||
Event : String? Description
|
||||
Event : Object Venue
|
||||
Event : Object Talent
|
||||
Event : Array TicketIds
|
||||
|
||||
Patron : String FirstName
|
||||
Patron : String? MiddleName
|
||||
Patron : String LastName
|
||||
Patron : String Email
|
||||
Patron : String? PhoneNumber
|
||||
Patron : String AddressOne
|
||||
Patron : String? AddressTwo
|
||||
Patron : String City
|
||||
Patron : String State
|
||||
Patron : String Zip
|
||||
|
||||
Season : Guid Id
|
||||
Season : String Name
|
||||
Season : String? Description
|
||||
Season : Date StartDate
|
||||
Season : Date EndDate
|
||||
Season : Array EventIds
|
||||
|
||||
Talent : String Name
|
||||
Talent : String? Description
|
||||
Address
|
||||
Order
|
||||
|
||||
Ticket : Guid Id
|
||||
Ticket : Guid? SeasonId
|
||||
Ticket : Guid EventId
|
||||
Ticket : TicketType Type
|
||||
Ticket : String QrCode
|
||||
Ticket : Object Patron
|
||||
Ticket : int Seats
|
||||
Ticket : DateTime Date
|
||||
Ticket : Patron Patron
|
||||
|
||||
Venue : String Name
|
||||
Venue : String? Description
|
||||
Venue : String AddressOne
|
||||
Venue : String? AddressTwo
|
||||
Venue : String City
|
||||
Venue : String State
|
||||
Venue : String Zip
|
||||
Event : Guid Id
|
||||
Event : String Title
|
||||
Event : String Description
|
||||
Event : DateTime Date
|
||||
Event : Array Tickets
|
||||
|
||||
Patron --* Ticket
|
||||
Patron : Guid Id
|
||||
Patron : String EmailAddress
|
||||
Patron : String PhoneNumber
|
||||
Patron : Address Address
|
||||
|
||||
Venue --* Event
|
||||
Talent --* Event
|
||||
Address : Guid Id
|
||||
Address : String StreetAddressOne
|
||||
Address : String StreetAddressTwo
|
||||
Address : String City
|
||||
Address : String State
|
||||
Address : String ZipCode
|
||||
|
||||
Order : Guid Id
|
||||
Order : Patron Patron
|
||||
Order : Array Tickets
|
||||
|
||||
Event o-- Ticket : X Tickets
|
||||
```
|
||||
|
|
|
|||
12
diagrams/order-lookup.md
Normal file
12
diagrams/order-lookup.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Order Lookup
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
UI->>API: Order Id
|
||||
API->>DB: Order Id
|
||||
DB->>API: Order Returned
|
||||
API->>UI: Order Details Returned
|
||||
```
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
# Ticket Generation
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
UI ->> API: Print Ticket Request
|
||||
API ->> API: Generate Ticket Id
|
||||
API ->> API: Generate Qr Code
|
||||
API ->> DB: Save Ticket
|
||||
API ->> DB: Associate Ticket with Event
|
||||
API ->> API: Build Ticket Data for UI
|
||||
API ->> UI: Respond with Ticket
|
||||
UI ->> UI: Builds Visual Ticket
|
||||
```
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# Ticket Lookup
|
||||
|
||||
## Happy Path
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
|
||||
UI ->> UI: Decode QrCode
|
||||
UI ->> API: Send TicketId from QrCode
|
||||
API ->> DB: Query Ticket
|
||||
DB -->> API: Ticket Returned, if found
|
||||
API ->> DB: Query Event from Ticket
|
||||
DB -->> API: Event Information Returned
|
||||
API ->> API: Check for Ticket Validity
|
||||
API ->> UI: Return Ticket Validity
|
||||
```
|
||||
|
||||
## No Ticket Found
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
|
||||
UI ->> UI: Decode QrCode
|
||||
UI ->> API: Send TicketId from QrCode
|
||||
API ->> DB: Query Ticket
|
||||
DB -->> API: None Found
|
||||
API ->> UI: Ticket Not Found
|
||||
```
|
||||
14
diagrams/ticket-minting.md
Normal file
14
diagrams/ticket-minting.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Ticket Minting
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
UI->>API: Mint Ticket(s) Request
|
||||
API->>DB: Get Ticket Ids
|
||||
DB->>DB: IDs Assigned
|
||||
DB->>API: IDs Returned
|
||||
API->>API: QR Codes Generated
|
||||
API->>UI: Code Returned, Email Sent
|
||||
```
|
||||
29
diagrams/ticket-verification.md
Normal file
29
diagrams/ticket-verification.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Ticket Verification
|
||||
|
||||
## Happy Path
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
|
||||
UI ->> API: Decoded Ticket Id from QR Code
|
||||
API ->> DB: Query DB with Id
|
||||
DB ->> API: Found Ticket Info
|
||||
API ->> UI: Tickets Found, Admit X Seats
|
||||
```
|
||||
|
||||
## Negative Path
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI
|
||||
participant API
|
||||
participant DB
|
||||
|
||||
UI ->> API: Decoded Ticket Id from QR Code
|
||||
API ->> DB: Query DB with Id
|
||||
DB ->> API: None Found
|
||||
API ->> UI: Ticket Not Found
|
||||
```
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# Ticket Validity Check
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
|
||||
start([Ticket Found, Event Found])
|
||||
eventDateIsToday(Checks if Event Date is Today)
|
||||
todayIsAfterEvent(Checks if Event was before Today)
|
||||
twoHoursEarly(Checks if its less than 2 hours to event start)
|
||||
fiveHoursAgo(Checks if Event started less than 5 hours ago)
|
||||
returnsInvalid([Ticket is Invalid])
|
||||
returnsExpired([Ticket is Expired])
|
||||
returnsExpired2([Ticket is Expired])
|
||||
returnsEarly([Ticket is Early])
|
||||
returnsValid([Ticket is Valid])
|
||||
|
||||
start --> eventDateIsToday -- yes --- todayIsAfterEvent
|
||||
eventDateIsToday -- no --- returnsInvalid
|
||||
|
||||
todayIsAfterEvent -- yes --- returnsExpired2
|
||||
|
||||
todayIsAfterEvent --> twoHoursEarly -- no --- returnsEarly
|
||||
twoHoursEarly -- yes --- fiveHoursAgo
|
||||
fiveHoursAgo -- yes --- returnsValid
|
||||
fiveHoursAgo -- no --- returnsExpired
|
||||
```
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
FROM mcr.microsoft.com/dotnet/aspnet:9.0
|
||||
COPY ../../artifacts/api /app
|
||||
COPY artifacts /app
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["dotnet", "api.dll"]
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB |
|
|
@ -56,16 +56,15 @@ public class EventController(IEventManager eventManager) : ControllerBase
|
|||
/// </summary>
|
||||
/// <param name="startDate">Start date for the event search</param>
|
||||
/// <param name="endDate">End date for the event search</param>
|
||||
/// <param name="seasonId">Season to find events for</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public ActionResult<List<Event>> Get(DateTime? startDate, DateTime? endDate, string? seasonId)
|
||||
public ActionResult<List<Event>> Get(DateTime? startDate, DateTime? endDate)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (startDate == null && endDate == null)
|
||||
{
|
||||
return Ok(seasonId == null ? eventManager.GetAllEvents() : eventManager.GetBySeason(new Guid(seasonId)));
|
||||
return Ok(eventManager.GetAllEvents());
|
||||
}
|
||||
return Ok(eventManager.GetEvents(startDate, endDate));
|
||||
}
|
||||
|
|
@ -74,24 +73,4 @@ public class EventController(IEventManager eventManager) : ControllerBase
|
|||
return BadRequest(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an event
|
||||
/// </summary>
|
||||
/// <param name="eventId">Event to delete</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public IActionResult Delete(Guid eventId)
|
||||
{
|
||||
// TODO: Protect Endpoint
|
||||
try
|
||||
{
|
||||
eventManager.DeleteEvent(eventId);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return BadRequest(e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,39 +53,18 @@ public class SeasonController(ISeasonManager seasonManager) : ControllerBase
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a season
|
||||
/// Adds an event to a season
|
||||
/// </summary>
|
||||
/// <param name="request">Updated season information</param>
|
||||
/// <param name="seasonId">Season Id</param>
|
||||
/// <param name="eventId">Event Id</param>
|
||||
/// <returns></returns>
|
||||
[HttpPatch]
|
||||
public IActionResult Patch(PatchSeason request)
|
||||
[HttpPut]
|
||||
public IActionResult Put(Guid eventId, Guid seasonId)
|
||||
{
|
||||
//TODO: Protect Endpoint
|
||||
|
||||
try
|
||||
{
|
||||
seasonManager.PatchSeason(request);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return BadRequest(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a season
|
||||
/// </summary>
|
||||
/// <param name="seasonId">SeasonId to delete</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public IActionResult Delete(Guid seasonId)
|
||||
{
|
||||
//TODO: Protect Endpoint
|
||||
|
||||
try
|
||||
{
|
||||
seasonManager.DeleteSeason(seasonId);
|
||||
seasonManager.AddEventToSeason(eventId, seasonId);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
|||
|
|
@ -56,11 +56,6 @@ public class TicketController(
|
|||
Details = eventManager.GetEvent(ticket.EventId)
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(ticket.Patron.Email))
|
||||
{
|
||||
//TODO: Hookup Email Service
|
||||
}
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,5 @@ public static class ServiceCollectionExtensions
|
|||
services.AddScoped<ITicketManager, TicketManager>();
|
||||
services.AddScoped<IEventManager, EventManager>();
|
||||
services.AddScoped<ISeasonManager, SeasonManager>();
|
||||
services.AddScoped<IEmailService, EmailService>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
using models.Core;
|
||||
using models.Response;
|
||||
|
||||
namespace api.Interfaces;
|
||||
|
||||
public interface IEmailService
|
||||
{
|
||||
void SendEmail(Ticket ticket, EventDetails details);
|
||||
}
|
||||
|
|
@ -11,6 +11,4 @@ public interface IEventManager
|
|||
List<Event> GetEvents(DateTime? startDate, DateTime? endDate);
|
||||
List<Event> GetAllEvents();
|
||||
EventDetails GetEvent(Guid id);
|
||||
void DeleteEvent(Guid eventId);
|
||||
List<Event> GetBySeason(Guid seasonId);
|
||||
}
|
||||
|
|
@ -7,6 +7,5 @@ public interface ISeasonManager
|
|||
{
|
||||
void AddSeason(AddSeason season);
|
||||
List<Season> GetSeasons();
|
||||
void PatchSeason(PatchSeason request);
|
||||
void DeleteSeason(Guid seasonId);
|
||||
void AddEventToSeason(Guid eventId, Guid seasonId);
|
||||
}
|
||||
|
|
@ -62,10 +62,4 @@ Content-Type: application/json
|
|||
|
||||
GET {{api_HostAddress}}/event
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
GET {{api_HostAddress}}/event?seasonId={{seasonId}}
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
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 ?? string.Empty);
|
||||
|
||||
if (from.Address != config.GetSection("Email:From").Value)
|
||||
{
|
||||
throw new Exception("Invalid email address");
|
||||
}
|
||||
|
||||
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($"<div #ticket style=\"{cardStyle} {columnStyle}\">");
|
||||
|
||||
sb.AppendLine($"<div #talentLogo style=\"{cardStyle} {rowStyle}\">");
|
||||
sb.AppendLine($"<img src=\"{imagePath}\" width=\"250\" height=\"100\" alt=\"Parma Symphony Orchestra Logo\"/>");
|
||||
sb.AppendLine("</div>"); //closes #talentLogo
|
||||
|
||||
sb.AppendLine($"<div #qrCode style=\"{rowStyle}\">");
|
||||
sb.AppendLine($"<img style=\"{qrCodeStyle}\" alt=\"QR Code\" src=\"data:image/png;base64,{ticket.QrCode}\"/>");
|
||||
sb.AppendLine("</div>"); //closes #qrCode
|
||||
|
||||
sb.AppendLine($"<div #venue style=\"{rowStyle}\">");
|
||||
sb.AppendLine($"<div style=\"{cardStyle}\">");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Talent.Name}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Name}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Description}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Date.ToString("F")}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Venue.Name}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Venue.Description}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Venue.AddressOne}</span>");
|
||||
sb.AppendLine($"<span style=\"{rowStyle}\">{@event.Venue.City} {@event.Venue.State} {@event.Venue.Zip}</span>");
|
||||
sb.AppendLine("</div>"); //closes #venue nested card
|
||||
sb.AppendLine("</div>"); //closes #venue
|
||||
|
||||
sb.AppendLine("</div>"); //closes #ticket
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ public class EventManager : IEventManager
|
|||
};
|
||||
|
||||
new Save().Execute(@event);
|
||||
new data.Seasons.AddEvent().Execute(@event.Id, request.SeasonId);
|
||||
}
|
||||
|
||||
public void PatchEvent(PatchEvent request)
|
||||
|
|
@ -43,14 +44,4 @@ public class EventManager : IEventManager
|
|||
{
|
||||
return new GetDetails().Execute(id);
|
||||
}
|
||||
|
||||
public void DeleteEvent(Guid eventId)
|
||||
{
|
||||
new Delete().Execute(eventId);
|
||||
}
|
||||
|
||||
public List<Event> GetBySeason(Guid seasonId)
|
||||
{
|
||||
return new GetBySeason().Execute(seasonId);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using api.Interfaces;
|
|||
using data.Seasons;
|
||||
using models.Core;
|
||||
using models.Request;
|
||||
using AddEvent = data.Seasons.AddEvent;
|
||||
|
||||
namespace api.Services;
|
||||
|
||||
|
|
@ -26,13 +27,8 @@ public class SeasonManager : ISeasonManager
|
|||
return new GetAll().Execute();
|
||||
}
|
||||
|
||||
public void PatchSeason(PatchSeason request)
|
||||
public void AddEventToSeason(Guid eventId, Guid seasonId)
|
||||
{
|
||||
new Update().Execute(request);
|
||||
}
|
||||
|
||||
public void DeleteSeason(Guid seasonId)
|
||||
{
|
||||
new Delete().Execute(seasonId);
|
||||
new AddEvent().Execute(eventId, seasonId);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ public class TicketManager : ITicketManager
|
|||
public void SaveMintedTicket(Ticket ticket)
|
||||
{
|
||||
new data.Tickets.Save().Execute(ticket);
|
||||
new data.Events.AddTicket().Execute(ticket.Id, ticket.EventId);
|
||||
}
|
||||
|
||||
public TicketSearch SearchTicket(Guid ticketId)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,4 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Assets\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@ using MongoDB.Driver;
|
|||
|
||||
namespace data.Events;
|
||||
|
||||
public class Delete
|
||||
public class AddTicket
|
||||
{
|
||||
public void Execute(Guid eventId)
|
||||
public void Execute(Guid ticketId, Guid eventId)
|
||||
{
|
||||
var database = MongoFactory.GetDatabase();
|
||||
var filter = Builders<Event>.Filter.Eq(e => e.Id, eventId);
|
||||
var collection = database.GetCollection<Event>("events");
|
||||
var filter = Builders<Event>.Filter.Eq(e => e.Id, eventId);
|
||||
|
||||
collection.DeleteOne(filter);
|
||||
var update = Builders<Event>.Update.Push("TicketIds", ticketId);
|
||||
|
||||
collection.FindOneAndUpdate(filter, update);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ public class Find
|
|||
{
|
||||
var database = MongoFactory.GetDatabase();
|
||||
var collection = database.GetCollection<Event>("events");
|
||||
var filter = Builders<Event>.Filter.Eq(e => e.Id, eventId);
|
||||
var filter = Builders<Event>.Filter.Eq("Id", eventId);
|
||||
return collection.Find(filter).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
using models.Core;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace data.Events;
|
||||
|
||||
public class GetBySeason
|
||||
{
|
||||
public List<Event> Execute(Guid seasonId)
|
||||
{
|
||||
var database = MongoFactory.GetDatabase();
|
||||
var collection = database.GetCollection<Event>("events");
|
||||
var filter = Builders<Event>.Filter.Eq(e => e.SeasonId, seasonId);
|
||||
|
||||
return collection.Find(filter).ToList();
|
||||
}
|
||||
}
|
||||
|
|
@ -6,24 +6,23 @@ namespace data.Events;
|
|||
|
||||
public class Update
|
||||
{
|
||||
public void Execute(PatchEvent request)
|
||||
public bool Execute(PatchEvent request)
|
||||
{
|
||||
var database = MongoFactory.GetDatabase();
|
||||
var collection = database.GetCollection<Event>("events");
|
||||
|
||||
var filter = Builders<Event>.Filter.Eq(e => e.Id, request.Id);
|
||||
var filter = Builders<Event>.Filter.Eq("_id", request.Id);
|
||||
|
||||
var newEvent = new Event
|
||||
{
|
||||
Id = request.Id,
|
||||
SeasonId = request.SeasonId,
|
||||
Date = request.Date,
|
||||
Name = request.Name,
|
||||
Description = request.Description,
|
||||
Venue = request.Venue,
|
||||
Talent = request.Talent,
|
||||
};
|
||||
|
||||
collection.ReplaceOne(filter, newEvent);
|
||||
|
||||
return collection.ReplaceOne(filter, newEvent).IsAcknowledged;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,16 @@ using MongoDB.Driver;
|
|||
|
||||
namespace data.Seasons;
|
||||
|
||||
public class Delete
|
||||
public class AddEvent
|
||||
{
|
||||
public void Execute(Guid seasonId)
|
||||
public void Execute(Guid eventId, Guid seasonId)
|
||||
{
|
||||
var database = MongoFactory.GetDatabase();
|
||||
var filter = Builders<Season>.Filter.Eq(s => s.Id, seasonId);
|
||||
var collection = database.GetCollection<Season>("seasons");
|
||||
var filter = Builders<Season>.Filter.Eq(s => s.Id, seasonId);
|
||||
|
||||
collection.DeleteOne(filter);
|
||||
var update = Builders<Season>.Update.Push("EventIds", eventId);
|
||||
|
||||
collection.FindOneAndUpdate(filter, update);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
using models.Core;
|
||||
using models.Request;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace data.Seasons;
|
||||
|
||||
public class Update
|
||||
{
|
||||
public void Execute(PatchSeason request)
|
||||
{
|
||||
var database = MongoFactory.GetDatabase();
|
||||
var collection = database.GetCollection<Season>("seasons");
|
||||
|
||||
var filter = Builders<Season>.Filter.Eq(s => s.Id, request.Id);
|
||||
|
||||
var newSeason = new Season
|
||||
{
|
||||
Id = request.Id,
|
||||
Name = request.Name,
|
||||
Description = request.Description,
|
||||
StartDate = request.StartDate,
|
||||
EndDate = request.EndDate,
|
||||
};
|
||||
|
||||
collection.ReplaceOne(filter, newSeason);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,4 +9,5 @@ public class Event
|
|||
public string? Description { get; set; }
|
||||
public required Venue Venue { get; set; }
|
||||
public required Talent Talent { get; set; }
|
||||
public List<Guid> TicketIds { get; set; } = [];
|
||||
}
|
||||
|
|
@ -7,4 +7,5 @@ public class Season
|
|||
public string? Description { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public List<Guid> EventIds { get; set; } = [];
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ namespace models.Request;
|
|||
public class PatchEvent
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid SeasonId { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public required string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
namespace models.Request;
|
||||
|
||||
public class PatchSeason
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
FROM nginx:latest
|
||||
COPY source/ticketUI/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY source/ticketUI/dist/ticket-ui /usr/share/nginx/html
|
||||
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY dist/ticket-ui /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ticket-ui",
|
||||
"version": "0.0.0",
|
||||
"version": "2024.12.11",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export class EventBrowserComponent implements OnInit {
|
|||
public selectedEventId$: WritableSignal<string> = signal('');
|
||||
|
||||
public ngOnInit() {
|
||||
this.eventService.searchEvents(undefined, undefined, undefined);
|
||||
this.eventService.searchAllEvents();
|
||||
}
|
||||
|
||||
public click(eventId: string): void {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@
|
|||
</div>
|
||||
<div class="row row-space-between row-bottom-margin">
|
||||
<label class="label" for="email">Email</label>
|
||||
<input id="email" [formControl]="email" type="email" class="input"
|
||||
[ngClass]="{'invalid': email.invalid && email.dirty}"/>
|
||||
<input id="email" [formControl]="email" type="text" class="input"/>
|
||||
</div>
|
||||
<div class="row row-space-between row-bottom-margin">
|
||||
<label class="label" for="phoneNumber">Phone</label>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
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,
|
||||
NgClass
|
||||
ReactiveFormsModule
|
||||
],
|
||||
templateUrl: './patron-info.component.html',
|
||||
styleUrl: './patron-info.component.scss'
|
||||
|
|
@ -16,9 +14,7 @@ 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, Validators.email]
|
||||
});
|
||||
public email = new FormControl('', {nonNullable: true, validators: [Validators.required]});
|
||||
public phoneNumber = new FormControl('');
|
||||
public addressOne = new FormControl('', {nonNullable: true, validators: [Validators.required]});
|
||||
public addressTwo = new FormControl('');
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
<div [ngClass]="{'row': ticket$() !== null}">
|
||||
<div class="card">
|
||||
<h3>Generate Tickets</h3>
|
||||
<div class="column">
|
||||
<app-ticket-type-selector #ticketType></app-ticket-type-selector>
|
||||
<app-event-browser />
|
||||
@if(IsSeasonTicket(ticketType.selectedTicketType$())) {
|
||||
<app-season-browser />
|
||||
}
|
||||
<app-patron-info />
|
||||
</div>
|
||||
<button class="button" (click)="saveTicket()">Save Ticket</button>
|
||||
<div class="card">
|
||||
<h3>Generate Tickets</h3>
|
||||
<div class="column">
|
||||
<app-ticket-type-selector #ticketType></app-ticket-type-selector>
|
||||
<app-event-browser />
|
||||
@if(IsSeasonTicket(ticketType.selectedTicketType$())) {
|
||||
<app-season-browser />
|
||||
}
|
||||
<app-patron-info />
|
||||
</div>
|
||||
|
||||
@if(ticket$() !== null) {
|
||||
<app-generated-ticket />
|
||||
}
|
||||
<button class="button" (click)="saveTicket()">Save Ticket</button>
|
||||
</div>
|
||||
|
||||
@if(ticket$() !== null) {
|
||||
<app-generated-ticket />
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ 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',
|
||||
|
|
@ -18,8 +16,7 @@ import {NgClass} from '@angular/common';
|
|||
TicketTypeSelectorComponent,
|
||||
PatronInfoComponent,
|
||||
SeasonBrowserComponent,
|
||||
GeneratedTicketComponent,
|
||||
NgClass
|
||||
GeneratedTicketComponent
|
||||
],
|
||||
templateUrl: './ticket.component.html',
|
||||
styleUrl: './ticket.component.scss'
|
||||
|
|
@ -31,15 +28,9 @@ 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,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,31 @@
|
|||
import {HttpHeaders} from '@angular/common/http';
|
||||
import {HttpHeaders, HttpParams} from '@angular/common/http';
|
||||
|
||||
export class ApiUtils {
|
||||
protected setHttpRequestOptions(): any {
|
||||
protected setHttpRequestOptions(params?: any): any {
|
||||
let headers: HttpHeaders = new HttpHeaders();
|
||||
headers = headers.set('Content-Type', 'application/json');
|
||||
|
||||
return {
|
||||
const options: any = {
|
||||
headers,
|
||||
observe: 'response'
|
||||
};
|
||||
|
||||
if (params) {
|
||||
options.params = this.setHttpParams(params);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private setHttpParams(query: object): HttpParams {
|
||||
const params = new HttpParams();
|
||||
for (const key in query) {
|
||||
// @ts-ignore
|
||||
if (query[key] && query.hasOwnProperty(key)) {
|
||||
// @ts-ignore
|
||||
params.append(key, query[key]);
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {Endpoints} from '../../models/endpoints';
|
|||
import {catchError, map, of} from 'rxjs';
|
||||
import {SnackbarService} from './snackbar.service';
|
||||
import {Event} from '../../models/core/event';
|
||||
import {PatchEvent} from '../../models/request/patch-event';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
|
@ -22,6 +21,7 @@ export class EventService extends ApiUtils {
|
|||
}
|
||||
|
||||
public addEvent(request: AddEventRequest): void {
|
||||
//TODO: Remove hard coded venue and talent information
|
||||
const options = this.setHttpRequestOptions();
|
||||
const url = environment.apiBase + Endpoints.EVENT;
|
||||
|
||||
|
|
@ -34,30 +34,14 @@ export class EventService extends ApiUtils {
|
|||
).subscribe(res => {
|
||||
if(res !== null) {
|
||||
this.snackbar.showMessage('Event added successfully.');
|
||||
this.searchEvents(undefined, undefined, undefined);
|
||||
this.searchAllEvents();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for events, returns all events if parameters are not provided
|
||||
* @param startDate If provided with an end date, will search in the date range
|
||||
* @param endDate If provided with a start date, will search in the date range
|
||||
* @param seasonId If provided, returns all events for a season
|
||||
*/
|
||||
public searchEvents(startDate: Date | undefined,
|
||||
endDate: Date | undefined,
|
||||
seasonId: string | undefined): void {
|
||||
public searchAllEvents(): void {
|
||||
const options = this.setHttpRequestOptions();
|
||||
let url: string = '';
|
||||
|
||||
if (startDate && endDate) {
|
||||
url = environment.apiBase + Endpoints.EVENT_DATE_SEARCH(startDate, endDate);
|
||||
} else if (seasonId) {
|
||||
url = environment.apiBase + Endpoints.EVENT_SEASON_SEARCH(seasonId);
|
||||
} else {
|
||||
url = environment.apiBase + Endpoints.EVENT;
|
||||
}
|
||||
const url = environment.apiBase + Endpoints.EVENT;
|
||||
|
||||
this.httpClient.get(url, options)
|
||||
.pipe(
|
||||
|
|
@ -67,47 +51,23 @@ export class EventService extends ApiUtils {
|
|||
return of(undefined);
|
||||
})
|
||||
).subscribe(res => {
|
||||
if(res !== null) {
|
||||
this.events$.set(res);
|
||||
} else {
|
||||
this.snackbar.showError('No events found.');
|
||||
}
|
||||
this.events$.set(res);
|
||||
});
|
||||
}
|
||||
|
||||
public updateEvent(request: PatchEvent): void {
|
||||
public searchEvents(startDate: Date, endDate: Date): void {
|
||||
const options = this.setHttpRequestOptions();
|
||||
const url = environment.apiBase + Endpoints.EVENT;
|
||||
const url = environment.apiBase + Endpoints.EVENT_DATE_SEARCH(startDate, endDate);
|
||||
|
||||
this.httpClient.patch(url, JSON.stringify(request), options)
|
||||
this.httpClient.get(url, options)
|
||||
.pipe(
|
||||
map((response: any) => response.body),
|
||||
catchError(error => {
|
||||
this.snackbar.showError(error.error);
|
||||
return of(undefined);
|
||||
})
|
||||
).subscribe(res => {
|
||||
if(res !== null) {
|
||||
this.snackbar.showMessage('Event updated successfully.');
|
||||
this.searchEvents(undefined, undefined, undefined);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public deleteEvent(eventId: string): void {
|
||||
const options = this.setHttpRequestOptions();
|
||||
const url = environment.apiBase + Endpoints.EVENT_DELETE(eventId);
|
||||
|
||||
this.httpClient.delete(url, options)
|
||||
.pipe(
|
||||
catchError(error => {
|
||||
this.snackbar.showError(error.error);
|
||||
return of(undefined);
|
||||
})
|
||||
).subscribe(res => {
|
||||
if(res !== null) {
|
||||
this.snackbar.showMessage('Event deleted successfully.');
|
||||
this.searchEvents(undefined, undefined, undefined);
|
||||
}
|
||||
})
|
||||
this.events$.set(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {environment} from '../../environments/environment';
|
|||
import {Endpoints} from '../../models/endpoints';
|
||||
import {catchError, map, of} from 'rxjs';
|
||||
import {AddSeason} from '../../models/request/add-season';
|
||||
import {PatchSeason} from '../../models/request/patch-season';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
|
@ -40,7 +39,7 @@ export class SeasonService extends ApiUtils {
|
|||
}
|
||||
|
||||
public saveSeason(request: AddSeason): void {
|
||||
const options = this.setHttpRequestOptions();
|
||||
const options = this.setHttpRequestOptions(request);
|
||||
const url = environment.apiBase + Endpoints.SEASON;
|
||||
|
||||
this.httpClient.post(url, JSON.stringify(request), options)
|
||||
|
|
@ -69,40 +68,4 @@ export class SeasonService extends ApiUtils {
|
|||
})
|
||||
).subscribe();
|
||||
}
|
||||
|
||||
public updateSeason(request: PatchSeason): void {
|
||||
const options = this.setHttpRequestOptions();
|
||||
const url = environment.apiBase + Endpoints.SEASON;
|
||||
|
||||
this.httpClient.patch(url, JSON.stringify(request), options)
|
||||
.pipe(
|
||||
catchError(error => {
|
||||
this.snackbar.showError(error.error);
|
||||
return of(undefined);
|
||||
})
|
||||
).subscribe(res => {
|
||||
if (res !== null) {
|
||||
this.snackbar.showMessage('Season updated successfully.');
|
||||
this.getSeasons();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public deleteSeason(seasonId: string): void {
|
||||
const options = this.setHttpRequestOptions();
|
||||
const url = environment.apiBase + Endpoints.SEASON_DELETE(seasonId);
|
||||
|
||||
this.httpClient.delete(url, options)
|
||||
.pipe(
|
||||
catchError(error => {
|
||||
this.snackbar.showError(error.error);
|
||||
return of(undefined);
|
||||
})
|
||||
).subscribe(res => {
|
||||
if (res !== null) {
|
||||
this.snackbar.showMessage('Season deleted successfully.');
|
||||
this.getSeasons();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export const environment = {
|
||||
production: false,
|
||||
apiBase: 'http://localhost:5168/api/',
|
||||
apiBase: 'http://localhost:5168/',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ export interface Event {
|
|||
name: string,
|
||||
description: string | null,
|
||||
venue: Venue,
|
||||
talent: Talent
|
||||
talent: Talent,
|
||||
ticketIds: Array<string>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,14 +22,6 @@ export class Endpoints {
|
|||
return `${Endpoints.EVENT}?startDate=${startDate}&endDate=${endDate}`;
|
||||
}
|
||||
|
||||
public static EVENT_SEASON_SEARCH(seasonId: string): string {
|
||||
return `${Endpoints.EVENT}?seasonId=${seasonId}`;
|
||||
}
|
||||
|
||||
public static EVENT_DELETE(eventId: string): string {
|
||||
return `${Endpoints.EVENT}?eventId=${eventId}`;
|
||||
}
|
||||
|
||||
/* Season Routes */
|
||||
public static readonly SEASON: string = 'season';
|
||||
|
||||
|
|
@ -37,8 +29,4 @@ export class Endpoints {
|
|||
public static SEASON_ADD_EVENT(eventId: string, seasonId: string): string {
|
||||
return `${Endpoints.SEASON}?eventId=${eventId}&seasonId=${seasonId}`;
|
||||
}
|
||||
|
||||
public static SEASON_DELETE(seasonId: string): string {
|
||||
return `${Endpoints.SEASON}?seasonId=${seasonId}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
export interface PatchSeason {
|
||||
id: string,
|
||||
name: string,
|
||||
description: string | null,
|
||||
startDate: Date,
|
||||
endDate: Date
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ body {
|
|||
}
|
||||
|
||||
.input {
|
||||
padding: 7px;
|
||||
padding: 5px;
|
||||
backdrop-filter: blur(25px) saturate(112%);
|
||||
-webkit-backdrop-filter: blur(25px) saturate(112%);
|
||||
background-color: rgba(255, 255, 255, 0.11);
|
||||
|
|
@ -99,7 +99,3 @@ body {
|
|||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border: 2px solid rgba(255, 43, 43, 0.5);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user