Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,13 @@ private async Task SaveAllChanges()
return;
}

// Show success message briefly before navigating away
successMessage = "Merchant details updated successfully";
StateHasChanged();

// Small delay so user sees confirmation (adjust duration as needed)
await Task.Delay(2500);

// Navigate to edit page
NavigationManager.NavigateTo($"/merchants");
}
Expand Down
140 changes: 0 additions & 140 deletions EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,6 @@

<PageTitle>Edit Operator</PageTitle>

@if (!hasPermission)
{
<div class="flex items-center justify-center py-12">
<div class="bg-red-50 border border-red-200 rounded-lg p-6 max-w-md">
<div class="flex items-center space-x-3">
<svg class="w-8 h-8 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
<div>
<h3 class="text-lg font-semibold text-red-900">Access Denied</h3>
<p class="text-sm text-red-700 mt-1">You don't have permission to edit operators.</p>
</div>
</div>
<button class="btn btn-secondary mt-4 w-full" @onclick='() => NavigationManager.NavigateTo("/operators")'>
Back to Operators
</button>
</div>
</div>
}
else
{
<div class="space-y-6">
@if (isLoading)
{
Expand Down Expand Up @@ -132,122 +111,3 @@ else
</div>
}
</div>

@code {
[Parameter]
public Guid OperatorId { get; set; }

private OperatorModel? operatorModel;
private EditOperatorModel model = new();
private bool isLoading = true;
private bool isSaving = false;
private bool hasPermission = false;
private string? errorMessage;
private string? successMessage;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
await base.OnAfterRenderAsync(firstRender);
return;
}

await RequirePermission(PermissionSection.Operator, PermissionFunction.Edit);
await LoadOperator();
}

private async Task LoadOperator()
{
try
{
isLoading = true;
var correlationId = new CorrelationId(Guid.NewGuid());
var estateId = await GetEstateId();

var result = await Mediator.Send(new OperatorQueries.GetOperatorQuery(correlationId, estateId, OperatorId));

if (result.IsSuccess && result.Data != null)
{
operatorModel = ModelFactory.ConvertFrom(result.Data);

// Initialize model with current values
model = new EditOperatorModel
{
OperatorName = operatorModel.Name,
RequireCustomMerchantNumber = operatorModel.RequireCustomMerchantNumber,
RequireCustomTerminalNumber = operatorModel.RequireCustomTerminalNumber
};
}
}
finally
{
isLoading = false;
}
}

private async Task HandleSubmit()
{
isSaving = true;
ClearMessages();

try
{
var correlationId = new CorrelationId(Guid.NewGuid());
var estateId = Guid.Parse("11111111-1111-1111-1111-111111111111");
var accessToken = "stubbed-token";

var command = new Commands.UpdateOperatorCommand(
correlationId,
accessToken,
estateId,
OperatorId,
model.OperatorName!,
model.RequireCustomMerchantNumber,
model.RequireCustomTerminalNumber
);

var result = await Mediator.Send(command);

if (result.IsSuccess)
{
successMessage = "Operator updated successfully";
await LoadOperator();
}
else
{
errorMessage = result.Message ?? "Failed to update operator";
}
}
catch (Exception ex)
{
errorMessage = $"An error occurred: {ex.Message}";
}
finally
{
isSaving = false;
}
}

private void ClearMessages()
{
errorMessage = null;
successMessage = null;
}

private void BackToList()
{
NavigationManager.NavigateTo("/operators");
}

public class EditOperatorModel
{
[Required(ErrorMessage = "Operator name is required")]
public string? OperatorName { get; set; }

public bool RequireCustomMerchantNumber { get; set; }

public bool RequireCustomTerminalNumber { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using EstateManagementUI.BlazorServer.Factories;
using EstateManagementUI.BlazorServer.Permissions;
using EstateManagementUI.BusinessLogic.Requests;
using MediatR;
using Microsoft.AspNetCore.Components;
using System.ComponentModel.DataAnnotations;
using EstateManagementUI.BlazorServer.Models;

namespace EstateManagementUI.BlazorServer.Components.Pages.Operators
{
public partial class Edit
{
[Parameter]
public Guid OperatorId { get; set; }

private OperatorModel? operatorModel;
private EditOperatorModel model = new();
private bool isLoading = true;
private bool isSaving = false;
private bool hasPermission = false;
private string? errorMessage;
private string? successMessage;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
await base.OnAfterRenderAsync(firstRender);
return;
}

await RequirePermission(PermissionSection.Operator, PermissionFunction.Edit);
await LoadOperator();
}

private async Task LoadOperator()
{
try
{
isLoading = true;
var correlationId = new CorrelationId(Guid.NewGuid());
var estateId = await GetEstateId();

var result = await Mediator.Send(new OperatorQueries.GetOperatorQuery(correlationId, estateId, OperatorId));

if (result.IsSuccess && result.Data != null)
{
operatorModel = ModelFactory.ConvertFrom(result.Data);

// Initialize model with current values
model = new EditOperatorModel
{
OperatorName = operatorModel.Name,
RequireCustomMerchantNumber = operatorModel.RequireCustomMerchantNumber,
RequireCustomTerminalNumber = operatorModel.RequireCustomTerminalNumber
};
}
}
finally
{
isLoading = false;
this.StateHasChanged();
}
}

private async Task HandleSubmit()
{
isSaving = true;
ClearMessages();

try
{
var correlationId = new CorrelationId(Guid.NewGuid());
var estateId = await this.GetEstateId();

var command = new OperatorCommands.UpdateOperatorCommand(
correlationId,
estateId,
OperatorId,
model.OperatorName!,
model.RequireCustomMerchantNumber,
model.RequireCustomTerminalNumber
);

var result = await Mediator.Send(command);

if (result.IsSuccess)
{
successMessage = "Operator updated successfully";
StateHasChanged();

// Small delay so user sees confirmation (adjust duration as needed)
await Task.Delay(2500);

NavigationManager.NavigateTo("/operators");
}
else
{
errorMessage = result.Message ?? "Failed to update operator";
}
}
catch (Exception ex)
{
errorMessage = $"An error occurred: {ex.Message}";
}
finally
{
isSaving = false;
}
}

private void ClearMessages()
{
errorMessage = null;
successMessage = null;
}

private void BackToList()
{
NavigationManager.NavigateTo("/operators");
}

public class EditOperatorModel
{
[Required(ErrorMessage = "Operator name is required")]
public string? OperatorName { get; set; }

public bool RequireCustomMerchantNumber { get; set; }

public bool RequireCustomTerminalNumber { get; set; }
}
}
}
19 changes: 19 additions & 0 deletions EstateManagmentUI.BusinessLogic/Client/OperatorMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using TransactionProcessor.DataTransferObjects.Requests.Operator;

namespace EstateManagementUI.BusinessLogic.Client
{
Expand All @@ -15,6 +16,9 @@ Task<Result<List<OperatorModel>>> GetOperators(OperatorQueries.GetOperatorsQuery

Task<Result<OperatorModel>> GetOperator(OperatorQueries.GetOperatorQuery request,
CancellationToken cancellationToken);

Task<Result> UpdateOperator(OperatorCommands.UpdateOperatorCommand request,
CancellationToken cancellationToken);
}

public partial class ApiClient : IApiClient {
Expand Down Expand Up @@ -52,5 +56,20 @@ public async Task<Result<OperatorModel>> GetOperator(OperatorQueries.GetOperator

return Result.Success(operatorModels);
}

public async Task<Result> UpdateOperator(OperatorCommands.UpdateOperatorCommand request,
CancellationToken cancellationToken) {
var token = await this.GetToken(cancellationToken);
if (token.IsFailed)
return ResultHelpers.CreateFailure(token);

var apiRequest = new UpdateOperatorRequest() { Name= request.Name, RequireCustomMerchantNumber = request.RequireCustomMerchantNumber, RequireCustomTerminalNumber = request.RequireCustomTerminalNumber};

var apiResult = await this.TransactionProcessorClient.UpdateOperator(token.Data, request.EstateId, request.OperatorId, apiRequest, cancellationToken);
if (apiResult.IsFailed)
return ResultHelpers.CreateFailure(apiResult);

return Result.Success();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public async Task<Result<List<ContractDropDownModel>>> Handle(ContractQueries.Ge
public class OperatorRequestHandler : IRequestHandler<OperatorQueries.GetOperatorsQuery, Result<List<OperatorModel>>>,
IRequestHandler<OperatorQueries.GetOperatorQuery, Result<OperatorModel>>,
IRequestHandler<Commands.CreateOperatorCommand, Result>,
IRequestHandler<Commands.UpdateOperatorCommand, Result>
IRequestHandler<OperatorCommands.UpdateOperatorCommand, Result>
{
private readonly IApiClient ApiClient;

Expand All @@ -246,9 +246,9 @@ public async Task<Result> Handle(Commands.CreateOperatorCommand request,
CancellationToken cancellationToken) {
return Result.Success();
}
public async Task<Result> Handle(Commands.UpdateOperatorCommand request,
public async Task<Result> Handle(OperatorCommands.UpdateOperatorCommand request,
CancellationToken cancellationToken) {
return Result.Success();
return await this.ApiClient.UpdateOperator(request, cancellationToken);
}
}

Expand Down
5 changes: 4 additions & 1 deletion EstateManagmentUI.BusinessLogic/Requests/Requests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ public record MakeMerchantDepositCommand(CorrelationId CorrelationId, Guid Estat
public record CreateMerchantCommand(CorrelationId CorrelationId, Guid EstateId, Guid MerchantId, string Name, String SettlementSchedule, MerchantAddress MerchantAddress, MerchantContact MerchantContact) : IRequest<Result>;
}

public static class OperatorCommands {
public record UpdateOperatorCommand(CorrelationId CorrelationId,Guid EstateId, Guid OperatorId, string Name, bool RequireCustomMerchantNumber, bool RequireCustomTerminalNumber) : IRequest<Result>;
}

public static class Commands
{

Expand All @@ -97,7 +101,6 @@ public record CreateOperatorCommand(CorrelationId CorrelationId, string AccessTo



public record UpdateOperatorCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid OperatorId, string Name, bool RequireCustomMerchantNumber, bool RequireCustomTerminalNumber) : IRequest<Result>;
public record AddProductToContractCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid ContractId, string ProductName, string DisplayText, decimal? Value) : IRequest<Result>;
public record AddTransactionFeeForProductToContractCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid ContractId, Guid ProductId, string Description, decimal Value) : IRequest<Result>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, Cancellation
MerchantCommands.CreateMerchantCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteCreateMerchant(cmd)),
MerchantCommands.UpdateMerchantCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteUpdateMerchant(cmd)),
Commands.CreateOperatorCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteCreateOperator(cmd)),
Commands.UpdateOperatorCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteUpdateOperator(cmd)),
OperatorCommands.UpdateOperatorCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteUpdateOperator(cmd)),
Commands.CreateContractCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteCreateContract(cmd)),
Commands.AddProductToContractCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteAddProductToContract(cmd)),
Commands.AddTransactionFeeForProductToContractCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteAddTransactionFee(cmd)),
Expand Down Expand Up @@ -183,7 +183,7 @@ private Result ExecuteCreateOperator(Commands.CreateOperatorCommand cmd)
return Result.Success();
}

private Result ExecuteUpdateOperator(Commands.UpdateOperatorCommand cmd)
private Result ExecuteUpdateOperator(OperatorCommands.UpdateOperatorCommand cmd)
{
var operatorModel = this._testDataStore.GetOperator(cmd.EstateId, cmd.OperatorId);
if (operatorModel == null)
Expand Down
Loading