Closing applications
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
using BlazorWebAssemblyVisaApiClient.Common;
|
|
||||||
|
|
||||||
namespace BlazorWebAssemblyVisaApiClient.Components.Auth.Exceptions
|
|
||||||
{
|
|
||||||
public class NotLoggedInException() : BlazorClientException("User is not logged in");
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using BlazorWebAssemblyVisaApiClient.Common;
|
||||||
|
|
||||||
|
namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider.Exceptions
|
||||||
|
{
|
||||||
|
public class UnknownRoleException() : BlazorClientException("Unknown user role");
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider.Exceptions;
|
||||||
using VisaApiClient;
|
using VisaApiClient;
|
||||||
|
|
||||||
namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider
|
namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider
|
||||||
{
|
{
|
||||||
public class UserDataProvider(Client client) : IUserDataProvider
|
public class UserDataProvider(Client client) : IUserDataProvider
|
||||||
{
|
{
|
||||||
private static readonly JwtSecurityTokenHandler tokenHandler = new ();
|
private readonly static JwtSecurityTokenHandler tokenHandler = new ();
|
||||||
|
private readonly static string[] knownRoles = ["Applicant", "ApprovingAuthority", "Admin"];
|
||||||
|
|
||||||
public async Task<ApplicantModel> GetApplicant()
|
public async Task<ApplicantModel> GetApplicant()
|
||||||
{
|
{
|
||||||
@@ -23,6 +25,11 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvide
|
|||||||
var token = tokenHandler.ReadJwtToken(client.AuthToken.Token);
|
var token = tokenHandler.ReadJwtToken(client.AuthToken.Token);
|
||||||
var role = token.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.Role)?.Value;
|
var role = token.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.Role)?.Value;
|
||||||
|
|
||||||
|
if (!knownRoles.Contains(role))
|
||||||
|
{
|
||||||
|
throw new UnknownRoleException();
|
||||||
|
}
|
||||||
|
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,63 @@
|
|||||||
@page "/applications"
|
@page "/applications"
|
||||||
@using System.Text
|
@using System.Reflection
|
||||||
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
||||||
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider
|
||||||
|
@using BlazorWebAssemblyVisaApiClient.PagesExceptions.Applications
|
||||||
@using VisaApiClient
|
@using VisaApiClient
|
||||||
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
||||||
|
|
||||||
<PageTitle>Applications</PageTitle>
|
<PageTitle>Applications</PageTitle>
|
||||||
|
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered">
|
||||||
<thead>
|
@switch (currentRole)
|
||||||
@((MarkupString)htmlHead)
|
{
|
||||||
</thead>
|
case "Applicant":
|
||||||
<tbody>
|
<thead>
|
||||||
@((MarkupString)htmlBody)
|
<tr>
|
||||||
</tbody>
|
<th>Destination Country</th>
|
||||||
|
<th>Visa Category</th>
|
||||||
|
<th>Request date</th>
|
||||||
|
<th>Days requested</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach (var application in applications.Cast<VisaApplicationModelForApplicant>())
|
||||||
|
{
|
||||||
|
var rowClass = application.Status switch
|
||||||
|
{
|
||||||
|
ApplicationStatus.Pending => "",
|
||||||
|
ApplicationStatus.Approved => "table-success",
|
||||||
|
ApplicationStatus.Rejected => "table-danger",
|
||||||
|
ApplicationStatus.Closed => "table-danger",
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
|
||||||
|
<tr class="@rowClass">
|
||||||
|
<th>@application.DestinationCountry</th>
|
||||||
|
<th>@application.VisaCategory.GetDisplayName()</th>
|
||||||
|
<th>@application.RequestDate.ToString("d")</th>
|
||||||
|
<th>@application.ValidDaysRequested</th>
|
||||||
|
<th>@application.Status.GetDisplayName()</th>
|
||||||
|
<th>
|
||||||
|
<input type="button" class="border-danger" @onclick="() => CloseApplication(application)" value="Close"/>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Nav.NavigateTo("/"); //todo feedback
|
||||||
|
break;
|
||||||
|
}
|
||||||
</table >
|
</table >
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string htmlBody = null!;
|
private string currentRole = null!;
|
||||||
|
private IEnumerable<object> applications = [];
|
||||||
private string htmlHead = null!;
|
|
||||||
|
|
||||||
[Inject] private IUserDataProvider UserDataProvider { get; set; } = null!;
|
[Inject] private IUserDataProvider UserDataProvider { get; set; } = null!;
|
||||||
|
|
||||||
@@ -27,41 +65,59 @@
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
var stringBuilder = new StringBuilder();
|
currentRole = UserDataProvider.GetCurrentRole()!;
|
||||||
|
await Fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Fetch()
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (UserDataProvider.GetCurrentRole())
|
applications = currentRole switch
|
||||||
{
|
{
|
||||||
case "Applicant":
|
"Applicant" => (await Client.GetForApplicantAsync()).OrderByDescending(a => a.RequestDate),
|
||||||
htmlHead = "<tr><th>Destination Country</th><th>Visa Category</th><th>Request date</th><th>Days requested</th><th>Status</th></tr>";
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
var applications = await Client.GetForApplicantAsync();
|
};
|
||||||
|
|
||||||
foreach (var application in applications)
|
|
||||||
{
|
|
||||||
var rowClass = application.Status switch
|
|
||||||
{
|
|
||||||
ApplicationStatus.Pending => "",
|
|
||||||
ApplicationStatus.Approved => "table-success",
|
|
||||||
ApplicationStatus.Rejected => "table-danger",
|
|
||||||
ApplicationStatus.Closed => "table-danger",
|
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
|
||||||
};
|
|
||||||
|
|
||||||
stringBuilder.AppendLine($"<tr class=\"{rowClass}\"><th>{application.DestinationCountry}</th><th>{application.VisaCategory.GetDisplayName()}</th><th>{application.RequestDate.ToString("d")}</th><th>{application.ValidDaysRequested}</th><th>{application.Status.GetDisplayName()}</th></tr>");
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlBody = stringBuilder.ToString();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Nav.NavigateTo("/"); //todo feedback
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ErrorHandler.Handle(e);
|
ErrorHandler.Handle(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CloseApplication(object application)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PropertyInfo idProp;
|
||||||
|
PropertyInfo statusProp;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var type = applications.First().GetType();
|
||||||
|
idProp = type.GetProperty("Id")!;
|
||||||
|
statusProp = type.GetProperty("Status")!;
|
||||||
|
if (idProp.PropertyType != typeof(Guid)
|
||||||
|
|| statusProp.PropertyType != typeof(ApplicationStatus))
|
||||||
|
{
|
||||||
|
throw new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw new UnknownApplicationTypeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = (Guid)idProp.GetValue(application)!;
|
||||||
|
await Client.CloseApplicationAsync(id);
|
||||||
|
|
||||||
|
statusProp.SetValue(application, ApplicationStatus.Closed);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorHandler.Handle(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
@using Newtonsoft.Json.Linq
|
@using Newtonsoft.Json.Linq
|
||||||
@using BlazorWebAssemblyVisaApiClient.Components
|
@using BlazorWebAssemblyVisaApiClient.Components
|
||||||
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
||||||
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider
|
|
||||||
@using BlazorWebAssemblyVisaApiClient.Validation
|
@using BlazorWebAssemblyVisaApiClient.Validation
|
||||||
@using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models
|
@using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models
|
||||||
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
||||||
@@ -139,8 +138,6 @@
|
|||||||
|
|
||||||
[Inject] IMapper Mapper { get; set; } = null!;
|
[Inject] IMapper Mapper { get; set; } = null!;
|
||||||
|
|
||||||
[Inject] IDateTimeProvider DateTimeProvider { get; set; } = null!;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
requestModel.BirthDate = DateTime.Now.AddYears(-ConfigurationConstraints.ApplicantMinAge);
|
requestModel.BirthDate = DateTime.Now.AddYears(-ConfigurationConstraints.ApplicantMinAge);
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using BlazorWebAssemblyVisaApiClient.Common;
|
||||||
|
|
||||||
|
namespace BlazorWebAssemblyVisaApiClient.PagesExceptions.Applications
|
||||||
|
{
|
||||||
|
public class UnknownApplicationTypeException() : BlazorClientException("Application type is unknown");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user