diff --git a/DbFirst.BlazorWasm/Components/CatalogsGrid.razor b/DbFirst.BlazorWasm/Components/CatalogsGrid.razor index 8aa8603..704be66 100644 --- a/DbFirst.BlazorWasm/Components/CatalogsGrid.razor +++ b/DbFirst.BlazorWasm/Components/CatalogsGrid.razor @@ -138,10 +138,7 @@ else @{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); } - + @@ -215,19 +212,15 @@ else { validationMessageStore.Clear(); editContext.NotifyValidationStateChanged(); - } - } - - private void OnTitleChanged() - { - if (validationMessageStore == null || editContext == null) - { return; } - var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle)); - validationMessageStore.Clear(field); - editContext.NotifyValidationStateChanged(); + if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle)) + { + var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle)); + validationMessageStore.Clear(field); + editContext.NotifyValidationStateChanged(); + } } private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) diff --git a/DbFirst.BlazorWasm/Components/MassDataGrid.razor b/DbFirst.BlazorWasm/Components/MassDataGrid.razor index 70b3e0d..8a1b178 100644 --- a/DbFirst.BlazorWasm/Components/MassDataGrid.razor +++ b/DbFirst.BlazorWasm/Components/MassDataGrid.razor @@ -1,3 +1,4 @@ +@using Microsoft.AspNetCore.Components.Forms @inject MassDataApiClient Api @if (!string.IsNullOrWhiteSpace(errorMessage)) @@ -82,11 +86,13 @@ else PageSize="100" CssClass="mb-3 massdata-grid" EditMode="GridEditMode.PopupEditForm" - PopupEditFormHeaderText="Bearbeiten" + PopupEditFormCssClass="massdata-edit-popup" + PopupEditFormHeaderText="@popupHeaderText" + CustomizeEditModel="OnCustomizeEditModel" EditModelSaving="OnEditModelSaving" DataItemDeleting="OnDataItemDeleting"> - + - + @{ SetEditContext(editFormContext.EditContext); var editModel = (MassDataEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); } + - @editFormContext.GetEditor(nameof(MassDataReadDto.CustomerName)) + - @editFormContext.GetEditor(nameof(MassDataReadDto.Amount)) + - @editFormContext.GetEditor(nameof(MassDataReadDto.Category)) + - @editFormContext.GetEditor(nameof(MassDataReadDto.StatusFlag)) + + + @if (!editModel.IsNew) + { + + + + } + + @@ -174,6 +196,9 @@ else private string? infoMessage; private int pageIndex; private int pageCount = 1; + private string popupHeaderText = "Edit"; + private EditContext? editContext; + private ValidationMessageStore? validationMessageStore; private readonly List statusFilterOptions = new() { @@ -182,6 +207,11 @@ else new() { Value = false, Text = "False" } }; + private readonly List procedureOptions = new() + { + new() { Value = 0, Text = "PRMassdata_UpsertByCustomerName" } + }; + protected override async Task OnInitializedAsync() { await LoadPage(0); @@ -216,16 +246,105 @@ else await LoadPage(index); } + private void SetEditContext(EditContext context) + { + if (editContext == context) + { + return; + } + + if (editContext != null) + { + editContext.OnFieldChanged -= OnEditFieldChanged; + } + + editContext = context; + validationMessageStore = new ValidationMessageStore(editContext); + editContext.OnFieldChanged += OnEditFieldChanged; + } + + private void OnEditFieldChanged(object? sender, FieldChangedEventArgs e) + { + if (validationMessageStore == null || editContext == null) + { + return; + } + + if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.UpdateProcedure)) + { + validationMessageStore.Clear(); + editContext.NotifyValidationStateChanged(); + return; + } + + if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.CustomerName)) + { + var field = new FieldIdentifier(editContext.Model, nameof(MassDataEditModel.CustomerName)); + validationMessageStore.Clear(field); + editContext.NotifyValidationStateChanged(); + } + } + + private void SetPopupHeaderText(bool isNew) + { + popupHeaderText = isNew ? "Neu" : "Edit"; + } + + private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) + { + if (e.IsNew) + { + e.EditModel = new MassDataEditModel { IsNew = true, UpdateProcedure = procedureOptions[0].Value }; + SetPopupHeaderText(true); + return; + } + + var item = (MassDataReadDto)e.DataItem; + e.EditModel = new MassDataEditModel + { + Id = item.Id, + CustomerName = item.CustomerName, + AmountText = item.Amount.ToString("0.00"), + Category = item.Category, + StatusFlag = item.StatusFlag, + UpdateProcedure = procedureOptions[0].Value, + IsNew = false, + OriginalCustomerName = item.CustomerName + }; + SetPopupHeaderText(false); + } + private async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { errorMessage = null; infoMessage = null; - var editModel = (MassDataReadDto)e.EditModel; + validationMessageStore?.Clear(); + editContext?.NotifyValidationStateChanged(); + + var editModel = (MassDataEditModel)e.EditModel; + if (!decimal.TryParse(editModel.AmountText, out var amount)) + { + AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ungültig."); + e.Cancel = true; + return; + } + + if (editModel.IsNew) + { + var existing = await Api.GetByCustomerNameAsync(editModel.CustomerName); + if (existing != null) + { + AddValidationError(editModel, nameof(MassDataEditModel.CustomerName), "Kunde existiert bereits."); + e.Cancel = true; + return; + } + } + var dto = new MassDataWriteDto { CustomerName = editModel.CustomerName, - Amount = editModel.Amount, + Amount = amount, Category = editModel.Category, StatusFlag = editModel.StatusFlag }; @@ -233,7 +352,7 @@ else try { await Api.UpsertAsync(dto); - infoMessage = "MassData aktualisiert."; + infoMessage = editModel.IsNew ? "MassData angelegt." : "MassData aktualisiert."; await LoadPage(pageIndex); } catch (Exception ex) @@ -243,6 +362,18 @@ else } } + private void AddValidationError(MassDataEditModel editModel, string fieldName, string message) + { + if (editContext == null || validationMessageStore == null) + { + return; + } + + var field = new FieldIdentifier(editModel, fieldName); + validationMessageStore.Add(field, message); + editContext.NotifyValidationStateChanged(); + } + private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) { errorMessage = null; @@ -251,6 +382,24 @@ else return Task.CompletedTask; } + private sealed class MassDataEditModel + { + public int Id { get; set; } + public string CustomerName { get; set; } = string.Empty; + public string AmountText { get; set; } = string.Empty; + public string Category { get; set; } = string.Empty; + public bool StatusFlag { get; set; } + public int UpdateProcedure { get; set; } + public bool IsNew { get; set; } + public string OriginalCustomerName { get; set; } = string.Empty; + } + + private sealed class ProcedureOption + { + public int Value { get; set; } + public string Text { get; set; } = string.Empty; + } + private sealed class BoolFilterOption { public bool? Value { get; set; } diff --git a/DbFirst.BlazorWasm/Services/MassDataApiClient.cs b/DbFirst.BlazorWasm/Services/MassDataApiClient.cs index 43f69bc..604451c 100644 --- a/DbFirst.BlazorWasm/Services/MassDataApiClient.cs +++ b/DbFirst.BlazorWasm/Services/MassDataApiClient.cs @@ -32,4 +32,21 @@ public class MassDataApiClient var payload = await response.Content.ReadFromJsonAsync(); return payload ?? new MassDataReadDto(); } + + public async Task GetByCustomerNameAsync(string customerName) + { + if (string.IsNullOrWhiteSpace(customerName)) + { + return null; + } + + var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}"); + if (response.StatusCode == System.Net.HttpStatusCode.NotFound) + { + return null; + } + + response.EnsureSuccessStatusCode(); + return await response.Content.ReadFromJsonAsync(); + } } diff --git a/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor b/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor index 9bb0fba..87c0fbe 100644 --- a/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor +++ b/DbFirst.BlazorWebApp/Components/CatalogsGrid.razor @@ -97,10 +97,7 @@ else @{ SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); } - + @@ -174,19 +171,15 @@ else { validationMessageStore.Clear(); editContext.NotifyValidationStateChanged(); - } - } - - private void OnTitleChanged() - { - if (validationMessageStore == null || editContext == null) - { return; } - var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle)); - validationMessageStore.Clear(field); - editContext.NotifyValidationStateChanged(); + if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle)) + { + var field = new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle)); + validationMessageStore.Clear(field); + editContext.NotifyValidationStateChanged(); + } } private void SetPopupHeaderText(bool isNew) diff --git a/DbFirst.BlazorWebApp/Components/MassDataGrid.razor b/DbFirst.BlazorWebApp/Components/MassDataGrid.razor index 70b3e0d..8a1b178 100644 --- a/DbFirst.BlazorWebApp/Components/MassDataGrid.razor +++ b/DbFirst.BlazorWebApp/Components/MassDataGrid.razor @@ -1,3 +1,4 @@ +@using Microsoft.AspNetCore.Components.Forms @inject MassDataApiClient Api @if (!string.IsNullOrWhiteSpace(errorMessage)) @@ -82,11 +86,13 @@ else PageSize="100" CssClass="mb-3 massdata-grid" EditMode="GridEditMode.PopupEditForm" - PopupEditFormHeaderText="Bearbeiten" + PopupEditFormCssClass="massdata-edit-popup" + PopupEditFormHeaderText="@popupHeaderText" + CustomizeEditModel="OnCustomizeEditModel" EditModelSaving="OnEditModelSaving" DataItemDeleting="OnDataItemDeleting"> - + - + @{ SetEditContext(editFormContext.EditContext); var editModel = (MassDataEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew); } + - @editFormContext.GetEditor(nameof(MassDataReadDto.CustomerName)) + - @editFormContext.GetEditor(nameof(MassDataReadDto.Amount)) + - @editFormContext.GetEditor(nameof(MassDataReadDto.Category)) + - @editFormContext.GetEditor(nameof(MassDataReadDto.StatusFlag)) + + + @if (!editModel.IsNew) + { + + + + } + + @@ -174,6 +196,9 @@ else private string? infoMessage; private int pageIndex; private int pageCount = 1; + private string popupHeaderText = "Edit"; + private EditContext? editContext; + private ValidationMessageStore? validationMessageStore; private readonly List statusFilterOptions = new() { @@ -182,6 +207,11 @@ else new() { Value = false, Text = "False" } }; + private readonly List procedureOptions = new() + { + new() { Value = 0, Text = "PRMassdata_UpsertByCustomerName" } + }; + protected override async Task OnInitializedAsync() { await LoadPage(0); @@ -216,16 +246,105 @@ else await LoadPage(index); } + private void SetEditContext(EditContext context) + { + if (editContext == context) + { + return; + } + + if (editContext != null) + { + editContext.OnFieldChanged -= OnEditFieldChanged; + } + + editContext = context; + validationMessageStore = new ValidationMessageStore(editContext); + editContext.OnFieldChanged += OnEditFieldChanged; + } + + private void OnEditFieldChanged(object? sender, FieldChangedEventArgs e) + { + if (validationMessageStore == null || editContext == null) + { + return; + } + + if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.UpdateProcedure)) + { + validationMessageStore.Clear(); + editContext.NotifyValidationStateChanged(); + return; + } + + if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.CustomerName)) + { + var field = new FieldIdentifier(editContext.Model, nameof(MassDataEditModel.CustomerName)); + validationMessageStore.Clear(field); + editContext.NotifyValidationStateChanged(); + } + } + + private void SetPopupHeaderText(bool isNew) + { + popupHeaderText = isNew ? "Neu" : "Edit"; + } + + private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) + { + if (e.IsNew) + { + e.EditModel = new MassDataEditModel { IsNew = true, UpdateProcedure = procedureOptions[0].Value }; + SetPopupHeaderText(true); + return; + } + + var item = (MassDataReadDto)e.DataItem; + e.EditModel = new MassDataEditModel + { + Id = item.Id, + CustomerName = item.CustomerName, + AmountText = item.Amount.ToString("0.00"), + Category = item.Category, + StatusFlag = item.StatusFlag, + UpdateProcedure = procedureOptions[0].Value, + IsNew = false, + OriginalCustomerName = item.CustomerName + }; + SetPopupHeaderText(false); + } + private async Task OnEditModelSaving(GridEditModelSavingEventArgs e) { errorMessage = null; infoMessage = null; - var editModel = (MassDataReadDto)e.EditModel; + validationMessageStore?.Clear(); + editContext?.NotifyValidationStateChanged(); + + var editModel = (MassDataEditModel)e.EditModel; + if (!decimal.TryParse(editModel.AmountText, out var amount)) + { + AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ungültig."); + e.Cancel = true; + return; + } + + if (editModel.IsNew) + { + var existing = await Api.GetByCustomerNameAsync(editModel.CustomerName); + if (existing != null) + { + AddValidationError(editModel, nameof(MassDataEditModel.CustomerName), "Kunde existiert bereits."); + e.Cancel = true; + return; + } + } + var dto = new MassDataWriteDto { CustomerName = editModel.CustomerName, - Amount = editModel.Amount, + Amount = amount, Category = editModel.Category, StatusFlag = editModel.StatusFlag }; @@ -233,7 +352,7 @@ else try { await Api.UpsertAsync(dto); - infoMessage = "MassData aktualisiert."; + infoMessage = editModel.IsNew ? "MassData angelegt." : "MassData aktualisiert."; await LoadPage(pageIndex); } catch (Exception ex) @@ -243,6 +362,18 @@ else } } + private void AddValidationError(MassDataEditModel editModel, string fieldName, string message) + { + if (editContext == null || validationMessageStore == null) + { + return; + } + + var field = new FieldIdentifier(editModel, fieldName); + validationMessageStore.Add(field, message); + editContext.NotifyValidationStateChanged(); + } + private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) { errorMessage = null; @@ -251,6 +382,24 @@ else return Task.CompletedTask; } + private sealed class MassDataEditModel + { + public int Id { get; set; } + public string CustomerName { get; set; } = string.Empty; + public string AmountText { get; set; } = string.Empty; + public string Category { get; set; } = string.Empty; + public bool StatusFlag { get; set; } + public int UpdateProcedure { get; set; } + public bool IsNew { get; set; } + public string OriginalCustomerName { get; set; } = string.Empty; + } + + private sealed class ProcedureOption + { + public int Value { get; set; } + public string Text { get; set; } = string.Empty; + } + private sealed class BoolFilterOption { public bool? Value { get; set; } diff --git a/DbFirst.BlazorWebApp/Services/MassDataApiClient.cs b/DbFirst.BlazorWebApp/Services/MassDataApiClient.cs index 11d4832..ce82d42 100644 --- a/DbFirst.BlazorWebApp/Services/MassDataApiClient.cs +++ b/DbFirst.BlazorWebApp/Services/MassDataApiClient.cs @@ -32,4 +32,21 @@ public class MassDataApiClient var payload = await response.Content.ReadFromJsonAsync(); return payload ?? new MassDataReadDto(); } + + public async Task GetByCustomerNameAsync(string customerName) + { + if (string.IsNullOrWhiteSpace(customerName)) + { + return null; + } + + var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}"); + if (response.StatusCode == System.Net.HttpStatusCode.NotFound) + { + return null; + } + + response.EnsureSuccessStatusCode(); + return await response.Content.ReadFromJsonAsync(); + } }