feat(usability): confirm saves and guard booking submissions against duplicates (U07)
This commit is contained in:
@@ -15,7 +15,7 @@ public partial class AddEntryDialog
|
||||
public EntryDto? EditEntry { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<DateTime> OnSave { get; set; }
|
||||
public EventCallback<BookingSaved> OnSave { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnCancel { get; set; }
|
||||
@@ -30,6 +30,12 @@ public partial class AddEntryDialog
|
||||
[Parameter] public string AccountName { get; set; } = string.Empty;
|
||||
private bool CanSave => !string.IsNullOrWhiteSpace(title) && ValidAmount && date != default && (!OutsideYear || (confirmDifferentYear && confirmedYear == date.Year));
|
||||
|
||||
private bool isSaving;
|
||||
private bool completed;
|
||||
private BookingSaved? committedResult;
|
||||
private string? saveError;
|
||||
private string? saveDetails;
|
||||
|
||||
#region Fields
|
||||
|
||||
private EntryType entryType = EntryType.Income;
|
||||
@@ -66,20 +72,40 @@ public partial class AddEntryDialog
|
||||
|
||||
private async Task Save()
|
||||
{
|
||||
if (!CanSave) return;
|
||||
if (EditEntry != null)
|
||||
if (isSaving || completed || (committedResult == null && !CanSave)) return;
|
||||
isSaving = true;
|
||||
saveError = null;
|
||||
saveDetails = null;
|
||||
try
|
||||
{
|
||||
await EntryService.UpdateEntryAsync(EditEntry.Id, date, title.Trim(), amount);
|
||||
if (committedResult == null)
|
||||
{
|
||||
var id = EditEntry?.Id ?? 0;
|
||||
if (EditEntry != null)
|
||||
await EntryService.UpdateEntryAsync(EditEntry.Id, date, title.Trim(), amount);
|
||||
else
|
||||
id = (await EntryService.CreateEntryAsync(AccountId, entryType, date, title.Trim(), amount)).Id;
|
||||
committedResult = new(id, date, entryType == EntryType.Income ? "Einnahme" : "Ausgabe", amount, EditEntry != null);
|
||||
}
|
||||
// If refreshing the page fails after commit, retry only notification,
|
||||
// never create a second booking.
|
||||
await OnSave.InvokeAsync(committedResult);
|
||||
completed = true;
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
await EntryService.CreateEntryAsync(AccountId, entryType, date, title.Trim(), amount);
|
||||
saveError = committedResult == null
|
||||
? "Speichern fehlgeschlagen. Die Eingaben bleiben erhalten. Bitte erneut versuchen."
|
||||
: "Die Buchung ist gespeichert. Die Ansicht konnte nicht aktualisiert werden. Bitte Ansicht aktualisieren; es wird keine weitere Buchung erzeugt.";
|
||||
saveDetails = ex.Message;
|
||||
}
|
||||
|
||||
await OnSave.InvokeAsync(date);
|
||||
finally { isSaving = false; }
|
||||
}
|
||||
|
||||
private async Task Cancel() => await OnCancel.InvokeAsync();
|
||||
private async Task Cancel()
|
||||
{
|
||||
if (!isSaving) await OnCancel.InvokeAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user