Adding Event Management
Fixing Bugs Building out UI
This commit is contained in:
parent
3bb86da5c0
commit
3a8f2949b2
59
source/ticketAPI/api/Controllers/EventController.cs
Normal file
59
source/ticketAPI/api/Controllers/EventController.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
using api.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using models.Request;
|
||||||
|
|
||||||
|
namespace api.Controllers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Endpoints for Event Management
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventManager"></param>
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class EventController(IEventManager eventManager) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpPost]
|
||||||
|
public ActionResult Post([FromBody] AddEvent request)
|
||||||
|
{
|
||||||
|
//TODO: Protect Endpoint
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
eventManager.AddEvent(request);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return BadRequest(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPatch]
|
||||||
|
public ActionResult Patch([FromBody] PatchEvent request)
|
||||||
|
{
|
||||||
|
//TODO: Protect Endpoint
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
eventManager.PatchEvent(request);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return BadRequest(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{startDate}/{endDate}")]
|
||||||
|
public ActionResult Get([FromRoute] DateTime startDate, DateTime endDate)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Ok(eventManager.GetEvents(startDate, endDate));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return BadRequest(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ using models.Response;
|
||||||
namespace api.Controllers;
|
namespace api.Controllers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Endpoints for Qr Code Generation
|
/// Endpoints for Ticket Management
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="qr">Injected QR Code Service</param>
|
/// <param name="qr">Injected QR Code Service</param>
|
||||||
/// <param name="ticketManager">Injected Ticket Manager Service</param>
|
/// <param name="ticketManager">Injected Ticket Manager Service</param>
|
||||||
|
|
@ -18,38 +18,45 @@ public class TicketController(
|
||||||
ITicketManager ticketManager) : ControllerBase
|
ITicketManager ticketManager) : ControllerBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a Base64 String Qr Code
|
/// Generates a Base64 String Qr Code and Saves Qr Code and Ticket to DB
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Base64 String Qr Code</returns>
|
/// <returns>Base64 String Qr Code</returns>
|
||||||
[HttpPost("mint")]
|
[HttpPost]
|
||||||
public ActionResult<MintResponse> MintTicket([FromBody] MintTickets mintRequest)
|
public ActionResult<MintResponse> AddTicket([FromBody] MintTickets mintRequest)
|
||||||
{
|
{
|
||||||
//TODO: Protect Endpoint
|
//TODO: Protect Endpoint
|
||||||
|
|
||||||
//generate ticket id
|
//generate ticket id
|
||||||
var ticketId = Guid.NewGuid();
|
var ticketId = Guid.NewGuid();
|
||||||
|
|
||||||
//generate the qr code
|
try
|
||||||
var qrCode = qr.GenerateQrCode(ticketId.ToString());
|
|
||||||
|
|
||||||
//build the ticket
|
|
||||||
var ticket = new Ticket
|
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(),
|
//generate the qr code
|
||||||
QrCode = qrCode,
|
var qrCode = qr.GenerateQrCode(ticketId.ToString());
|
||||||
Type = mintRequest.Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
//save the minted ticket
|
//build the ticket
|
||||||
ticketManager.SaveMintedTicket(ticket);
|
var ticket = new Ticket
|
||||||
|
{
|
||||||
|
Id = ticketId,
|
||||||
|
QrCode = qrCode,
|
||||||
|
Type = mintRequest.Type,
|
||||||
|
};
|
||||||
|
|
||||||
//return
|
//save the minted ticket
|
||||||
var response = new MintResponse
|
ticketManager.SaveMintedTicket(ticket);
|
||||||
|
|
||||||
|
//return
|
||||||
|
var response = new MintResponse
|
||||||
|
{
|
||||||
|
QrCode = ticket.QrCode,
|
||||||
|
Type = ticket.Type
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(response);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
QrCode = ticket.QrCode,
|
return BadRequest(e.Message);
|
||||||
Type = ticket.Type
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,5 +9,6 @@ public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
services.AddScoped<IQrCodeGenerator, QrCodeGenerator>();
|
services.AddScoped<IQrCodeGenerator, QrCodeGenerator>();
|
||||||
services.AddScoped<ITicketManager, TicketManager>();
|
services.AddScoped<ITicketManager, TicketManager>();
|
||||||
|
services.AddScoped<IEventManager, EventManager>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
11
source/ticketAPI/api/Interfaces/IEventManager.cs
Normal file
11
source/ticketAPI/api/Interfaces/IEventManager.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using models.Core;
|
||||||
|
using models.Request;
|
||||||
|
|
||||||
|
namespace api.Interfaces;
|
||||||
|
|
||||||
|
public interface IEventManager
|
||||||
|
{
|
||||||
|
void AddEvent(AddEvent request);
|
||||||
|
void PatchEvent(PatchEvent request);
|
||||||
|
List<Event> GetEvents(DateTime startDate, DateTime endDate);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using api;
|
using api;
|
||||||
|
using data;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
|
@ -23,4 +24,8 @@ app.UseHttpsRedirection();
|
||||||
app.UseCors("AllowOrigin");
|
app.UseCors("AllowOrigin");
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
|
//Inject config into Mongo DB Factory
|
||||||
|
MongoFactory.InitConfig(app.Configuration);
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
50
source/ticketAPI/api/RestFiles/event.http
Normal file
50
source/ticketAPI/api/RestFiles/event.http
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
@api_HostAddress = http://localhost:5168
|
||||||
|
|
||||||
|
POST {{api_HostAddress}}/event
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Date": "2024-12-02T15:00:00.991Z",
|
||||||
|
"EventName": "Winter Concert",
|
||||||
|
"EventDescription": "A wintery journey of classical music",
|
||||||
|
"Venue": {
|
||||||
|
"Name": "Valley Forge High School",
|
||||||
|
"Description": "Auditorium",
|
||||||
|
"AddressOne": "9999 Independence Blvd",
|
||||||
|
"AddressTwo": null,
|
||||||
|
"City": "Parma",
|
||||||
|
"State": "Ohio",
|
||||||
|
"Zip": "44130"
|
||||||
|
},
|
||||||
|
"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."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
PATCH {{api_HostAddress}}/Event
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"Id": "1a06c032-b073-4715-9b95-9f3410e7abd9",
|
||||||
|
"Date": "2024-12-03T15:00:00.991Z",
|
||||||
|
"EventName": "Winter Concert",
|
||||||
|
"EventDescription": "A wintery journey of classical music",
|
||||||
|
"Venue": {
|
||||||
|
"Name": "Valley Forge High School",
|
||||||
|
"Description": "Auditorium",
|
||||||
|
"AddressOne": "9999 Independence Blvd",
|
||||||
|
"AddressTwo": null,
|
||||||
|
"City": "Parma",
|
||||||
|
"State": "Ohio",
|
||||||
|
"Zip": "44130"
|
||||||
|
},
|
||||||
|
"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."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
@api_HostAddress = http://localhost:5168
|
@api_HostAddress = http://localhost:5168
|
||||||
|
|
||||||
POST {{api_HostAddress}}/ticket/mint
|
POST {{api_HostAddress}}/ticket
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"ticketType": "Single"
|
"ticketType": "Single"
|
||||||
|
|
|
||||||
34
source/ticketAPI/api/Services/EventManager.cs
Normal file
34
source/ticketAPI/api/Services/EventManager.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using api.Interfaces;
|
||||||
|
using data.Events;
|
||||||
|
using models.Core;
|
||||||
|
using models.Request;
|
||||||
|
|
||||||
|
namespace api.Services;
|
||||||
|
|
||||||
|
public class EventManager : IEventManager
|
||||||
|
{
|
||||||
|
public void AddEvent(AddEvent request)
|
||||||
|
{
|
||||||
|
var @event = new Event
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
EventDescription = request.EventDescription,
|
||||||
|
EventName = request.EventName,
|
||||||
|
Date = request.Date,
|
||||||
|
Talent = request.Talent,
|
||||||
|
Venue = request.Venue
|
||||||
|
};
|
||||||
|
|
||||||
|
new Save().Execute(@event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PatchEvent(PatchEvent request)
|
||||||
|
{
|
||||||
|
new Update().Execute(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Event> GetEvents(DateTime startDate, DateTime endDate)
|
||||||
|
{
|
||||||
|
return new GetInDates().Execute(startDate, endDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,11 +4,10 @@ using models.Core;
|
||||||
|
|
||||||
namespace api.Services;
|
namespace api.Services;
|
||||||
|
|
||||||
public class TicketManager(IConfiguration config) : ITicketManager
|
public class TicketManager : ITicketManager
|
||||||
{
|
{
|
||||||
public void SaveMintedTicket(Ticket ticket)
|
public void SaveMintedTicket(Ticket ticket)
|
||||||
{
|
{
|
||||||
var db = new Save(config);
|
new Save().Execute(ticket);
|
||||||
db.Execute(ticket);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
19
source/ticketAPI/data/Events/GetInDates.cs
Normal file
19
source/ticketAPI/data/Events/GetInDates.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
using models.Core;
|
||||||
|
using models.Request;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace data.Events;
|
||||||
|
|
||||||
|
public class GetInDates
|
||||||
|
{
|
||||||
|
public List<Event> Execute(DateTime startDate, DateTime endDate)
|
||||||
|
{
|
||||||
|
var database = MongoFactory.GetDatabase();
|
||||||
|
var collection = database.GetCollection<Event>("events");
|
||||||
|
|
||||||
|
return collection.Find(x =>
|
||||||
|
startDate <= x.Date
|
||||||
|
&& x.Date <= endDate
|
||||||
|
).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
source/ticketAPI/data/Events/Save.cs
Normal file
14
source/ticketAPI/data/Events/Save.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
using models.Core;
|
||||||
|
|
||||||
|
namespace data.Events;
|
||||||
|
|
||||||
|
public class Save
|
||||||
|
{
|
||||||
|
public void Execute(Event @event)
|
||||||
|
{
|
||||||
|
var database = MongoFactory.GetDatabase();
|
||||||
|
var collection = database.GetCollection<Event>("events");
|
||||||
|
|
||||||
|
collection.InsertOne(@event);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
source/ticketAPI/data/Events/Update.cs
Normal file
28
source/ticketAPI/data/Events/Update.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
using models.Core;
|
||||||
|
using models.Request;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace data.Events;
|
||||||
|
|
||||||
|
public class Update
|
||||||
|
{
|
||||||
|
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 newEvent = new Event
|
||||||
|
{
|
||||||
|
Id = request.Id,
|
||||||
|
Date = request.Date,
|
||||||
|
EventName = request.EventName,
|
||||||
|
EventDescription = request.EventDescription,
|
||||||
|
Venue = request.Venue,
|
||||||
|
Talent = request.Talent,
|
||||||
|
};
|
||||||
|
|
||||||
|
return collection.ReplaceOne(filter, newEvent).IsAcknowledged;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
source/ticketAPI/data/MongoFactory.cs
Normal file
40
source/ticketAPI/data/MongoFactory.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace data;
|
||||||
|
|
||||||
|
public static class MongoFactory
|
||||||
|
{
|
||||||
|
private static IConfiguration? _config;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up the configuration, must be called before using GetDatabase()
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config"></param>
|
||||||
|
public static void InitConfig(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up the connection to Mongo and returns the database from Configuration
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="NullReferenceException"></exception>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static IMongoDatabase GetDatabase()
|
||||||
|
{
|
||||||
|
if (_config == null)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Configuration is not set");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(_config.GetSection("Mongo:ConnectionString").Value))
|
||||||
|
{
|
||||||
|
throw new Exception("No MongoDB connection string");
|
||||||
|
}
|
||||||
|
|
||||||
|
var client = new MongoClient(_config.GetSection("Mongo:ConnectionString").Value);
|
||||||
|
return client.GetDatabase(_config.GetSection("Mongo:Database").Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
source/ticketAPI/data/Tickets/Save.cs
Normal file
14
source/ticketAPI/data/Tickets/Save.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
using models.Core;
|
||||||
|
|
||||||
|
namespace data.Tickets;
|
||||||
|
|
||||||
|
public class Save
|
||||||
|
{
|
||||||
|
public void Execute(Ticket ticket)
|
||||||
|
{
|
||||||
|
var database = MongoFactory.GetDatabase();
|
||||||
|
var collection = database.GetCollection<Ticket>("tickets");
|
||||||
|
|
||||||
|
collection.InsertOne(ticket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using models.Core;
|
|
||||||
using MongoDB.Driver;
|
|
||||||
|
|
||||||
namespace data.Tickets;
|
|
||||||
|
|
||||||
public class Save(IConfiguration config)
|
|
||||||
{
|
|
||||||
public void Execute(Ticket ticket)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty(config.GetSection("Mongo:ConnectionString").Value))
|
|
||||||
{
|
|
||||||
throw new Exception("No MongoDB connection string");
|
|
||||||
}
|
|
||||||
|
|
||||||
var client = new MongoClient(config.GetSection("Mongo:ConnectionString").Value);
|
|
||||||
var database = client.GetDatabase(config.GetSection("Mongo:Database").Value);
|
|
||||||
var collection = database.GetCollection<Ticket>("tickets");
|
|
||||||
|
|
||||||
collection.InsertOne(ticket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,8 +5,6 @@ namespace models.Core;
|
||||||
|
|
||||||
public class Talent
|
public class Talent
|
||||||
{
|
{
|
||||||
[BsonGuidRepresentation(GuidRepresentation.Standard)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
using MongoDB.Bson;
|
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
|
||||||
|
|
||||||
namespace models.Core;
|
namespace models.Core;
|
||||||
|
|
||||||
public class Venue
|
public class Venue
|
||||||
{
|
{
|
||||||
[BsonGuidRepresentation(GuidRepresentation.Standard)]
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public List<string> Address { get; set; } = [];
|
public required string AddressOne { get; set; }
|
||||||
|
public string? AddressTwo { get; set; }
|
||||||
public required string City { get; set; }
|
public required string City { get; set; }
|
||||||
public required string State { get; set; }
|
public required string State { get; set; }
|
||||||
public required string Zip { get; set; }
|
public required string Zip { get; set; }
|
||||||
|
|
|
||||||
12
source/ticketAPI/models/Request/AddEvent.cs
Normal file
12
source/ticketAPI/models/Request/AddEvent.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using models.Core;
|
||||||
|
|
||||||
|
namespace models.Request;
|
||||||
|
|
||||||
|
public class AddEvent
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public required string EventName { get; set; }
|
||||||
|
public string? EventDescription { get; set; }
|
||||||
|
public required Venue Venue { get; set; }
|
||||||
|
public required Talent Talent { get; set; }
|
||||||
|
}
|
||||||
7
source/ticketAPI/models/Request/EventSearch.cs
Normal file
7
source/ticketAPI/models/Request/EventSearch.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace models.Request;
|
||||||
|
|
||||||
|
public class EventSearch
|
||||||
|
{
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
}
|
||||||
13
source/ticketAPI/models/Request/PatchEvent.cs
Normal file
13
source/ticketAPI/models/Request/PatchEvent.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
using models.Core;
|
||||||
|
|
||||||
|
namespace models.Request;
|
||||||
|
|
||||||
|
public class PatchEvent
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public required string EventName { get; set; }
|
||||||
|
public string? EventDescription { get; set; }
|
||||||
|
public required Venue Venue { get; set; }
|
||||||
|
public required Talent Talent { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
<div class="row">
|
<div class="sidenav">
|
||||||
<div class="card">
|
<app-sidebar/>
|
||||||
<app-sidebar />
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<router-outlet />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="main">
|
||||||
|
<router-outlet/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* The sidebar menu */
|
||||||
|
.sidenav {
|
||||||
|
height: 100%; /* Full-height: remove this if you want "auto" height */
|
||||||
|
width: 120px; /* Set the width of the sidebar */
|
||||||
|
position: fixed; /* Fixed Sidebar (stay in place on scroll) */
|
||||||
|
z-index: 1; /* Stay on top */
|
||||||
|
top: 0; /* Stay at the top */
|
||||||
|
left: 0;
|
||||||
|
backdrop-filter: blur(25px) saturate(112%);
|
||||||
|
-webkit-backdrop-filter: blur(25px) saturate(112%);
|
||||||
|
background-color: rgba(255, 255, 255, 0.11);
|
||||||
|
overflow-x: hidden; /* Disable horizontal scroll */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style page content */
|
||||||
|
.main {
|
||||||
|
margin-left: 120px; /* Same as the width of the sidebar */
|
||||||
|
padding: 0px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On smaller screens, where height is less than 450px, change the style of the sidebar (less padding and a smaller font size) */
|
||||||
|
@media screen and (max-height: 450px) {
|
||||||
|
.sidenav {}
|
||||||
|
.sidenav a {font-size: 18px;}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,24 @@
|
||||||
import { Routes } from '@angular/router';
|
import {Routes} from '@angular/router';
|
||||||
import {DebugComponent} from './page/debug/debug.component';
|
import {DebugComponent} from './page/debug/debug.component';
|
||||||
|
import {EventComponent} from './page/event/event.component';
|
||||||
|
import {TicketComponent} from './page/ticket/ticket.component';
|
||||||
|
import {ScanComponent} from './page/scan/scan.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'debug',
|
path: 'debug',
|
||||||
component: DebugComponent
|
component: DebugComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'event',
|
||||||
|
component: EventComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'ticket',
|
||||||
|
component: TicketComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'scan',
|
||||||
|
component: ScanComponent
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { DebugComponent } from './debug.component';
|
|
||||||
|
|
||||||
describe('DebugComponent', () => {
|
|
||||||
let component: DebugComponent;
|
|
||||||
let fixture: ComponentFixture<DebugComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [DebugComponent]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(DebugComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -20,6 +20,6 @@ export class DebugComponent {
|
||||||
ticketType: TicketTypeEnum.Single
|
ticketType: TicketTypeEnum.Single
|
||||||
};
|
};
|
||||||
|
|
||||||
this.ticketMinter.mintTicket(mintRequest);
|
this.ticketMinter.addTicket(mintRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
source/ticketUI/src/app/page/event/event.component.html
Normal file
1
source/ticketUI/src/app/page/event/event.component.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<p>event works!</p>
|
||||||
11
source/ticketUI/src/app/page/event/event.component.ts
Normal file
11
source/ticketUI/src/app/page/event/event.component.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-event',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './event.component.html',
|
||||||
|
styleUrl: './event.component.scss'
|
||||||
|
})
|
||||||
|
export class EventComponent {
|
||||||
|
|
||||||
|
}
|
||||||
1
source/ticketUI/src/app/page/scan/scan.component.html
Normal file
1
source/ticketUI/src/app/page/scan/scan.component.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<p>scan works!</p>
|
||||||
11
source/ticketUI/src/app/page/scan/scan.component.ts
Normal file
11
source/ticketUI/src/app/page/scan/scan.component.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-scan',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './scan.component.html',
|
||||||
|
styleUrl: './scan.component.scss'
|
||||||
|
})
|
||||||
|
export class ScanComponent {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<p>ticket works!</p>
|
||||||
11
source/ticketUI/src/app/page/ticket/ticket.component.ts
Normal file
11
source/ticketUI/src/app/page/ticket/ticket.component.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-ticket',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './ticket.component.html',
|
||||||
|
styleUrl: './ticket.component.scss'
|
||||||
|
})
|
||||||
|
export class TicketComponent {
|
||||||
|
|
||||||
|
}
|
||||||
31
source/ticketUI/src/app/services/api-utils.ts
Normal file
31
source/ticketUI/src/app/services/api-utils.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import {HttpHeaders, HttpParams} from '@angular/common/http';
|
||||||
|
|
||||||
|
export class ApiUtils {
|
||||||
|
public setHttpRequestOptions(params?: any): any {
|
||||||
|
let headers: HttpHeaders = new HttpHeaders();
|
||||||
|
headers = headers.set('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
source/ticketUI/src/app/services/event.service.ts
Normal file
48
source/ticketUI/src/app/services/event.service.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import {inject, Injectable} from '@angular/core';
|
||||||
|
import {HttpClient} from '@angular/common/http';
|
||||||
|
import {AddEventRequest} from '../../models/request/add-event-request';
|
||||||
|
import {ApiUtils} from './api-utils';
|
||||||
|
import {environment} from '../../environments/environment';
|
||||||
|
import {Endpoints} from '../../models/endpoints';
|
||||||
|
import {catchError, of} from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class EventService extends ApiUtils {
|
||||||
|
private httpClient = inject(HttpClient);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
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<AddEventRequest>(url, JSON.stringify(request), options)
|
||||||
|
.pipe(
|
||||||
|
catchError(error => {
|
||||||
|
console.log(error);
|
||||||
|
return of(undefined);
|
||||||
|
})
|
||||||
|
).subscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,24 +1,27 @@
|
||||||
import {Injectable} from '@angular/core';
|
import {inject, Injectable} from '@angular/core';
|
||||||
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
import {HttpClient} from '@angular/common/http';
|
||||||
import {signal} from '@angular/core';
|
import {signal} from '@angular/core';
|
||||||
import {catchError, map, of} from 'rxjs';
|
import {catchError, map, of} from 'rxjs';
|
||||||
import {environment} from '../../environments/environment';
|
import {environment} from '../../environments/environment';
|
||||||
import {MintResponse} from '../../models/response/mint-response';
|
import {MintResponse} from '../../models/response/mint-response';
|
||||||
import {Endpoints} from '../../models/endpoints';
|
import {Endpoints} from '../../models/endpoints';
|
||||||
import {MintRequest} from '../../models/request/mint-request';
|
import {MintRequest} from '../../models/request/mint-request';
|
||||||
|
import {ApiUtils} from './api-utils';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class TicketService {
|
export class TicketService extends ApiUtils {
|
||||||
public dataSignal = signal('');
|
public dataSignal = signal('');
|
||||||
|
private httpClient = inject(HttpClient);
|
||||||
|
|
||||||
constructor(public httpClient: HttpClient) {
|
constructor() {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public mintTicket(request: MintRequest): void {
|
public addTicket(request: MintRequest): void {
|
||||||
const options = this.setHttpRequestOptions();
|
const options = this.setHttpRequestOptions();
|
||||||
const url = environment.apiBase + Endpoints.MINT_TICKETS;
|
const url = environment.apiBase + Endpoints.TICKET;
|
||||||
|
|
||||||
this.httpClient.post<MintResponse>(url, JSON.stringify(request), options)
|
this.httpClient.post<MintResponse>(url, JSON.stringify(request), options)
|
||||||
.pipe(
|
.pipe(
|
||||||
|
|
@ -31,34 +34,6 @@ export class TicketService {
|
||||||
if (res !== undefined) {
|
if (res !== undefined) {
|
||||||
this.dataSignal.set(res.qrCode);
|
this.dataSignal.set(res.qrCode);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private setHttpRequestOptions(params?: any): any {
|
|
||||||
let headers: HttpHeaders = new HttpHeaders();
|
|
||||||
headers = headers.set('Content-Type', 'application/json');
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<button class="button">Generate Tickets</button>
|
<button class="sidebar-button" [routerLink]="['/ticket']">Generate Tickets</button>
|
||||||
<button class="button">Scan Tickets</button>
|
<button class="sidebar-button" [routerLink]="['/scan']">Scan Tickets</button>
|
||||||
<button class="button">Manage Events</button>
|
<button class="sidebar-button" [routerLink]="['/event']">Manage Events</button>
|
||||||
@if(!environment.production) {
|
@if(!environment.production) {
|
||||||
<button class="button" [routerLink]="['/debug']">Debug</button>
|
<button class="sidebar-button" [routerLink]="['/debug']">Debug</button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
.sidebar-button {
|
||||||
|
margin: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
backdrop-filter: blur(25px) saturate(112%);
|
||||||
|
-webkit-backdrop-filter: blur(25px) saturate(112%);
|
||||||
|
background-color: rgba(255, 255, 255, 0.11);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.125);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { SidebarComponent } from './sidebar.component';
|
|
||||||
|
|
||||||
describe('SidebarComponent', () => {
|
|
||||||
let component: SidebarComponent;
|
|
||||||
let fixture: ComponentFixture<SidebarComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [SidebarComponent]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(SidebarComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
4
source/ticketUI/src/models/core/talent.ts
Normal file
4
source/ticketUI/src/models/core/talent.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface Talent {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
9
source/ticketUI/src/models/core/venue.ts
Normal file
9
source/ticketUI/src/models/core/venue.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
export interface Venue {
|
||||||
|
name: string,
|
||||||
|
description: string,
|
||||||
|
addressOne: string,
|
||||||
|
addressTwo: string | null,
|
||||||
|
city: string,
|
||||||
|
state: string,
|
||||||
|
zip: string,
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
export class Endpoints {
|
export class Endpoints {
|
||||||
public static readonly TICKET = 'ticket';
|
public static readonly TICKET = 'ticket';
|
||||||
public static readonly MINT_TICKETS = Endpoints.TICKET + '/mint'
|
|
||||||
|
public static readonly EVENT = 'events';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
source/ticketUI/src/models/request/add-event-request.ts
Normal file
10
source/ticketUI/src/models/request/add-event-request.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import {Venue} from '../core/venue';
|
||||||
|
import {Talent} from '../core/talent';
|
||||||
|
|
||||||
|
export interface AddEventRequest {
|
||||||
|
date: Date,
|
||||||
|
eventName: string,
|
||||||
|
eventDescription: string,
|
||||||
|
venue: Venue,
|
||||||
|
talent: Talent,
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user