SHA256
GuestLog - GuestDocumentList - Added filter for GuestDocuments.
This commit is contained in:
@@ -13,32 +13,53 @@
|
|||||||
<PageTitle>Somnia - Guest Docs</PageTitle>
|
<PageTitle>Somnia - Guest Docs</PageTitle>
|
||||||
|
|
||||||
<MudStack Row="true" Class="my-4">
|
<MudStack Row="true" Class="my-4">
|
||||||
<MudText Typo="Typo.h4" GutterBottom="true">Guest Documents</MudText>
|
<MudText Typo="Typo.h4" GutterBottom="true">@LanguageLocale.page_GuestDocList_pageTitle</MudText>
|
||||||
<MudSpacer />
|
<MudSpacer />
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Success" Size="Size.Small" StartIcon="@Icons.Material.Filled.Add"
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small"
|
||||||
|
StartIcon="@Icons.Material.Filled.Search" OnClick="() => SearchDataAsync()">
|
||||||
|
@LanguageLocale.general_btnSearch
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small" StartIcon="@Icons.Material.Filled.Add"
|
||||||
OnClick="() => BtnNewGuest()">
|
OnClick="() => BtnNewGuest()">
|
||||||
@LanguageLocale.page_GuestDocList_btnNewGuest
|
@LanguageLocale.page_GuestDocList_btnNewGuest
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
<MudSelect T="string" MultiSelection="true" FullWidth="true" Dense="true" Clearable="true" Margin="@Margin.Dense"
|
<MudPaper Class="pa-4 my-4" Elevation="2" Height="100%">
|
||||||
Class="filter-input category-filter" Label="Module" Placeholder="Select Modules"
|
<MudForm Model="@docFilter">
|
||||||
SelectedValuesChanged="@FilterModuleValuesChanged">
|
<MudStack Row Breakpoint="Breakpoint.LgAndDown" StretchItems="StretchItems.All">
|
||||||
@foreach (var module in _moduleList)
|
<MudStack Row style="margin-block: 0.2em;">
|
||||||
{
|
<MudSelect @bind-Value="docFilter.DocumentType" For="@(() => docFilter.DocumentType)"
|
||||||
<MudSelectItem T="string" Value="@module">@module</MudSelectItem>
|
Label="@LanguageLocale.dto_GuestDocument_DocumentType">
|
||||||
}
|
@foreach (string docType in dataListService.GetDataListByName(GuestConsts.DataList_DocumentTypes))
|
||||||
</MudSelect>
|
{
|
||||||
|
<MudSelectItem Value="docType">
|
||||||
|
@dataListService.GetLocalizedValue(GuestConsts.DataList_DocumentTypes, docType)
|
||||||
|
</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
<MudTextField @bind-Value="docFilter.DocumentNumber" For="@(() => docFilter.DocumentNumber)"
|
||||||
|
Label="@LanguageLocale.dto_GuestDocument_DocumentNum" />
|
||||||
|
</MudStack>
|
||||||
|
<MudStack Row style="margin-block: 0.2em;">
|
||||||
|
<MudTextField @bind-Value="docFilter.Name" For="@(() => docFilter.Name)"
|
||||||
|
Label="@LanguageLocale.dto_GuestDocument_Name"
|
||||||
|
HelperText="@LanguageLocale.general_wildcardHelperText" HelperTextOnFocus="true" />
|
||||||
|
<MudTextField @bind-Value="docFilter.Surname" For="@(() => docFilter.Surname)"
|
||||||
|
Label="@LanguageLocale.dto_GuestDocument_Surname"
|
||||||
|
HelperText="@LanguageLocale.general_wildcardHelperText" HelperTextOnFocus="true" />
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
</MudForm>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
<MudDataGrid @ref="_dataGrid" T="GuestDocumentDTO" Items="@guestDocList" Loading="@_dataLoading" ReadOnly="true"
|
<MudDataGrid @ref="_dataGrid" T="GuestDocumentDTO" Items="@guestDocList" Loading="@_dataLoading" ReadOnly="true"
|
||||||
Hideable="true" ColumnsPanelReordering="true">
|
Hideable="true" ColumnsPanelReordering="true" Elevation="2">
|
||||||
<ToolBarContent>
|
<ToolBarContent>
|
||||||
<MudText Typo="Typo.subtitle1">Document List</MudText>
|
<MudText Typo="Typo.subtitle1">@LanguageLocale.page_GuestDocList_documentList</MudText>
|
||||||
<MudStack Class="ml-auto" Row="true" AlignItems="AlignItems.End">
|
<MudStack Class="ml-auto" Row="true" AlignItems="AlignItems.Center">
|
||||||
<MudButton StartIcon="@Icons.Material.Outlined.Refresh" Variant="Variant.Outlined" Size="Size.Small"
|
<MudCheckBox @bind-Value="_showAllData" Label="@LanguageLocale.page_GuestDocList_showAllElements"
|
||||||
OnClick="() => LoadDataAsync()">
|
LabelPlacement="Placement.Start" />
|
||||||
@LanguageLocale.general_reloadData
|
|
||||||
</MudButton>
|
|
||||||
<MudButton StartIcon="@Icons.Material.Outlined.ViewColumn" Variant="Variant.Outlined" Size="Size.Small"
|
<MudButton StartIcon="@Icons.Material.Outlined.ViewColumn" Variant="Variant.Outlined" Size="Size.Small"
|
||||||
OnClick="(args) => BtnConfigureColumnsClick(args)">
|
OnClick="(args) => BtnConfigureColumnsClick(args)">
|
||||||
@LanguageLocale.general_ConfigureColumns
|
@LanguageLocale.general_ConfigureColumns
|
||||||
@@ -67,9 +88,13 @@
|
|||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
|
<PagerContent>
|
||||||
|
<MudDataGridPager T="GuestDocumentDTO" />
|
||||||
|
</PagerContent>
|
||||||
</MudDataGrid>
|
</MudDataGrid>
|
||||||
|
|
||||||
<MudMessageBox @ref="_msgBoxConfirmDelete" Title="Warning" CancelText="Cancel">
|
<MudMessageBox @ref="_msgBoxConfirmDelete" Title="@LanguageLocale.general_confirmTitle"
|
||||||
|
CancelText="@LanguageLocale.general_btnCancel">
|
||||||
<MessageContent>
|
<MessageContent>
|
||||||
@LanguageLocale.general_confirmDeleteMsg
|
@LanguageLocale.general_confirmDeleteMsg
|
||||||
</MessageContent>
|
</MessageContent>
|
||||||
@@ -85,8 +110,10 @@
|
|||||||
private IEnumerable<GuestDocumentDTO> guestDocList = [];
|
private IEnumerable<GuestDocumentDTO> guestDocList = [];
|
||||||
|
|
||||||
private bool _dataLoading = true;
|
private bool _dataLoading = true;
|
||||||
private HashSet<string> _moduleList = [];
|
private bool _showAllData = false;
|
||||||
private HashSet<string> _selectedModuleList = [];
|
private const int resultLimit = 200;
|
||||||
|
|
||||||
|
private GuestDocFilterDTO docFilter = new GuestDocFilterDTO();
|
||||||
|
|
||||||
private MudDataGrid<GuestDocumentDTO> _dataGrid = null!;
|
private MudDataGrid<GuestDocumentDTO> _dataGrid = null!;
|
||||||
private MudMessageBox _msgBoxConfirmDelete = null!;
|
private MudMessageBox _msgBoxConfirmDelete = null!;
|
||||||
@@ -95,17 +122,24 @@
|
|||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await LoadDataAsync(showMsg: false);
|
await LoadDataAsync(showMsg: false);
|
||||||
|
|
||||||
@* _moduleList = guestDocList.Select(e => e.Module).ToHashSet(); *@
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Data Loading
|
#region Data Loading
|
||||||
|
|
||||||
|
private async Task SearchDataAsync()
|
||||||
|
{
|
||||||
|
docFilter.Name = docFilter.Name?.ToUpper();
|
||||||
|
docFilter.Surname = docFilter.Surname?.ToUpper();
|
||||||
|
|
||||||
|
await LoadDataAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task LoadDataAsync(bool showMsg = true)
|
private async Task LoadDataAsync(bool showMsg = true)
|
||||||
{
|
{
|
||||||
_dataLoading = true;
|
_dataLoading = true;
|
||||||
|
|
||||||
guestDocList = await GuestDocService.GetDtoListAsync();
|
int dataLimit = _showAllData ? 0 : resultLimit;
|
||||||
|
guestDocList = await GuestDocService.GetDtoListByFilterAsync(filter: docFilter, limit: dataLimit);
|
||||||
|
|
||||||
if (showMsg)
|
if (showMsg)
|
||||||
{
|
{
|
||||||
@@ -118,13 +152,6 @@
|
|||||||
|
|
||||||
#region Event Handlers
|
#region Event Handlers
|
||||||
|
|
||||||
private async Task FilterModuleValuesChanged(IReadOnlyCollection<string> newValues)
|
|
||||||
{
|
|
||||||
_selectedModuleList = [.. newValues];
|
|
||||||
|
|
||||||
await LoadDataAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task BtnConfigureColumnsClick(MouseEventArgs args)
|
private async Task BtnConfigureColumnsClick(MouseEventArgs args)
|
||||||
{
|
{
|
||||||
_dataGrid.ShowColumnsPanel(args);
|
_dataGrid.ShowColumnsPanel(args);
|
||||||
|
|||||||
@@ -8,9 +8,6 @@ public static class GuestConsts
|
|||||||
public const string Page_GuestDocs_Detail = "/guest-documents/d/{docId}";
|
public const string Page_GuestDocs_Detail = "/guest-documents/d/{docId}";
|
||||||
|
|
||||||
|
|
||||||
public const string regexPattern_phoneNum = @"\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}";
|
|
||||||
|
|
||||||
|
|
||||||
public const string DataList_DocumentTypes = "DocumentType";
|
public const string DataList_DocumentTypes = "DocumentType";
|
||||||
public const string DataList_GenderOptions = "GenderOption";
|
public const string DataList_GenderOptions = "GenderOption";
|
||||||
public const string DataList_CountryCodes = "CountryCode";
|
public const string DataList_CountryCodes = "CountryCode";
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Somnia.GuestLog.Models.DTOs;
|
||||||
|
|
||||||
|
public class GuestDocFilterDTO
|
||||||
|
{
|
||||||
|
public string? DocumentType { get; set; }
|
||||||
|
public string? DocumentNumber { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Surname { get; set; }
|
||||||
|
|
||||||
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -147,6 +147,7 @@
|
|||||||
<data name="general.inProgressMsg" xml:space="preserve"><value>In Progress...</value></data>
|
<data name="general.inProgressMsg" xml:space="preserve"><value>In Progress...</value></data>
|
||||||
<data name="general.ConfigureColumns" xml:space="preserve"><value>Configure Columns</value></data>
|
<data name="general.ConfigureColumns" xml:space="preserve"><value>Configure Columns</value></data>
|
||||||
<data name="general.confirmDeleteMsg" xml:space="preserve"><value>Deleting can not be undone!</value></data>
|
<data name="general.confirmDeleteMsg" xml:space="preserve"><value>Deleting can not be undone!</value></data>
|
||||||
|
<data name="general.confirmTitle" xml:space="preserve"><value>Confirm?</value></data>
|
||||||
<data name="general.btnDelete" xml:space="preserve"><value>Delete</value></data>
|
<data name="general.btnDelete" xml:space="preserve"><value>Delete</value></data>
|
||||||
<data name="general.btnCreate" xml:space="preserve"><value>Create</value></data>
|
<data name="general.btnCreate" xml:space="preserve"><value>Create</value></data>
|
||||||
<data name="general.btnEdit" xml:space="preserve"><value>Edit</value></data>
|
<data name="general.btnEdit" xml:space="preserve"><value>Edit</value></data>
|
||||||
@@ -155,8 +156,12 @@
|
|||||||
<data name="general.btnSearch" xml:space="preserve"><value>Search</value></data>
|
<data name="general.btnSearch" xml:space="preserve"><value>Search</value></data>
|
||||||
<data name="general.btnSave" xml:space="preserve"><value>Save</value></data>
|
<data name="general.btnSave" xml:space="preserve"><value>Save</value></data>
|
||||||
<data name="general.btnCancel" xml:space="preserve"><value>Cancel</value></data>
|
<data name="general.btnCancel" xml:space="preserve"><value>Cancel</value></data>
|
||||||
|
<data name="general.wildcardHelperText" xml:space="preserve"><value>Use '%' as wildcard</value></data>
|
||||||
|
|
||||||
|
<data name="page.GuestDocList.pageTitle" xml:space="preserve"><value>Guest Documents</value></data>
|
||||||
|
<data name="page.GuestDocList.documentList" xml:space="preserve"><value>Document List</value></data>
|
||||||
<data name="page.GuestDocList.btnNewGuest" xml:space="preserve"><value>New Guest</value></data>
|
<data name="page.GuestDocList.btnNewGuest" xml:space="preserve"><value>New Guest</value></data>
|
||||||
|
<data name="page.GuestDocList.showAllElements" xml:space="preserve"><value>Show all elements</value></data>
|
||||||
|
|
||||||
<data name="page.GuestDocNew.msgAlreadyExists" xml:space="preserve"><value>This Guest Document Already exists!!</value></data>
|
<data name="page.GuestDocNew.msgAlreadyExists" xml:space="preserve"><value>This Guest Document Already exists!!</value></data>
|
||||||
<data name="page.GuestDocNew.btnGoExistingDoc" xml:space="preserve"><value>Go to existing document</value></data>
|
<data name="page.GuestDocNew.btnGoExistingDoc" xml:space="preserve"><value>Go to existing document</value></data>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Somnia.GuestLog.Infrastructure;
|
using Somnia.GuestLog.Infrastructure;
|
||||||
using Somnia.GuestLog.Models.DTOs;
|
using Somnia.GuestLog.Models.DTOs;
|
||||||
using Somnia.GuestLog.Models.Entities;
|
using Somnia.GuestLog.Models.Entities;
|
||||||
|
using Somnia.GuestLog.Utils;
|
||||||
|
|
||||||
namespace Somnia.GuestLog.Services;
|
namespace Somnia.GuestLog.Services;
|
||||||
|
|
||||||
@@ -127,6 +128,40 @@ public class GuestDocumentService(
|
|||||||
return dbList.Select(x => GetDtoFromDb(x));
|
return dbList.Select(x => GetDtoFromDb(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get GuestDocumentDTO from DB with the given filters.
|
||||||
|
/// Result count can be limited for perfomance reasons.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filter">Filters to use</param>
|
||||||
|
/// <param name="limit">Result count. Set to 0 for unlimited results</param>
|
||||||
|
/// <returns>Filtered GuestDocumentDTO result list</returns>
|
||||||
|
public async Task<IEnumerable<GuestDocumentDTO>> GetDtoListByFilterAsync(GuestDocFilterDTO filter, int limit = 0)
|
||||||
|
{
|
||||||
|
using var dbContext = contextFactory.CreateDbContext();
|
||||||
|
|
||||||
|
var query = dbContext.GuestDocuments.AsQueryable();
|
||||||
|
|
||||||
|
query = query.WhereIf(!string.IsNullOrEmpty(filter.DocumentType),
|
||||||
|
e => e.DocumentType == filter.DocumentType);
|
||||||
|
query = query.WhereIf(!string.IsNullOrEmpty(filter.DocumentNumber),
|
||||||
|
e => e.DocumentNum == filter.DocumentNumber);
|
||||||
|
|
||||||
|
query = query.WhereIf(!string.IsNullOrEmpty(filter.Name),
|
||||||
|
e => EF.Functions.Like(e.Name, filter.Name));
|
||||||
|
query = query.WhereIf(!string.IsNullOrEmpty(filter.Surname),
|
||||||
|
e => EF.Functions.Like(e.Surname, filter.Surname));
|
||||||
|
|
||||||
|
query = query.OrderByDescending(e => e.UpdateTime);
|
||||||
|
|
||||||
|
if (limit > 0)
|
||||||
|
{
|
||||||
|
query = query.Take(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbList = await query.ToListAsync();
|
||||||
|
|
||||||
|
return dbList.Select(x => GetDtoFromDb(x));
|
||||||
|
}
|
||||||
|
|
||||||
public GuestDocumentDTO GetDtoFromDb(GuestDocument dbItem)
|
public GuestDocumentDTO GetDtoFromDb(GuestDocument dbItem)
|
||||||
{
|
{
|
||||||
@@ -154,5 +189,4 @@ public class GuestDocumentService(
|
|||||||
UpdateTime = dbItem.UpdateTime,
|
UpdateTime = dbItem.UpdateTime,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ public interface IGuestDocumentService
|
|||||||
public Task<bool> DeleteDocumentAsync(string docType, string docNum);
|
public Task<bool> DeleteDocumentAsync(string docType, string docNum);
|
||||||
|
|
||||||
public Task<GuestDocumentDTO?> GetDtoByIdAsync(string docType, string docNum);
|
public Task<GuestDocumentDTO?> GetDtoByIdAsync(string docType, string docNum);
|
||||||
|
public Task<IEnumerable<GuestDocumentDTO>> GetDtoListByFilterAsync(GuestDocFilterDTO filter, int limit = 0);
|
||||||
public Task<IEnumerable<GuestDocumentDTO>> GetDtoListAsync();
|
public Task<IEnumerable<GuestDocumentDTO>> GetDtoListAsync();
|
||||||
|
|
||||||
//TODO: Add Filter
|
//TODO: Add Filter
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace Somnia.GuestLog.Utils;
|
||||||
|
|
||||||
|
public static class QueryExtensions
|
||||||
|
{
|
||||||
|
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, bool condition, Expression<Func<T, bool>> predicate)
|
||||||
|
{
|
||||||
|
return condition ? source.Where(predicate) : source;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,4 +12,7 @@ public static partial class RegexUtils
|
|||||||
|
|
||||||
[GeneratedRegex("^[A-Z]{3}[0-9]{6}$")]
|
[GeneratedRegex("^[A-Z]{3}[0-9]{6}$")]
|
||||||
public static partial Regex RegexGuestDocSuportNumber();
|
public static partial Regex RegexGuestDocSuportNumber();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$")]
|
||||||
|
public static partial Regex RegexPhoneNumber();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class GuestDocumentDTOValidator : AbstractValidator<GuestDocumentDTO>
|
|||||||
.When(x => !string.IsNullOrEmpty(x.EmailAddress));
|
.When(x => !string.IsNullOrEmpty(x.EmailAddress));
|
||||||
|
|
||||||
RuleFor(x => x.PhoneNumber)
|
RuleFor(x => x.PhoneNumber)
|
||||||
.Matches(GuestConsts.regexPattern_phoneNum)
|
.Matches(RegexUtils.RegexPhoneNumber()).WithMessage("Invalid format")
|
||||||
.When(x => !string.IsNullOrEmpty(x.PhoneNumber));
|
.When(x => !string.IsNullOrEmpty(x.PhoneNumber));
|
||||||
|
|
||||||
RuleFor(x => x.AddressCountry)
|
RuleFor(x => x.AddressCountry)
|
||||||
|
|||||||
Reference in New Issue
Block a user