Compare commits

...

6 Commits

Author SHA1 Message Date
a.beging@eas-solutions.de
8df4abc8a3 Fix EditProspectDialog: update NumericEdit to handle null Foodsharing-ID correctly
All checks were successful
Build And Push Dev Docker Image / docker (push) Successful in 2m15s
2026-05-12 10:07:11 +02:00
a.beging@eas-solutions.de
bf69880d5f Fix GetAttributeOfType method: add check for empty member info to prevent null reference exceptions 2026-05-12 10:07:01 +02:00
a.beging@eas-solutions.de
c6178ecacd Fix User class: enhance GroupsList property to safely parse UserGroup enums 2026-05-12 10:06:52 +02:00
troogs
935f026c75 Fix and harden prospect creation against Blazor runtime crashes
All checks were successful
Build And Push Dev Docker Image / docker (push) Successful in 3m3s
- Handle empty numeric input safely with nullable integer binding.

- Add semaphore locks to prevent double-click invocation errors on mobile.

- Implement global exception handling and user notifications for prospect operations.
2026-05-10 19:47:39 +02:00
troogs
e1c57967e4 Fix EditProspectDialog and Prospects: prevent multiple modal openings during save and create operations 2026-05-10 19:40:06 +02:00
troogs
c702e8dbd5 Fix EditProspectDialog: update NumericEdit to handle nullable Foodsharing-ID 2026-05-10 19:40:00 +02:00
5 changed files with 70 additions and 17 deletions

View File

@@ -42,7 +42,12 @@ namespace FoodsharingSiegen.Contracts.Entity
{
if (string.IsNullOrWhiteSpace(Groups)) return new List<UserGroup>();
var stringList = Groups.Split(",");
var enumList = stringList.Where(x => !string.IsNullOrWhiteSpace(x)).Select(Enum.Parse<UserGroup>).ToList();
var enumList = stringList
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => Enum.TryParse<UserGroup>(x.Trim(), out var result) ? result : (UserGroup?)null)
.Where(x => x.HasValue)
.Select(x => x!.Value)
.ToList();
return enumList;
}
set => Groups = string.Join(",", value);

View File

@@ -34,6 +34,7 @@ namespace FoodsharingSiegen.Contracts.Helper
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
if (memInfo.Length == 0) return null;
var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return attributes.Length > 0 ? (T)attributes[0] : null;
}

View File

@@ -11,7 +11,7 @@
<div class="col">
<Field>
<FieldLabel>Foodsharing-ID</FieldLabel>
<NumericEdit TValue="int" @bind-Value="Prospect.FsId"></NumericEdit>
<NumericEdit TValue="int?" Value="@(Prospect.FsId == 0 ? (int?)null : Prospect.FsId)" ValueChanged="@((int? v) => Prospect.FsId = v ?? 0)"></NumericEdit>
</Field>
</div>
</div>

View File

@@ -82,23 +82,52 @@ namespace FoodsharingSiegen.Server.Dialogs
#region Private Method SaveClick
private bool _isSaving;
/// <summary>
/// Saves the click (a. beging, 31.05.2022)
/// </summary>
private async Task SaveClick()
{
if (IsUpdateMode)
if (_isSaving) return;
_isSaving = true;
try
{
var updateR = await ProspectService.UpdateAsync(Prospect);
if (updateR.Success && OnSuccess != null) await OnSuccess.Invoke();
if (IsUpdateMode)
{
var updateR = await ProspectService.UpdateAsync(Prospect);
if (updateR.Success)
{
if (OnSuccess != null) await OnSuccess.Invoke();
await ModalService.Hide();
}
else
{
await Notification.Error(updateR.Exception?.Message ?? "Unbekannter Fehler beim Speichern.", "Fehler");
}
}
else
{
var addR = await ProspectService.AddProspectAsync(Prospect);
if (addR.Success)
{
if (OnSuccess != null) await OnSuccess.Invoke();
await ModalService.Hide();
}
else
{
await Notification.Error(addR.Exception?.Message ?? "Unbekannter Fehler beim Hinzufügen.", "Fehler");
}
}
}
else
catch (Exception ex)
{
var addR = await ProspectService.AddProspectAsync(Prospect);
if (addR.Success && OnSuccess != null) await OnSuccess.Invoke();
await Notification.Error(ex.Message, "Systemfehler");
}
finally
{
_isSaving = false;
}
await ModalService.Hide();
}
#endregion

View File

@@ -56,13 +56,24 @@ namespace FoodsharingSiegen.Server.Pages
#region Private Method CreateProspectAsync
private bool _isOpeningModal;
/// <summary>
/// Asynchronously creates a new prospect by displaying the AddProspectModal dialog and refreshing the prospect list.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
private async Task CreateProspectAsync()
{
await EditProspectDialog.ShowAsync(ModalService, LoadProspects);
if (_isOpeningModal) return;
_isOpeningModal = true;
try
{
await EditProspectDialog.ShowAsync(ModalService, LoadProspects);
}
finally
{
_isOpeningModal = false;
}
}
#endregion
@@ -89,15 +100,22 @@ namespace FoodsharingSiegen.Server.Pages
/// </summary>
private async Task LoadProspects()
{
var parameter = new GetProspectsParameter
try
{
CannotHaveInteractions = [InteractionType.Complete, InteractionType.Verify, InteractionType.ReleasedForVerification]
};
var parameter = new GetProspectsParameter
{
CannotHaveInteractions = [InteractionType.Complete, InteractionType.Verify, InteractionType.ReleasedForVerification]
};
var prospectsR = await ProspectService.GetProspectsAsync(parameter);
if (prospectsR.Success) ProspectList = prospectsR.Data;
var prospectsR = await ProspectService.GetProspectsAsync(parameter);
if (prospectsR.Success) ProspectList = prospectsR.Data;
await InvokeAsync(StateHasChanged);
await InvokeAsync(StateHasChanged);
}
catch (Exception ex)
{
await Notification.Error(ex.Message, "Fehler beim Laden");
}
}
#endregion