Application creating but without past visas and visits
This commit is contained in:
		| @@ -13,7 +13,7 @@ | ||||
|         Expiration date:<br/> | ||||
|         <InputDate DisplayName="Expiration date of permission to destination Country" class="rounded" | ||||
|                    @bind-Value="PermissionToDestCountry.ExpirationDate" | ||||
|                    max="@formattedDate"/> | ||||
|                    min="@formattedDate"/> | ||||
|     </label><br/> | ||||
|     <ValidationMessage For="() => PermissionToDestCountry.ExpirationDate"></ValidationMessage> | ||||
| </div> | ||||
|   | ||||
| @@ -0,0 +1,34 @@ | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using VisaApiClient | ||||
|  | ||||
| <div> | ||||
|     <label> | ||||
|         Number:<br/> | ||||
|         <InputText DisplayName="Number of re-entry permit" class="rounded" | ||||
|                    @bind-Value="ReentryPermit.Number"/> | ||||
|     </label><br/> | ||||
|     <ValidationMessage For="() => ReentryPermit.Number"></ValidationMessage><br/> | ||||
|  | ||||
|     <label> | ||||
|         Expiration date:<br/> | ||||
|         <InputDate DisplayName="Expiration date of re-entry permit" class="rounded" | ||||
|                    @bind-Value="ReentryPermit.ExpirationDate" | ||||
|                    min="@formattedDate"/> | ||||
|     </label><br/> | ||||
|     <ValidationMessage For="() => ReentryPermit.ExpirationDate"></ValidationMessage> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private string formattedDate = null!; | ||||
|  | ||||
|     [Parameter, EditorRequired] public ReentryPermitModel ReentryPermit { get; set; } = null!; | ||||
|  | ||||
|     [Inject] IDateTimeProvider DateTimeProvider { get; set; } = null!; | ||||
|  | ||||
|     protected override void OnInitialized() | ||||
|     { | ||||
|         formattedDate = DateTimeProvider.FormattedNow(); | ||||
|         ReentryPermit.ExpirationDate = DateTimeProvider.Now(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,4 +1,6 @@ | ||||
| <CascadingValue Value="this"> | ||||
| @using System.Net | ||||
| @using VisaApiClient | ||||
| <CascadingValue Value="this"> | ||||
|     @ChildContent | ||||
| </CascadingValue> | ||||
|  | ||||
| @@ -7,8 +9,13 @@ | ||||
|     [Parameter] | ||||
|     public RenderFragment? ChildContent { get; set; } | ||||
|  | ||||
|     [Inject] private NavigationManager Nav { get; set; } = null!; | ||||
|  | ||||
|     public void Handle(Exception ex) | ||||
|     { | ||||
|  | ||||
|         if (ex is ApiException<ProblemDetails> { StatusCode: (int)HttpStatusCode.Unauthorized or (int)HttpStatusCode.Forbidden }) | ||||
|         { | ||||
|             Nav.NavigateTo("/"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,14 @@ | ||||
| using AutoMapper; | ||||
| using BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models; | ||||
| using VisaApiClient; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles | ||||
| { | ||||
|     public class VisaApplicationCreateRequestProfile : Profile | ||||
|     { | ||||
|         public VisaApplicationCreateRequestProfile() | ||||
|         { | ||||
|             CreateMap<VisaApplicationCreateRequestModel, VisaApplicationCreateRequest>(MemberList.Destination); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,22 @@ | ||||
| using System.Text; | ||||
| using FluentValidation.Results; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers | ||||
| { | ||||
|     public static class ValidationResultExtensions | ||||
|     { | ||||
|         public static string ToErrorsString(this ValidationResult validationResult) | ||||
|             => ErrorsToString(validationResult.Errors.Select(e => e.ErrorMessage)); | ||||
|  | ||||
|         private static string ErrorsToString(IEnumerable<string> errors) | ||||
|         { | ||||
|             var stringBuilder = new StringBuilder(); | ||||
|             foreach (var error in errors) | ||||
|             { | ||||
|                 stringBuilder.Append($"{error}<br/>"); | ||||
|             } | ||||
|  | ||||
|             return stringBuilder.ToString(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -5,7 +5,7 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvide | ||||
|     public interface IUserDataProvider | ||||
|     { | ||||
|  | ||||
|         public ApplicantModel? GetApplicant(); | ||||
|         public Task<ApplicantModel> GetApplicant(); | ||||
|  | ||||
|         public string? GetCurrentRole(); | ||||
|     } | ||||
|   | ||||
| @@ -8,10 +8,9 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvide | ||||
|     { | ||||
|         private static readonly JwtSecurityTokenHandler tokenHandler = new (); | ||||
|  | ||||
|         public ApplicantModel? GetApplicant() | ||||
|         public async Task<ApplicantModel> GetApplicant() | ||||
|         { | ||||
|             //todo api action | ||||
|             return null; | ||||
|             return await client.GetApplicantAsync(); | ||||
|         } | ||||
|  | ||||
|         public string? GetCurrentRole() | ||||
|   | ||||
| @@ -22,6 +22,13 @@ | ||||
|             </NavLink> | ||||
|         </div> | ||||
|     </nav> | ||||
|     <nav class="flex-column"> | ||||
|         <div class="nav-item px-3"> | ||||
|             <NavLink class="nav-link" href="applications/new" Match="NavLinkMatch.All"> | ||||
|                 <span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> New application | ||||
|             </NavLink> | ||||
|         </div> | ||||
|     </nav> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| @page "/applications" | ||||
| @using System.Net | ||||
| @using System.Text | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider | ||||
| @@ -61,14 +60,7 @@ | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             if (e is ApiException<ProblemDetails> { Result.Status: (int)HttpStatusCode.Unauthorized } problemDetailsException) | ||||
|             { | ||||
|                 htmlBody =  $"<p>{problemDetailsException.Result.Detail!}</p>"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ErrorHandler.Handle(e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,17 @@ | ||||
| @page "/visaApplications/new" | ||||
| @page "/applications/new" | ||||
| @using System.Net | ||||
| @using AutoMapper | ||||
| @using BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.FormComponents.Applicants | ||||
| @using VisaApiClient | ||||
| @using BlazorWebAssemblyVisaApiClient.Components | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.FormComponents.VisaApplications | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider | ||||
| @using FluentValidation | ||||
| @using Newtonsoft.Json | ||||
| @using Newtonsoft.Json.Linq | ||||
| @inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase | ||||
|  | ||||
| <PageTitle>New Application</PageTitle> | ||||
| @@ -23,9 +30,10 @@ | ||||
|             <ValidationMessage For="() => requestModel.DestinationCountry"></ValidationMessage><br/> | ||||
|  | ||||
|             <label> | ||||
|                 Category: <EnumInputList Model="requestModel" | ||||
|                                          EnumProperty="r => r.VisaCategory" | ||||
|                                          OnChanged="StateHasChanged"/> | ||||
|                 Category: | ||||
|                 <EnumInputList Model="requestModel" | ||||
|                                EnumProperty="r => r.VisaCategory" | ||||
|                                OnChanged="StateHasChanged"/> | ||||
|             </label><br/> | ||||
|             <ValidationMessage For="() => requestModel.VisaCategory"></ValidationMessage><br/> | ||||
|  | ||||
| @@ -46,33 +54,98 @@ | ||||
|             <ValidationMessage For="() => requestModel.ValidDaysRequested"></ValidationMessage><br/> | ||||
|         </div> | ||||
|  | ||||
|         <div class="form-block"> | ||||
|             <fieldset disabled="@(requestModel.VisaCategory is not VisaCategory.Transit)"> | ||||
|         @if (requestModel.VisaCategory is VisaCategory.Transit) | ||||
|         { | ||||
|             <div class="form-block"> | ||||
|                 <h5>Permission to destination Country</h5> | ||||
|                 <PermissionToDestCountryInput PermissionToDestCountry="requestModel.PermissionToDestCountry" /> | ||||
|             </fieldset> | ||||
|         </div><br/> | ||||
|                 <PermissionToDestCountryInput PermissionToDestCountry="requestModel.PermissionToDestCountry"/> | ||||
|             </div> | ||||
|         } | ||||
|  | ||||
|         @if (isNonResident) | ||||
|         { | ||||
|             <div class="form-block"> | ||||
|                 <h5>Re-entry permission</h5> | ||||
|                 <ReentryPermitInput ReentryPermit="requestModel.ReentryPermit" /> | ||||
|             </div> | ||||
|             <br/> | ||||
|         } | ||||
|  | ||||
|         <input type="submit" class="btn-outline-primary" value="Register"/> | ||||
|         <ValidationSummary/> | ||||
|         <Status @ref="status"/> | ||||
|     </EditForm> | ||||
| </div> | ||||
|  | ||||
| //todo past visas and visits | ||||
|  | ||||
| @code { | ||||
|     private VisaApplicationCreateRequestModel requestModel = new(); | ||||
|     private Status status = null!; | ||||
|     private bool isNonResident; | ||||
|  | ||||
|     [Inject] IDateTimeProvider DateTimeProvider { get; set; } = null!; | ||||
|  | ||||
|     protected override void OnInitialized() | ||||
|     [Inject] IUserDataProvider UserDataProvider { get; set; } = null!; | ||||
|  | ||||
|     [Inject] IValidator<VisaApplicationCreateRequestModel> VisaApplicationCreateRequestValidator { get; set; } = null!; | ||||
|  | ||||
|     [Inject] IMapper Mapper { get; set; } = null!; | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             isNonResident = (await UserDataProvider.GetApplicant()).IsNonResident; | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             ErrorHandler.Handle(e); | ||||
|         } | ||||
|  | ||||
|         requestModel.PermissionToDestCountry!.ExpirationDate = DateTimeProvider.Now(); | ||||
|     } | ||||
|  | ||||
|     private static void TryCreate() | ||||
|     private async Task TryCreate() | ||||
|     { | ||||
|         var validationResult = await VisaApplicationCreateRequestValidator.ValidateAsync(requestModel); | ||||
|         if (!validationResult.IsValid) | ||||
|         { | ||||
|             var errorsString = validationResult.ToErrorsString(); | ||||
|             status.SetError(errorsString); | ||||
|         } | ||||
|  | ||||
|         status.SetMessage("Wait..."); | ||||
|  | ||||
|         var request = Mapper.Map<VisaApplicationCreateRequest>(requestModel); | ||||
|         try | ||||
|         { | ||||
|             await Client.CreateApplicationAsync(request); | ||||
|             status.SetSucces("Application created successfully."); | ||||
|         } | ||||
|         catch (ApiException<ProblemDetails> e) | ||||
|         { | ||||
|             if (e.StatusCode == (int)HttpStatusCode.BadRequest | ||||
|                 && e.Result.AdditionalProperties.TryGetValue("errors", out var errors)) | ||||
|             { | ||||
|                 var errorsList = ((JArray)errors).ToObject<List<string>>(); | ||||
|                 if (errorsList is null) | ||||
|                 { | ||||
|                     ErrorHandler.Handle(new JsonException("Can't convert validation errors to list")); | ||||
|  | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 status.SetError(string.Join("<br/>", errorsList)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ErrorHandler.Handle(e); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             ErrorHandler.Handle(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| @page "/register" | ||||
| @using System.Net | ||||
| @using System.Text | ||||
| @using AutoMapper | ||||
| @using VisaApiClient | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.FormComponents.Applicants | ||||
| @@ -8,6 +7,7 @@ | ||||
| @using Newtonsoft.Json | ||||
| @using Newtonsoft.Json.Linq | ||||
| @using BlazorWebAssemblyVisaApiClient.Components | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models | ||||
| @inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase | ||||
| @@ -144,23 +144,12 @@ | ||||
|         requestModel.BirthDate = DateTime.Now; | ||||
|     } | ||||
|  | ||||
|     private string ErrorsToString(IEnumerable<string> errors) | ||||
|     { | ||||
|         var stringBuilder = new StringBuilder(); | ||||
|         foreach (var error in errors) | ||||
|         { | ||||
|             stringBuilder.Append($"{error}<br/>"); | ||||
|         } | ||||
|  | ||||
|         return stringBuilder.ToString(); | ||||
|     } | ||||
|  | ||||
|     private async void TryRegisterApplicant() | ||||
|     { | ||||
|         var validationResult = await RegisterApplicantRequestValidator.ValidateAsync(requestModel); | ||||
|         if (!validationResult.IsValid) | ||||
|         { | ||||
|             var errorsString = ErrorsToString(validationResult.Errors.Select(e => e.ErrorMessage)); | ||||
|             var errorsString = validationResult.ToErrorsString(); | ||||
|             status.SetError(errorsString); | ||||
|  | ||||
|             return; | ||||
| @@ -187,7 +176,7 @@ | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 status.SetError(ErrorsToString(errorsList)); | ||||
|                 status.SetError(string.Join("<br/>", errorsList)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -196,6 +185,7 @@ | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             status.SetError("Error occured"); | ||||
|             ErrorHandler.Handle(e); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -26,14 +26,12 @@ namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models | ||||
|         [Range(0, ConfigurationConstraints.MaxValidDays)] | ||||
|         public int ValidDaysRequested { get; set; } | ||||
|  | ||||
|         [Required] | ||||
|         [ValidateComplexType] | ||||
|         public PastVisaModel[] PastVisas { get; set; } = default!; | ||||
|  | ||||
|         [ValidateComplexType] | ||||
|         public PermissionToDestCountryModel? PermissionToDestCountry { get; set; } = new(); | ||||
|  | ||||
|         [Required] | ||||
|         [ValidateComplexType] | ||||
|         public PastVisitModel[] PastVisits { get; set; } = default!; | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,27 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Validators; | ||||
|  | ||||
| public class PastVisaModelValidator : AbstractValidator<PastVisaModel> | ||||
| { | ||||
|     public PastVisaModelValidator(IDateTimeProvider dateTimeProvider) | ||||
|     { | ||||
|         RuleFor(v => v.ExpirationDate) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Expiration date of past visa can not be empty") | ||||
|             .GreaterThan(v => v.IssueDate) | ||||
|             .WithMessage("Past visa expiration date can not be earlier than issue date"); | ||||
|  | ||||
|         RuleFor(v => v.IssueDate) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Issue date of past visa can not be empty") | ||||
|             .LessThan(dateTimeProvider.Now()) | ||||
|             .WithMessage("Issue date of past visa must be in past"); | ||||
|  | ||||
|         RuleFor(v => v.Name) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Name of past visa can not be empty"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Validators; | ||||
|  | ||||
| public class PastVisitModelValidator : AbstractValidator<PastVisitModel> | ||||
| { | ||||
|     public PastVisitModelValidator(IDateTimeProvider dateTimeProvider) | ||||
|     { | ||||
|         RuleFor(v => v.StartDate) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Start date of past visit can not be empty") | ||||
|             .LessThan(v => v.EndDate) | ||||
|             .WithMessage("Start date of past visit must be earlier than end date") | ||||
|             .LessThan(dateTimeProvider.Now()) | ||||
|             .WithMessage("Start date of past visit must be in past"); | ||||
|  | ||||
|         RuleFor(v => v.EndDate) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("End date of past visit can not be empty"); | ||||
|  | ||||
|         RuleFor(v => v.DestinationCountry) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Destination Country of past visit can not be null") | ||||
|             .MaximumLength(ConfigurationConstraints.CountryNameLength) | ||||
|             .WithMessage($"Destination Country of past visit length must be less than {ConfigurationConstraints.CountryNameLength}"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Validators; | ||||
|  | ||||
| public class PermissionToDestCountryModelValidator : AbstractValidator<PermissionToDestCountryModel?> | ||||
| { | ||||
|     public PermissionToDestCountryModelValidator(IDateTimeProvider dateTimeProvider) | ||||
|     { | ||||
|         RuleFor(p => p!.ExpirationDate) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Expiration date of permission to destination Country can not be empty") | ||||
|             .GreaterThan(dateTimeProvider.Now()) | ||||
|             .WithMessage("Permission to destination Country must not be expired"); | ||||
|  | ||||
|         RuleFor(p => p!.Issuer) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Issuer of permission for destination Country can not be empty") | ||||
|             .MaximumLength(ConfigurationConstraints.IssuerNameLength) | ||||
|             .WithMessage($"Issuer of permission to destination Country length must be less than {ConfigurationConstraints.IssuerNameLength}"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,42 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Validators; | ||||
|  | ||||
| public class VisaApplicationCreateRequestModelValidator : AbstractValidator<VisaApplicationCreateRequestModel> | ||||
| { | ||||
|     public VisaApplicationCreateRequestModelValidator( | ||||
|         IValidator<PastVisaModel> pastVisaModelValidator, | ||||
|         IValidator<PermissionToDestCountryModel?> permissionToDestCountryModelValidator, | ||||
|         IValidator<PastVisitModel> pastVisitModelValidator) | ||||
|     { | ||||
|         RuleFor(r => r.PermissionToDestCountry) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("For transit you must provide permission to destination country") | ||||
|             .SetValidator(permissionToDestCountryModelValidator) | ||||
|             .When(r => r.VisaCategory is VisaCategory.Transit); | ||||
|  | ||||
|         RuleFor(r => r.DestinationCountry) | ||||
|             .NotEmpty() | ||||
|             .WithMessage("Destination country can not be empty"); | ||||
|  | ||||
|         RuleFor(r => r.VisaCategory) | ||||
|             .IsInEnum(); | ||||
|  | ||||
|         RuleFor(r => r.RequestedNumberOfEntries) | ||||
|             .IsInEnum(); | ||||
|  | ||||
|         RuleFor(r => r.ValidDaysRequested) | ||||
|             .GreaterThan(0) | ||||
|             .WithMessage($"Valid days requested should be positive number and less than {ConfigurationConstraints.MaxValidDays}") | ||||
|             .LessThanOrEqualTo(ConfigurationConstraints.MaxValidDays) | ||||
|             .WithMessage($"Valid days requested must be less than or equal to {ConfigurationConstraints.MaxValidDays}"); | ||||
|  | ||||
|         RuleForEach(r => r.PastVisas) | ||||
|             .SetValidator(pastVisaModelValidator); | ||||
|  | ||||
|         RuleForEach(r => r.PastVisits) | ||||
|             .SetValidator(pastVisitModelValidator); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user