GuestLog - User message improvements

- Added UserMessageService to have common methods for showing messages and errors to the user.
- Added Result record so services can return status on operation error (so it can be shown in the UI messages).
- Updated services to use the new Result record.
- Updated pages to use the new IUserMessageService.
This commit is contained in:
2026-08-23 21:57:26 +02:00
parent 0de4e1ba10
commit 511bd023f2
22 changed files with 239 additions and 80 deletions
@@ -1,9 +1,10 @@
@using Somnia.GuestLog.Models.DTOs;
@using Somnia.GuestLog.Services
@using Somnia.GuestLog.Services.AddressQuery;
@inject ILogger<AddressQueryDialog> logger;
@inject IAddressQueryFactory addressQueryFactory;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
<MudDialog @ref="@DialogRef">
<TitleContent>
@@ -112,7 +113,7 @@
catch (Exception ex)
{
logger.LogError(ex, "SearchAddress returned an error!");
Snackbar.Add($"Error searching address: {ex.Message}", Severity.Error);
userMessage.ShowMessage($"Error searching address: {ex.Message}", MessageKind.Error);
}
}
@@ -120,7 +121,7 @@
{
if (SelectedAddressResult is null)
{
Snackbar.Add("Select an address", Severity.Warning);
userMessage.ShowMessage("Select an address", MessageKind.Warning);
return;
}
@@ -2,7 +2,7 @@
@using Somnia.GuestLog.Services
@inject ILogger<AddressQueryDialog> logger;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IGuestDocumentService guestDocumentService;
@@ -108,7 +108,7 @@
catch (Exception ex)
{
logger.LogError(ex, "GuestDocument Search returned an error!");
Snackbar.Add($"Error searching: {ex.Message}", Severity.Error);
userMessage.ShowMessage($"Error searching: {ex.Message}", MessageKind.Error);
}
}
@@ -119,7 +119,7 @@
{
if (filter.IsEmpty)
{
Snackbar.Add("Add some search!", Severity.Warning);
userMessage.ShowMessage("Search can't be empty!", MessageKind.Warning);
return;
}
@@ -131,7 +131,7 @@
{
if (SelectedResult is null)
{
Snackbar.Add("Select a guest document", Severity.Warning);
userMessage.ShowMessage("A guest document must be selected", MessageKind.Warning);
return;
}
@@ -7,7 +7,7 @@
@inject IDataListService dataListService;
@inject IValidator<StayEntryDTO> stayValidator;
@inject IDialogService dialogService;
@inject ISnackbar snackbar
@inject IUserMessageService userMessage
<MudForm @ref="@_form" Model="@Model" Validation="@((stayValidator as StayEntryDTOValidator)!.ValidateValue)"
@@ -149,7 +149,7 @@
if (Model.GuestDocuments is null || Model.GuestDocuments.Count == 0)
{
snackbar.Add("At least 1 guest is required!", MudBlazor.Severity.Warning);
userMessage.ShowMessage("At least 1 guest is required!", MessageKind.Warning);
return false;
}
@@ -205,7 +205,7 @@
if (resultData is null)
{
snackbar.Add("Error! No Guest Document selected!", MudBlazor.Severity.Error);
userMessage.ShowMessage("Error! No Guest Document selected!", MessageKind.Error);
return;
}
@@ -216,7 +216,7 @@
&& e.DocumentNum == resultData.DocumentNum);
if (alreadyAdded)
{
snackbar.Add("GuestDocument already added!", MudBlazor.Severity.Warning);
userMessage.ShowMessage("GuestDocument already added!", MessageKind.Warning);
return;
}
}
@@ -1,11 +1,12 @@
@page "/debug/addrSearch"
@using Somnia.GuestLog.Models.DTOs;
@using Somnia.GuestLog.Services;
@using Somnia.GuestLog.Services.AddressQuery;
@inject ILogger<AddressQuery> logger;
@inject IAddressQueryFactory addressQueryFactory;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
<PageTitle>DEBUG - Address Query</PageTitle>
@@ -89,7 +90,7 @@
catch (Exception ex)
{
logger.LogError(ex, "SearchAddress returned an error!");
Snackbar.Add($"Error searching address: {ex.Message}", Severity.Error);
userMessage.ShowMessage($"Error searching address: {ex.Message}", MessageKind.Error);
}
}
@@ -1,8 +1,10 @@
@page "/debug/empty"
@using Somnia.GuestLog.Services
@inject ILogger<Empty> logger;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
<PageTitle>DEBUG - Empty</PageTitle>
@@ -4,7 +4,7 @@
@using Somnia.GuestLog.Services;
@using Microsoft.AspNetCore.WebUtilities;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
@inject NavigationManager Navigation
@inject IGuestDocumentService guestDocService
@@ -92,7 +92,7 @@
{
if (docId is null)
{
Snackbar.Add("No GuestDocument provided!!", Severity.Error);
userMessage.ShowMessage("No GuestDocument provided!!", MessageKind.Error);
Navigation.NotFound();
return;
}
@@ -100,7 +100,7 @@
GuestDocIdDTO? docIdModel = GuestDocIdDTO.DecodeFromString(docId);
if (docIdModel is null)
{
Snackbar.Add($"Provided GuestDocId can't be decoded: '{docId}'", Severity.Error);
userMessage.ShowMessage($"Provided GuestDocId can't be decoded: '{docId}'", MessageKind.Error);
Navigation.NotFound();
return;
}
@@ -109,7 +109,7 @@
documentModel = await guestDocService.GetDtoByIdAsync(docIdModel.DocumentType, docIdModel.DocumentNum);
if (documentModel is null)
{
Snackbar.Add($"GuestDocument not found with ID: '{docId}'", Severity.Error);
userMessage.ShowMessage($"GuestDocument not found with ID: '{docId}'", MessageKind.Error);
Navigation.NotFound();
return;
}
@@ -138,7 +138,7 @@
private void BtnEdit()
{
Snackbar.Add("Not implemented yet!", Severity.Info);
userMessage.ShowMessage("Not implemented yet!", MessageKind.Info);
}
private void BtnReturn()
@@ -5,7 +5,7 @@
@inject IGuestDocumentService GuestDocService
@inject NavigationManager Navigation
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
@inject IDataListService dataListService;
@@ -101,7 +101,7 @@
if (showMsg)
{
Snackbar.Add("Data loaded from DB", Severity.Info, o => o.VisibleStateDuration = 1000);
userMessage.ShowMessage("Data loaded from DB", MessageKind.Info);
}
_dataLoading = false;
}
@@ -142,14 +142,15 @@
return;
}
bool deleted = await GuestDocService.DeleteDocumentAsync(item);
if (!deleted)
Result deleteResult = await GuestDocService.DeleteDocumentAsync(item);
if (!deleteResult.IsSuccess)
{
Snackbar.Add($"Error deleting document {item.DocumentType}-{item.DocumentNum}", Severity.Error);
string errorMsg = $"Error deleting document {item.DocumentType}-{item.DocumentNum}";
userMessage.ShowResultWithMessage(deleteResult, errorMsg);
return;
}
Snackbar.Add($"Document {item.DocumentType}-{item.DocumentNum} deleted!", Severity.Success);
userMessage.ShowMessage($"Document {item.DocumentType}-{item.DocumentNum} deleted!", MessageKind.Success);
await LoadDataAsync();
}
@@ -4,7 +4,7 @@
@using Somnia.GuestLog.Services;
@using Somnia.GuestLog.Validators;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
@inject NavigationManager Navigation
@inject IGuestDocumentService guestDocService
@@ -129,26 +129,25 @@
bool isFormValid = await _form.ValidateForm();
if (!isFormValid)
{
Snackbar.Add("Invalid Form!", Severity.Error);
userMessage.ShowMessage("Invalid Form!", MessageKind.Warning);
return;
}
GuestDocumentDTO model = _form.Model;
Snackbar.Add($"Document '{model.DocumentNum}' creating...", Severity.Info);
//Show Loading dialog...
var loadingDialog = await DialogService.ShowAsync<LoadingDialog>();
bool isCreated = await guestDocService.CreateDocumentAsync(model);
if (!isCreated)
Result createResult = await guestDocService.CreateDocumentAsync(model);
if (!createResult.IsSuccess)
{
Snackbar.Add($"Error creating Document '{model.DocumentNum}'", Severity.Error);
string errorMsg = $"Error creating Document '{model.DocumentNum}'";
userMessage.ShowResultWithMessage(createResult, errorMsg);
loadingDialog.Close();
return;
}
Snackbar.Add($"Document '{model.DocumentNum}' Created!", Severity.Success);
userMessage.ShowMessage($"Document '{model.DocumentNum}' Created!", MessageKind.Success);
Navigation.NavigateTo(GuestConsts.Page_GuestDocs_List);
}
@@ -156,7 +155,7 @@
{
if (currentPageMode != ePageMode.alreadyExistDoc)
{
Snackbar.Add("Invalid operation!", Severity.Error);
userMessage.ShowMessage("Invalid operation!", MessageKind.Error);
return;
}
@@ -3,7 +3,7 @@
@using Somnia.GuestLog.Models.DTOs;
@using Somnia.GuestLog.Services;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
@inject NavigationManager Navigation
@inject IGuestDocumentService guestDocService
@@ -54,7 +54,7 @@
stayModel = await stayService.GetDtoByIdAsync(StayId, queryConfig: new(IncludeGuests: true));
if (stayModel is null)
{
Snackbar.Add($"Stay not found with ID: '{StayId}'", Severity.Error);
userMessage.ShowMessage($"Stay not found with ID: '{StayId}'", MessageKind.Error);
Navigation.NotFound();
return;
}
@@ -62,7 +62,7 @@
private void BtnEdit()
{
Snackbar.Add("Not implemented yet!", Severity.Info);
userMessage.ShowMessage("Not implemented yet!", MessageKind.Info);
}
private void BtnReturn()
@@ -5,7 +5,7 @@
@inject IStayEntryService StayEntryService
@inject NavigationManager Navigation
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
@inject IDataListService dataListService;
@@ -96,7 +96,7 @@
if (showMsg)
{
Snackbar.Add("Data loaded from DB", Severity.Info, o => o.VisibleStateDuration = 1000);
userMessage.ShowMessage("Data loaded from DB", MessageKind.Info);
}
_dataLoading = false;
}
@@ -131,14 +131,15 @@
return;
}
bool deleted = await StayEntryService.DeleteEntryAsync(item);
if (!deleted)
Result deleteResult = await StayEntryService.DeleteEntryAsync(item);
if (!deleteResult.IsSuccess)
{
Snackbar.Add($"Error deleting Stay {item.Id}", Severity.Error);
string errorMsg = $"Error deleting Stay {item.Id}";
userMessage.ShowResultWithMessage(deleteResult, errorMsg);
return;
}
Snackbar.Add($"Stay {item.Id} deleted!", Severity.Success);
userMessage.ShowMessage($"Stay {item.Id} deleted!", MessageKind.Success);
await LoadDataAsync();
}
@@ -4,7 +4,7 @@
@using Somnia.GuestLog.Services;
@inject ISnackbar Snackbar
@inject IUserMessageService userMessage
@inject IDialogService DialogService
@inject NavigationManager Navigation
@inject IStayEntryService stayService
@@ -45,22 +45,22 @@
bool isFormValid = await _form.ValidateForm();
if (!isFormValid)
{
Snackbar.Add("Invalid Form!", Severity.Warning);
userMessage.ShowMessage("Invalid Form!", MessageKind.Warning);
return;
}
var loadingDialog = await DialogService.ShowAsync<LoadingDialog>();
StayEntryDTO model = _form.GetModel();
bool isCreated = await stayService.CreateEntryAsync(model);
if (!isCreated)
Result createResult = await stayService.CreateEntryAsync(model);
if (!createResult.IsSuccess)
{
Snackbar.Add($"Error creating StayEntry", Severity.Error);
userMessage.ShowResultWithMessage(createResult, $"Error creating StayEntry");
loadingDialog.Close();
return;
}
Snackbar.Add($"StayEntry Created!", Severity.Success);
userMessage.ShowMessage($"StayEntry Created!", MessageKind.Success);
Navigation.NavigateTo(GuestConsts.Page_StayEntry_List);
}
@@ -1,5 +1,6 @@
@using System.Net.Http
@using System.Net.Http.Json
@using System.Linq;
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@@ -15,4 +16,4 @@
@using Somnia.GuestLog.Components.Forms
@using Somnia.GuestLog.Components.Controls
@using Somnia.GuestLog.Resources
@using System.Linq;
@using MessageKind = Somnia.GuestLog.Services.IUserMessageService.MessageKind;