Started CreateApplication.razor
This commit is contained in:
		| @@ -2,9 +2,9 @@ | ||||
| @using System.Reflection | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers | ||||
| @typeparam TItem where TItem : class | ||||
|     @typeparam TMember where TMember : struct, Enum | ||||
| @typeparam TMember where TMember : struct, Enum | ||||
|  | ||||
| <InputSelect TValue="TMember"  @bind-Value="selected"> | ||||
| <InputSelect TValue="TMember" @bind-Value="selected"> | ||||
|     @foreach (var value in enumValues) | ||||
|     { | ||||
|         <option value="@value.Key">@value.Value</option> | ||||
| @@ -16,6 +16,8 @@ | ||||
|  | ||||
|     [Parameter, EditorRequired] public Expression<Func<TItem, TMember>> EnumProperty { get; set; } = null!; | ||||
|  | ||||
|     [Parameter] public Action? OnChanged { get; set; } | ||||
|  | ||||
|     private Dictionary<TMember, string> enumValues = new(); | ||||
|     private PropertyInfo modelMemberInfo = null!; | ||||
|     private TMember selected; | ||||
| @@ -33,12 +35,17 @@ | ||||
|  | ||||
|     protected override void OnAfterRender(bool firstRender) | ||||
|     { | ||||
|         OnValueChanged(); | ||||
|         var current = (TMember)modelMemberInfo.GetValue(Model)!; | ||||
|         if (!current.Equals(selected)) | ||||
|         { | ||||
|             OnValueChanged(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void OnValueChanged() | ||||
|     { | ||||
|         modelMemberInfo.SetValue(Model, selected); | ||||
|         OnChanged?.Invoke(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using VisaApiClient | ||||
|  | ||||
| <div> | ||||
| @@ -22,7 +21,7 @@ | ||||
|     <div > | ||||
|         <label> | ||||
|             Issue date:<br/> | ||||
|             <InputDate DisplayName="Issue date" class="rounded" @bind-Value="Passport.IssueDate" max="DateTimeProvider.Now()"/> | ||||
|             <InputDate DisplayName="Issue date" class="rounded" @bind-Value="Passport.IssueDate" max="@formattedDate"/> | ||||
|         </label><br/> | ||||
|         <ValidationMessage For="() => Passport.IssueDate"></ValidationMessage> | ||||
|     </div><br/> | ||||
| @@ -30,14 +29,14 @@ | ||||
|     <div > | ||||
|         <label> | ||||
|             Expiration date:<br/> | ||||
|             <InputDate DisplayName="Expiration date" class="rounded" @bind-Value="Passport.ExpirationDate" min="DateTimeProvider.Now()"/> | ||||
|             <InputDate DisplayName="Expiration date" class="rounded" @bind-Value="Passport.ExpirationDate" min="@formattedDate"/> | ||||
|         </label><br/> | ||||
|         <ValidationMessage For="() => Passport.ExpirationDate"></ValidationMessage> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private string now = DateTime.Now.ToString("yyyy-MM-dd"); | ||||
|     private string formattedDate = null!; | ||||
|  | ||||
|     [Parameter, EditorRequired] public PassportModel Passport { get; set; } = null!; | ||||
|  | ||||
| @@ -47,6 +46,7 @@ | ||||
|     { | ||||
|         Passport.IssueDate = DateTime.Now; | ||||
|         Passport.ExpirationDate = DateTime.Now; | ||||
|         formattedDate = DateTimeProvider.FormattedNow(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| @using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models | ||||
|  | ||||
| @using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models | ||||
| <div> | ||||
|     <div > | ||||
|         <label > | ||||
|   | ||||
| @@ -1,46 +0,0 @@ | ||||
| <h3>CustomValidation</h3> | ||||
|  | ||||
| @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<string, List<string>> 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(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,33 @@ | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using VisaApiClient | ||||
|  | ||||
| <div> | ||||
|     <label> | ||||
|         Destination Country:<br/> | ||||
|         <InputText DisplayName="Issuer of permission to destination Country" class="rounded" | ||||
|                    @bind-Value="PermissionToDestCountry.Issuer"/> | ||||
|     </label><br/> | ||||
|     <ValidationMessage For="() => PermissionToDestCountry.Issuer"></ValidationMessage><br/> | ||||
|  | ||||
|     <label> | ||||
|         Expiration date:<br/> | ||||
|         <InputDate DisplayName="Expiration date of permission to destination Country" class="rounded" | ||||
|                    @bind-Value="PermissionToDestCountry.ExpirationDate" | ||||
|                    max="@formattedDate"/> | ||||
|     </label><br/> | ||||
|     <ValidationMessage For="() => PermissionToDestCountry.ExpirationDate"></ValidationMessage> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private string formattedDate = null!; | ||||
|  | ||||
|     [Parameter, EditorRequired] public PermissionToDestCountryModel PermissionToDestCountry { get; set; } = null!; | ||||
|  | ||||
|     [Inject] IDateTimeProvider DateTimeProvider { get; set; } = null!; | ||||
|  | ||||
|     protected override void OnInitialized() | ||||
|     { | ||||
|         formattedDate = DateTimeProvider.FormattedNow(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -9,7 +9,7 @@ | ||||
|     [Parameter] | ||||
|     public RenderFragment? ChildContent { get; set; } | ||||
|  | ||||
|     public string StatusText { get; set; } = string.Empty; | ||||
|     public string StatusText { get; private set; } = string.Empty; | ||||
|  | ||||
|     public void SetMessage(string message) | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| using AutoMapper; | ||||
| using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; | ||||
| using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; | ||||
| using VisaApiClient; | ||||
| using PlaceOfWorkModel = BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models.PlaceOfWorkModel; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles | ||||
| { | ||||
| @@ -12,7 +13,7 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.AutoMapper.Profiles | ||||
|  | ||||
|             CreateMap<RegisterRequestModel, RegisterRequest>(MemberList.Destination); | ||||
|  | ||||
|             CreateMap<FluentValidation.Applicants.Models.PlaceOfWorkModel, VisaApiClient.PlaceOfWorkModel>(MemberList.Destination); | ||||
|             CreateMap<PlaceOfWorkModel, VisaApiClient.PlaceOfWorkModel>(MemberList.Destination); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,5 +3,7 @@ | ||||
|     public class DateTimeProvider : IDateTimeProvider | ||||
|     { | ||||
|         public DateTime Now() => DateTime.Now; | ||||
|  | ||||
|         public string FormattedNow() => Now().ToString("yyyy-MM-dd"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,5 +3,7 @@ | ||||
|     public interface IDateTimeProvider | ||||
|     { | ||||
|         DateTime Now(); | ||||
|  | ||||
|         string FormattedNow(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| @page "/applications" | ||||
| @using System.Net | ||||
| @using System.Text | ||||
| @using BlazorWebAssemblyVisaApiClient.Components | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.Auth | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers | ||||
| @using VisaApiClient | ||||
|   | ||||
| @@ -0,0 +1,78 @@ | ||||
| @page "/visaApplications/new" | ||||
| @using BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.FormComponents.Applicants | ||||
| @using VisaApiClient | ||||
| @using BlazorWebAssemblyVisaApiClient.Components | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.FormComponents.VisaApplications | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase | ||||
|  | ||||
| <PageTitle>New Application</PageTitle> | ||||
|  | ||||
| <div class="horizontal-centered-content"> | ||||
|     <h3>New application</h3> | ||||
|     <EditForm class="form" Model="requestModel" OnValidSubmit="TryCreate"> | ||||
|         <ObjectGraphDataAnnotationsValidator/> | ||||
|  | ||||
|         <div class="form-block"> | ||||
|             <h5>Visa</h5> | ||||
|             <label> | ||||
|                 Destination Country:<br/> | ||||
|                 <InputText DisplayName="Destination Country" class="rounded" @bind-Value="requestModel.DestinationCountry"/> | ||||
|             </label><br/> | ||||
|             <ValidationMessage For="() => requestModel.DestinationCountry"></ValidationMessage><br/> | ||||
|  | ||||
|             <label> | ||||
|                 Category: <EnumInputList Model="requestModel" | ||||
|                                          EnumProperty="r => r.VisaCategory" | ||||
|                                          OnChanged="StateHasChanged"/> | ||||
|             </label><br/> | ||||
|             <ValidationMessage For="() => requestModel.VisaCategory"></ValidationMessage><br/> | ||||
|  | ||||
|             <label> | ||||
|                 Number of entries: <EnumInputList Model="requestModel" EnumProperty="r => r.RequestedNumberOfEntries"/> | ||||
|             </label><br/> | ||||
|             <ValidationMessage For="() => requestModel.RequestedNumberOfEntries"></ValidationMessage><br/> | ||||
|  | ||||
|             <label> | ||||
|                 For group: <InputCheckbox @bind-Value="requestModel.IsForGroup"/> | ||||
|             </label><br/> | ||||
|             <ValidationMessage For="() => requestModel.IsForGroup"></ValidationMessage><br/> | ||||
|  | ||||
|             <label> | ||||
|                 Valid for days:<br/> | ||||
|                 <InputNumber DisplayName="Valid days" class="rounded" @bind-Value="requestModel.ValidDaysRequested"/> | ||||
|             </label> | ||||
|             <ValidationMessage For="() => requestModel.ValidDaysRequested"></ValidationMessage><br/> | ||||
|         </div> | ||||
|  | ||||
|         <div class="form-block"> | ||||
|             <fieldset disabled="@(requestModel.VisaCategory is not VisaCategory.Transit)"> | ||||
|                 <h5>Permission to destination Country</h5> | ||||
|                 <PermissionToDestCountryInput PermissionToDestCountry="requestModel.PermissionToDestCountry" /> | ||||
|             </fieldset> | ||||
|         </div><br/> | ||||
|  | ||||
|         <input type="submit" class="btn-outline-primary" value="Register"/> | ||||
|         <Status @ref="status"/> | ||||
|     </EditForm> | ||||
| </div> | ||||
|  | ||||
|  | ||||
| @code { | ||||
|     private VisaApplicationCreateRequestModel requestModel = new(); | ||||
|     private Status status = null!; | ||||
|  | ||||
|     [Inject] IDateTimeProvider DateTimeProvider { get; set; } = null!; | ||||
|  | ||||
|     protected override void OnInitialized() | ||||
|     { | ||||
|         requestModel.PermissionToDestCountry!.ExpirationDate = DateTimeProvider.Now(); | ||||
|     } | ||||
|  | ||||
|     private static void TryCreate() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -4,13 +4,12 @@ | ||||
| @using AutoMapper | ||||
| @using VisaApiClient | ||||
| @using BlazorWebAssemblyVisaApiClient.Components.FormComponents.Applicants | ||||
| @using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services | ||||
| @using global::FluentValidation | ||||
| @using Newtonsoft.Json | ||||
| @using Newtonsoft.Json.Linq | ||||
| @using BlazorWebAssemblyVisaApiClient.Components | ||||
| @using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider | ||||
| @using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models | ||||
| @inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase | ||||
|  | ||||
| <PageTitle>Registration</PageTitle> | ||||
| @@ -60,7 +59,7 @@ | ||||
|                 <ValidationMessage For="() => requestModel.CityOfBirth"></ValidationMessage><br/> | ||||
|                 <label> | ||||
|                     Birth date:<br/> | ||||
|                     <InputDate DisplayName="Birth date" class="rounded" @bind-Value="requestModel.BirthDate" max="@DateTimeProvider.Now()"/> | ||||
|                     <InputDate DisplayName="Birth date" class="rounded" @bind-Value="requestModel.BirthDate" max="@DateTimeProvider.FormattedNow()"/> | ||||
|                 </label><br/> | ||||
|                 <ValidationMessage For="() => requestModel.BirthDate"></ValidationMessage> | ||||
|             </div> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| using System.Reflection; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using FluentValidation; | ||||
| using Microsoft.AspNetCore.Components.Web; | ||||
| using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models | ||||
| { | ||||
|     /// Model of place of work with attributes required for validation to work | ||||
|     public class PlaceOfWorkModel | ||||
| @@ -3,7 +3,7 @@ using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Converters; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models | ||||
| { | ||||
|     /// Model of request with attributes required for validation to work | ||||
|     public class RegisterApplicantRequestModel | ||||
| @@ -1,7 +1,7 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models | ||||
| { | ||||
|     /// Model of request with attributes required for validation to work | ||||
|     public class RegisterRequestModel | ||||
| @@ -1,7 +1,7 @@ | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Validators; | ||||
| 
 | ||||
| public class NameModelValidator : AbstractValidator<NameModel> | ||||
| { | ||||
| @@ -1,9 +1,8 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Validators; | ||||
| 
 | ||||
| public class PassportModelValidator : AbstractValidator<PassportModel> | ||||
| { | ||||
| @@ -1,7 +1,7 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; | ||||
| using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; | ||||
| using FluentValidation; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Validators; | ||||
| 
 | ||||
| public class PlaceOfWorkModelValidator : AbstractValidator<PlaceOfWorkModel> | ||||
| { | ||||
| @@ -1,11 +1,10 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.DateTimeProvider; | ||||
| using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
| using PlaceOfWorkModel = BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models.PlaceOfWorkModel; | ||||
| using PlaceOfWorkModel = BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models.PlaceOfWorkModel; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Validators; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Applicants.Validators; | ||||
| 
 | ||||
| public class RegisterApplicantRequestValidator : AbstractValidator<RegisterApplicantRequestModel> | ||||
| { | ||||
| @@ -1,7 +1,7 @@ | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Common; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Common; | ||||
| 
 | ||||
| public class AuthDataValidator : AbstractValidator<AuthData> | ||||
| { | ||||
| @@ -1,8 +1,8 @@ | ||||
| using BlazorWebAssemblyVisaApiClient.FluentValidation.Applicants.Models; | ||||
| using BlazorWebAssemblyVisaApiClient.Validation.Applicants.Models; | ||||
| using FluentValidation; | ||||
| using VisaApiClient; | ||||
| 
 | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation.Common; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.Common; | ||||
| 
 | ||||
| public class RegisterRequestModelValidator : AbstractValidator<RegisterRequestModel> | ||||
| { | ||||
| @@ -1,4 +1,4 @@ | ||||
| namespace BlazorWebAssemblyVisaApiClient.FluentValidation; | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation; | ||||
| 
 | ||||
| public static class ConfigurationConstraints | ||||
| { | ||||
| @@ -0,0 +1,40 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using VisaApiClient; | ||||
|  | ||||
| namespace BlazorWebAssemblyVisaApiClient.Validation.VisaApplications.Models | ||||
| { | ||||
|     /// Model for request for data annotations validation to work | ||||
|     public class VisaApplicationCreateRequestModel | ||||
|     { | ||||
|         [ValidateComplexType] | ||||
|         public ReentryPermitModel? ReentryPermit { get; set; } = new(); | ||||
|  | ||||
|         [Required] | ||||
|         [MaxLength(ConfigurationConstraints.CountryNameLength)] | ||||
|         public string DestinationCountry { get; set; } = default!; | ||||
|  | ||||
|         [Required] | ||||
|         public VisaCategory VisaCategory { get; set; } | ||||
|  | ||||
|         [Required] | ||||
|         public bool IsForGroup { get; set; } | ||||
|  | ||||
|         [Required] | ||||
|         public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; } | ||||
|  | ||||
|         [Required] | ||||
|         [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!; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user