diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/BlazorWebAssemblyVisaApiClient.csproj b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/BlazorWebAssemblyVisaApiClient.csproj index a2499f3..4798785 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/BlazorWebAssemblyVisaApiClient.csproj +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/BlazorWebAssemblyVisaApiClient.csproj @@ -7,6 +7,10 @@ + + + + @@ -15,4 +19,8 @@ + + <_ContentIncludedByDefault Remove="wwwroot\sample-data\weather.json" /> + + diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/AddressInput.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/AddressInput.razor new file mode 100644 index 0000000..83b4c03 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/AddressInput.razor @@ -0,0 +1,39 @@ +@using VisaApiClient + +
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+ +@code { + [Parameter, EditorRequired] public AddressModel Address { get; set; } = null!; +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/AuthDataInput.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/AuthDataInput.razor new file mode 100644 index 0000000..8979a87 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/AuthDataInput.razor @@ -0,0 +1,23 @@ +@using VisaApiClient + +
+
+
+
+
+ +
+
+ +
+
+ +@code { + [Parameter, EditorRequired] public AuthData AuthData { get; set; } = null!; +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/EnumInputList.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/EnumInputList.razor new file mode 100644 index 0000000..0895b65 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/EnumInputList.razor @@ -0,0 +1,50 @@ +@using System.ComponentModel.DataAnnotations +@using System.Linq.Expressions +@using System.Reflection +@typeparam TItem where TItem : class + @typeparam TMember where TMember : struct, Enum + + + @foreach (var value in enumValues) + { + + } +
+ +@code { + [Parameter, EditorRequired] public TItem Model { get; set; } = default!; + + [Parameter, EditorRequired] public Expression> EnumProperty { get; set; } = null!; + + private Dictionary enumValues = new(); + private PropertyInfo modelMemberInfo = null!; + private TMember selected; + + protected override void OnInitialized() + { + var enumMembers = typeof(TMember).GetMembers(); + var modelMemberName = ((MemberExpression)EnumProperty.Body).Member.Name; + modelMemberInfo = typeof(TItem).GetProperty(modelMemberName)!; + + foreach (var value in Enum.GetValues()) + { + var member = enumMembers.First(info => info.Name == value.ToString()); + var displayAttribute = (DisplayAttribute?)member + .GetCustomAttributes(typeof(DisplayAttribute), false) + .FirstOrDefault(); + var displayName = displayAttribute?.Name ?? value.ToString(); + enumValues.Add(value, displayName); + } + } + + protected override void OnAfterRender(bool firstRender) + { + OnValueChanged(); + } + + private void OnValueChanged() + { + modelMemberInfo.SetValue(Model, selected); + } + +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/NameInput.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/NameInput.razor new file mode 100644 index 0000000..ad0de6c --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/NameInput.razor @@ -0,0 +1,31 @@ +@using VisaApiClient + +
+
+
+ +

+ +
+
+ +

+ +
+
+ +
+
+ +@code { + [Parameter, EditorRequired] public NameModel Name { get; set; } = null!; +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/PassportInput.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/PassportInput.razor new file mode 100644 index 0000000..ec52b6c --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/PassportInput.razor @@ -0,0 +1,51 @@ +@using BlazorWebAssemblyVisaApiClient.Infrastructure.Services +@using VisaApiClient + +
+
+
+ +

+ +
+
+ +

+ +
+
+ +

+ +
+
+ +
+
+ +@code { + private string now = DateTime.Now.ToString("yyyy-MM-dd"); + + [Parameter, EditorRequired] public PassportModel Passport { get; set; } = null!; + + [Inject] IDateTimeProvider DateTimeProvider { get; set; } = null!; + + protected override void OnInitialized() + { + Passport.IssueDate = DateTime.Now; + Passport.ExpirationDate = DateTime.Now; + } + +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/PlaceOfWorkInput.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/PlaceOfWorkInput.razor new file mode 100644 index 0000000..988c47f --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Applicants/PlaceOfWorkInput.razor @@ -0,0 +1,23 @@ +@using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models + +
+
+
+
+
+ +
+
+ +
+
+ +@code { + [Parameter, EditorRequired] public PlaceOfWorkModel PlaceOfWork { get; set; } = null!; +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Validation/CustomValidation.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Validation/CustomValidation.razor new file mode 100644 index 0000000..36a09aa --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Components/FormComponents/Validation/CustomValidation.razor @@ -0,0 +1,46 @@ +

CustomValidation

+ +@code { + private ValidationMessageStore? messageStore; + + [CascadingParameter] + private EditContext? CurrentEditContext { get; set; } + + protected override void OnInitialized() + { + if (CurrentEditContext is null) + { + throw new InvalidOperationException( + $"{nameof(CustomValidation)} requires a cascading " + + $"parameter of type {nameof(EditContext)}. " + + $"For example, you can use {nameof(CustomValidation)} " + + $"inside an {nameof(EditForm)}."); + } + + messageStore = new(CurrentEditContext); + + CurrentEditContext.OnValidationRequested += (_, _) => + messageStore?.Clear(); + CurrentEditContext.OnFieldChanged += (_, e) => + messageStore?.Clear(e.FieldIdentifier); + } + + public void DisplayErrors(Dictionary> errors) + { + if (CurrentEditContext is not null) + { + foreach (var err in errors) + { + messageStore?.Add(CurrentEditContext.Field(err.Key), err.Value); + } + + CurrentEditContext.NotifyValidationStateChanged(); + } + } + + public void ClearErrors() + { + messageStore?.Clear(); + CurrentEditContext?.NotifyValidationStateChanged(); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/PlaceOfWorkModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/PlaceOfWorkModel.cs new file mode 100644 index 0000000..dc7ec95 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/PlaceOfWorkModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models +{ + /// Model of place of work with attributes required for validation to work + public class PlaceOfWorkModel + { + [Required] + [StringLength(ConfigurationConstraints.PlaceOfWorkNameLength, MinimumLength = 1)] + public string Name { get; set; } = default!; + + [Required] + [ValidateComplexType] + public AddressModel Address { get; set; } = new AddressModel(); + + [Required] + [StringLength(ConfigurationConstraints.PhoneNumberLength, MinimumLength = ConfigurationConstraints.PhoneNumberMinLength)] + public string PhoneNum { get; set; } = default!; + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/RegisterApplicantRequestModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/RegisterApplicantRequestModel.cs new file mode 100644 index 0000000..d87f12d --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/RegisterApplicantRequestModel.cs @@ -0,0 +1,68 @@ +using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models +{ + /// Model of request with attributes required for validation to work + public class RegisterApplicantRequestModel + { + [Required] + [ValidateComplexType] + public RegisterRequestModel RegisterRequest { get; set; } = new(); + + [Required] + [ValidateComplexType] + public NameModel ApplicantName { get; set; } = new(); + + [Required] + [ValidateComplexType] + public PassportModel Passport { get; set; } = new(); + + [Required(AllowEmptyStrings = true)] + public DateTimeOffset BirthDate { get; set; } + + [Required] + [StringLength(70, MinimumLength = 1)] + public string CityOfBirth { get; set; } = default!; + + [Required] + [StringLength(70, MinimumLength = 1)] + public string CountryOfBirth { get; set; } = default!; + + [Required] + [StringLength(30, MinimumLength = 1)] + public string Citizenship { get; set; } = default!; + + [Required] + [StringLength(30, MinimumLength = 1)] + public string CitizenshipByBirth { get; set; } = default!; + + [Required(AllowEmptyStrings = true)] + [JsonConverter(typeof(StringEnumConverter))] + public Gender Gender { get; set; } + + [Required(AllowEmptyStrings = true)] + [JsonConverter(typeof(StringEnumConverter))] + public MaritalStatus MaritalStatus { get; set; } + + [Required] + [ValidateComplexType] + public NameModel FatherName { get; set; } = new(); + + [Required] + [ValidateComplexType] + public NameModel MotherName { get; set; } = new(); + + [Required] + [StringLength(50, MinimumLength = 1)] + public string JobTitle { get; set; } = default!; + + [Required] + [ValidateComplexType] + public PlaceOfWorkModel PlaceOfWork { get; set; } = new(); + + public bool IsNonResident { get; set; } + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/RegisterRequestModel.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/RegisterRequestModel.cs new file mode 100644 index 0000000..682dd7a --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Models/RegisterRequestModel.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models +{ + /// Model of request with attributes required for validation to work + public class RegisterRequestModel + { + [Required] + [ValidateComplexType] + public AuthData AuthData { get; set; } = new AuthData(); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/NameModelValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/NameModelValidator.cs new file mode 100644 index 0000000..14c334b --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/NameModelValidator.cs @@ -0,0 +1,26 @@ +using FluentValidation; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; + +public class NameModelValidator : AbstractValidator +{ + public NameModelValidator() + { + RuleFor(m => m.FirstName) + .NotEmpty() + .WithMessage("First Name can not be empty") + .MaximumLength(ConfigurationConstraints.NameLength) + .WithMessage($"First Name length must be less than {ConfigurationConstraints.NameLength}"); + + RuleFor(m => m.Surname) + .NotEmpty() + .WithMessage("Surname can not be empty") + .MaximumLength(ConfigurationConstraints.NameLength) + .WithMessage($"Surname length must be less than {ConfigurationConstraints.NameLength}"); + + RuleFor(m => m.Patronymic) + .MaximumLength(ConfigurationConstraints.NameLength) + .WithMessage($"Patronymic length must be less than {ConfigurationConstraints.NameLength}"); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/PassportModelValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/PassportModelValidator.cs new file mode 100644 index 0000000..289b8c4 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/PassportModelValidator.cs @@ -0,0 +1,35 @@ +using BlazorWebAssemblyVisaApiClient.Infrastructure.Services; +using FluentValidation; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; + +public class PassportModelValidator : AbstractValidator +{ + public PassportModelValidator(IDateTimeProvider dateTimeProvider) + { + RuleFor(r => r.Issuer) + .NotEmpty() + .WithMessage("Passport issuer can not be empty") + .MaximumLength(ConfigurationConstraints.IssuerNameLength) + .WithMessage($"Passport issuer length must be less than {ConfigurationConstraints.IssuerNameLength}"); + + RuleFor(r => r.Number) + .NotEmpty() + .WithMessage("Passport number can not be empty") + .MaximumLength(ConfigurationConstraints.PassportNumberLength) + .WithMessage($"Passport number length must be less than {ConfigurationConstraints.PassportNumberLength}"); + + RuleFor(r => r.ExpirationDate) + .NotEmpty() + .WithMessage("Passport expiration date can not be empty") + .GreaterThan(dateTimeProvider.Now()) + .WithMessage("Can not approve visa for applicants with expired passport"); + + RuleFor(r => r.IssueDate) + .NotEmpty() + .WithMessage("Passport issue date can not be empty") + .LessThanOrEqualTo(dateTimeProvider.Now()) + .WithMessage("Passport issue date must be in past"); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/PlaceOfWorkModelValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/PlaceOfWorkModelValidator.cs new file mode 100644 index 0000000..2974164 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/PlaceOfWorkModelValidator.cs @@ -0,0 +1,50 @@ +using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; +using FluentValidation; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; + +public class PlaceOfWorkModelValidator : AbstractValidator +{ + public PlaceOfWorkModelValidator() + { + RuleFor(p => p.Name) + .NotEmpty() + .WithMessage("Place of work name can not be empty") + .MaximumLength(ConfigurationConstraints.PlaceOfWorkNameLength) + .WithMessage($"Place of work name length must be less than {ConfigurationConstraints.PlaceOfWorkNameLength}"); + + RuleFor(p => p.PhoneNum) + .NotEmpty() + .WithMessage("Place of work phone number can not be empty") + .MaximumLength(ConfigurationConstraints.PhoneNumberLength) + .WithMessage( + $"Phone number length must be in range from {ConfigurationConstraints.PhoneNumberMinLength} to {ConfigurationConstraints.PhoneNumberLength}") + .MinimumLength(ConfigurationConstraints.PhoneNumberMinLength) + .WithMessage( + $"Phone number length must be in range from {ConfigurationConstraints.PhoneNumberMinLength} to {ConfigurationConstraints.PhoneNumberLength}"); + + RuleFor(p => p.Address.Country) + .NotEmpty() + .WithMessage("Country name of place of work can not be empty") + .MaximumLength(ConfigurationConstraints.CountryNameLength) + .WithMessage($"Country name of place of work length must be less than {ConfigurationConstraints.CountryNameLength}"); + + RuleFor(p => p.Address.City) + .NotEmpty() + .WithMessage("City name of place of work can not be empty") + .MaximumLength(ConfigurationConstraints.CityNameLength) + .WithMessage($"City name of place of work length must be less than {ConfigurationConstraints.CityNameLength}"); + + RuleFor(p => p.Address.Street) + .NotEmpty() + .WithMessage("Street name of place of work can not be empty") + .MaximumLength(ConfigurationConstraints.StreetNameLength) + .WithMessage($"Street name of place of work length must be less than {ConfigurationConstraints.StreetNameLength}"); + + RuleFor(p => p.Address.Building) + .NotEmpty() + .WithMessage("Building of place of work can not be empty") + .MaximumLength(ConfigurationConstraints.CountryNameLength) + .WithMessage($"Building of place of work length must be less than {ConfigurationConstraints.BuildingNumberLength}"); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/RegisterApplicantRequestValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/RegisterApplicantRequestValidator.cs new file mode 100644 index 0000000..d7c626d --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Applicants/Validators/RegisterApplicantRequestValidator.cs @@ -0,0 +1,76 @@ +using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; +using BlazorWebAssemblyVisaApiClient.Infrastructure.Services; +using FluentValidation; +using VisaApiClient; +using PlaceOfWorkModel = BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models.PlaceOfWorkModel; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; + +public class RegisterApplicantRequestValidator : AbstractValidator +{ + public RegisterApplicantRequestValidator( + IDateTimeProvider dateTimeProvider, + IValidator nameValidator, + IValidator registerRequestModelValidator, + IValidator passportValidator, + IValidator placeOfWorkModelValidator) + { + RuleFor(r => r.RegisterRequest) + .SetValidator(registerRequestModelValidator); + + RuleFor(r => r.ApplicantName) + .SetValidator(nameValidator); + + RuleFor(r => r.FatherName) + .SetValidator(nameValidator); + + RuleFor(r => r.MotherName) + .SetValidator(nameValidator); + + RuleFor(r => r.Passport) + .SetValidator(passportValidator); + + RuleFor(r => r.BirthDate) + .NotEmpty() + .WithMessage("Birth date can not be empty") + .LessThanOrEqualTo(dateTimeProvider.Now().AddYears(-ConfigurationConstraints.ApplicantMinAge)) + .WithMessage($"Applicant must be older than {ConfigurationConstraints.ApplicantMinAge}"); + + RuleFor(r => r.CountryOfBirth) + .NotEmpty() + .WithMessage("Country of birth can not be empty") + .MaximumLength(ConfigurationConstraints.CountryNameLength) + .WithMessage($"Country of birth name length must be less than {ConfigurationConstraints.CountryNameLength}"); + + RuleFor(r => r.CityOfBirth) + .NotEmpty() + .WithMessage("City of birth can not be empty") + .MaximumLength(ConfigurationConstraints.CityNameLength) + .WithMessage($"City of birth name length must be less than {ConfigurationConstraints.CityNameLength}"); + + RuleFor(r => r.Citizenship) + .NotEmpty() + .WithMessage("Citizenship can not be empty") + .MaximumLength(ConfigurationConstraints.CitizenshipLength) + .WithMessage($"Citizenship length must be less than {ConfigurationConstraints.CitizenshipLength}"); + + RuleFor(r => r.CitizenshipByBirth) + .NotEmpty() + .WithMessage("Citizenship by birth can not be empty") + .MaximumLength(ConfigurationConstraints.CitizenshipLength) + .WithMessage($"Citizenship by birth length must be less than {ConfigurationConstraints.CitizenshipLength}"); + + RuleFor(r => r.Gender).IsInEnum(); + + RuleFor(r => r.MaritalStatus).IsInEnum(); + + RuleFor(r => r.JobTitle) + .NotEmpty() + .WithMessage("Title of job can not be empty") + .MaximumLength(ConfigurationConstraints.JobTitleLength) + .WithMessage($"Title of job length must be less than {ConfigurationConstraints.JobTitleLength}"); + + RuleFor(r => r.PlaceOfWork) + .SetValidator(placeOfWorkModelValidator); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Common/AuthDataValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Common/AuthDataValidator.cs new file mode 100644 index 0000000..b9ce6de --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Common/AuthDataValidator.cs @@ -0,0 +1,24 @@ +using FluentValidation; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Common; + +public class AuthDataValidator : AbstractValidator +{ + public AuthDataValidator() + { + RuleFor(d => d.Email) + .NotEmpty() + .WithMessage("Email can not be empty") + .EmailAddress() + .WithMessage("Email must be valid") + .MaximumLength(ConfigurationConstraints.EmailLength) + .WithMessage($"Email length must be less than {ConfigurationConstraints.EmailLength}"); + + RuleFor(d => d.Password) + .NotEmpty() + .WithMessage("Password can not be empty") + .MaximumLength(ConfigurationConstraints.PasswordLength) + .WithMessage($"Password length must be less than {ConfigurationConstraints.PasswordLength}"); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Common/RegisterRequestModelValidator.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Common/RegisterRequestModelValidator.cs new file mode 100644 index 0000000..0111b9f --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/Common/RegisterRequestModelValidator.cs @@ -0,0 +1,14 @@ +using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; +using FluentValidation; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Common; + +public class RegisterRequestModelValidator : AbstractValidator +{ + public RegisterRequestModelValidator(IValidator authDataValidator) + { + RuleFor(r => r.AuthData) + .SetValidator(authDataValidator); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/ConfigurationConstraints.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/ConfigurationConstraints.cs new file mode 100644 index 0000000..02bf65a --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/FluentValidation/ConfigurationConstraints.cs @@ -0,0 +1,23 @@ +namespace BlazorWebAssemblyVisaApiClient.FluentValidation; + +public static class ConfigurationConstraints +{ + public const int CityNameLength = 70; + public const int CountryNameLength = 70; + public const int CitizenshipLength = 30; + public const int ReentryPermitNumberLength = 25; + public const int IssuerNameLength = 200; + public const int VisaNameLength = 70; + public const int StreetNameLength = 100; + public const int PlaceOfWorkNameLength = 200; + public const int NameLength = 50; + public const int BuildingNumberLength = 10; + public const int PassportNumberLength = 20; + public const int PhoneNumberLength = 13; + public const int PhoneNumberMinLength = 11; + public const int EmailLength = 254; + public const int PasswordLength = 50; + public const int ApplicantMinAge = 14; + public const int JobTitleLength = 50; + public const int MaxValidDays = 90; +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs new file mode 100644 index 0000000..f0473b6 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/AutoMapper/Profiles/RegisterApplicantRequestProfile.cs @@ -0,0 +1,18 @@ +using AutoMapper; +using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; +using VisaApiClient; + +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles +{ + public class RegisterApplicantRequestProfile : Profile + { + public RegisterApplicantRequestProfile() + { + CreateMap(MemberList.Destination); + + CreateMap(MemberList.Destination); + + CreateMap(MemberList.Destination); + } + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider.cs new file mode 100644 index 0000000..35e9e91 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/DateTimeProvider.cs @@ -0,0 +1,7 @@ +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services +{ + public class DateTimeProvider : IDateTimeProvider + { + public DateTime Now() => DateTime.Now; + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/IDateTimeProvider.cs b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/IDateTimeProvider.cs new file mode 100644 index 0000000..d0f7596 --- /dev/null +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Infrastructure/Services/IDateTimeProvider.cs @@ -0,0 +1,7 @@ +namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services +{ + public interface IDateTimeProvider + { + DateTime Now(); + } +} diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/MainLayout.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/MainLayout.razor index c44193d..72784d4 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/MainLayout.razor +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/MainLayout.razor @@ -5,11 +5,7 @@
-
- About -
- -
+
@Body
diff --git a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/NavMenu.razor b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/NavMenu.razor index b03233d..0a20ac1 100644 --- a/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/NavMenu.razor +++ b/SchengenVisaApi/BlazorWebAssemblyVisaApiClient/Layout/NavMenu.razor @@ -1,6 +1,6 @@