Files
SomniaGuestLog/src/Somnia.GuestLog/Components/Forms/StayEntryForm.razor
T
Daniel-Garmig 0de4e1ba10 GuestLog - General Improvements.
- GuestDocument details - Added navigation to details for stays.
- StayEntry details - Added dialog to see details of GuestDocuments.
- StayEntry List - Added filter for result table.
- StayEntry New - Show suggested guests on GuestSearchDialog so no searchs are required in some cases.
- NavMenu - Removed default navigation links.
2026-08-18 22:17:16 +02:00

260 lines
9.6 KiB
Plaintext

@using System.Diagnostics
@using FluentValidation;
@using Somnia.GuestLog.Models.DTOs;
@using Somnia.GuestLog.Services;
@using Somnia.GuestLog.Validators;
@inject IDataListService dataListService;
@inject IValidator<StayEntryDTO> stayValidator;
@inject IDialogService dialogService;
@inject ISnackbar snackbar
<MudForm @ref="@_form" Model="@Model" Validation="@((stayValidator as StayEntryDTOValidator)!.ValidateValue)"
ReadOnly="@ReadOnly">
<MudGrid>
<MudItem xs="12" xl=6>
<MudPaper Class="pa-4" Elevation="3" Height="100%">
<MudText Typo="Typo.subtitle1" Align="Align.Center">
@LanguageLocale.control_StayEntryForm_sectionDetails
</MudText>
<MudDivider DividerType="DividerType.Middle" Class="mb-4" />
<MudStack Row style="@FieldMarginY">
<MudDatePicker @bind-Date="Model.DateIn" For="@(() => Model.DateIn)"
Label="@LanguageLocale.dto_StayEntry_DateIn" Clearable OpenTo="OpenTo.Date" Editable />
<MudTimePicker @bind-Time="TimeIn" Label=" " Editable />
<MudDatePicker @bind-Date="Model.DateOut" For="@(() => Model.DateOut)"
Label="@LanguageLocale.dto_StayEntry_DateOut" Clearable OpenTo="OpenTo.Date" Editable />
<MudTimePicker @bind-Time="TimeOut" Label=" " Editable />
</MudStack>
<MudStack Row style="@FieldMarginY">
<MudTextField @bind-Value="Model.RoomCount" For="@(() => Model.RoomCount)"
Label="@LanguageLocale.dto_StayEntry_RoomCount" InputType="InputType.Number" FullWidth />
<MudTextField @bind-Value="Model.RoomNumber" For="@(() => Model.RoomNumber)"
Label="@LanguageLocale.dto_StayEntry_RoomNumber" FullWidth />
<MudSelect @bind-Value="Model.PaymentMethod" For="@(() => Model.PaymentMethod)"
Label="@LanguageLocale.dto_StayEntry_PaymentMethod" FullWidth>
@foreach (string payment in PaymentMethodSet)
{
<MudSelectItem Value="payment">
@dataListService.GetLocalizedValue(GuestConsts.DataList_PaymentMethods, payment)
</MudSelectItem>
}
</MudSelect>
</MudStack>
</MudPaper>
</MudItem>
<MudItem xs="12" xl=6>
<MudPaper Class="pa-4" Elevation="3" Height="100%" Width="100%">
<MudText Typo="Typo.subtitle1" Align="Align.Center">
@LanguageLocale.control_StayEntryForm_sectionGuests
</MudText>
<MudDivider DividerType="DividerType.Middle" Class="mb-4" />
@if (!ReadOnly)
{
<MudStack Row style="@FieldMarginY">
<MudButton OnClick="BtnAddGuest" StartIcon="@Icons.Material.Filled.Add">
@LanguageLocale.control_StayEntryForm_btnAddGuest
</MudButton>
</MudStack>
}
<MudTable Items="@Model.GuestDocuments" Hover="true">
<HeaderContent>
<MudTh>@LanguageLocale.dto_GuestDocument_DocumentType</MudTh>
<MudTh>@LanguageLocale.dto_GuestDocument_DocumentNum</MudTh>
<MudTh>@LanguageLocale.dto_GuestDocument_Name</MudTh>
<MudTh>@LanguageLocale.dto_GuestDocument_Surname</MudTh>
<MudTh>@LanguageLocale.dto_GuestDocument_Surname2</MudTh>
<MudTh>@LanguageLocale.general_actions</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="@LanguageLocale.dto_GuestDocument_DocumentType">
@context.DocumentType
</MudTd>
<MudTd DataLabel="@LanguageLocale.dto_GuestDocument_DocumentNum">
@context.DocumentNum
</MudTd>
<MudTd DataLabel="@LanguageLocale.dto_GuestDocument_Name">
@context.Name
</MudTd>
<MudTd DataLabel="@LanguageLocale.dto_GuestDocument_Surname" HideSmall="true">
@context.Surname
</MudTd>
<MudTd DataLabel="@LanguageLocale.dto_GuestDocument_Surname2" HideSmall="true">
@context.Surname2
</MudTd>
@if (!ReadOnly)
{
<MudTd DataLabel="@LanguageLocale.general_actions">
<MudIconButton Icon="@Icons.Material.Filled.Delete"
OnClick="@(() => BtnDeleteGuest(context.DocumentType!, context.DocumentNum!))" />
</MudTd>
}
@if (ReadOnly)
{
<MudTd DataLabel="@LanguageLocale.general_actions">
<MudIconButton Icon="@Icons.Material.Filled.Info"
OnClick="@(() => BtnViewGuestDetails(context))" />
</MudTd>
}
</RowTemplate>
</MudTable>
</MudPaper>
</MudItem>
</MudGrid>
</MudForm>
@code {
[Parameter]
public StayEntryDTO Model { private get; set; } = new();
[Parameter]
public bool ReadOnly { get; set; } = false;
private TimeSpan? TimeIn = DateTime.Now.TimeOfDay;
private TimeSpan? TimeOut = new(hours: 12, minutes: 0, seconds: 0);
private MudForm _form = null!;
private const string FieldMarginY = "margin-block: 0.5em";
private IEnumerable<string> PaymentMethodSet
{
get
{
if (field is null)
{
field = dataListService.GetDataListByName(GuestConsts.DataList_PaymentMethods);
}
return field;
}
}
protected override void OnInitialized()
{
Model.DateIn = DateTime.Today;
}
#region Public Methods
public async Task<bool> ValidateForm()
{
await _form.ValidateAsync();
if (Model.GuestDocuments is null || Model.GuestDocuments.Count == 0)
{
snackbar.Add("At least 1 guest is required!", MudBlazor.Severity.Warning);
return false;
}
return _form.IsValid;
}
public StayEntryDTO GetModel()
{
//Update model times.
Model.DateIn = GetDateTimeFromDateAndTime(Model.DateIn, TimeIn);
Model.DateOut = GetDateTimeFromDateAndTime(Model.DateOut, TimeOut);
return Model;
}
#endregion
private static DateTime? GetDateTimeFromDateAndTime(DateTime? date, TimeSpan? time)
{
DateOnly? dateOnly = date is not null ? DateOnly.FromDateTime(date.Value) : null;
TimeOnly? timeOnly = time is not null ? TimeOnly.FromTimeSpan(time.Value) : null;
if (dateOnly is not null && timeOnly is not null)
{
return new DateTime(dateOnly.Value, timeOnly.Value);
}
return null;
}
#region Event Handlers
private async Task BtnAddGuest()
{
DialogOptions dialogOptions = new()
{
MaxWidth = MaxWidth.Medium,
FullWidth = true,
BackdropClick = false,
CloseOnEscapeKey = true,
};
var dialog = await dialogService.ShowAsync<GuestDocumentSearchDialog>(title: "", options: dialogOptions);
DialogResult? result = await dialog.Result;
if (result is null || result.Canceled)
{
return;
}
GuestDocumentDTO? resultData = await dialog.GetReturnValueAsync<GuestDocumentDTO>();
if (resultData is null)
{
snackbar.Add("Error! No Guest Document selected!", MudBlazor.Severity.Error);
return;
}
//Check if this guest is already added.
if (Model.GuestDocuments is not null && Model.GuestDocuments.Count > 0)
{
bool alreadyAdded = Model.GuestDocuments.Any(e => e.DocumentType == resultData.DocumentType
&& e.DocumentNum == resultData.DocumentNum);
if (alreadyAdded)
{
snackbar.Add("GuestDocument already added!", MudBlazor.Severity.Warning);
return;
}
}
//Init List.
if (Model.GuestDocuments is null)
{
Model.GuestDocuments = [];
}
Model.GuestDocuments.Add(resultData);
}
private void BtnDeleteGuest(string docType, string docNum)
{
Debug.Assert(Model.GuestDocuments is not null);
//Filter out given GuestDocument from model.
Model.GuestDocuments = Model.GuestDocuments
.Where(e => !(e.DocumentType == docType && e.DocumentNum == docNum))
.ToList();
}
private async Task BtnViewGuestDetails(GuestDocumentDTO item)
{
var parameters =
new DialogParameters<GuestDocDetailsDialog> { { x => x.DocumentDTO, item } };
var options = new DialogOptions()
{
FullScreen = true,
CloseButton = true,
CloseOnEscapeKey = true,
};
await dialogService.ShowAsync<GuestDocDetailsDialog>("GuestDoc Details", parameters, options);
}
#endregion
}