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 @@ -29,6 +29,14 @@
<p class="text-sm">@errorMessage</p>
</div>
}

@if (!string.IsNullOrWhiteSpace(successMessage))
{
<div class="bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded-lg">
<p class="font-medium">Success</p>
<p class="text-sm">@successMessage</p>
</div>
}

<!-- Form -->
<div class="bg-white rounded-lg shadow-md p-6">
Expand Down Expand Up @@ -84,72 +92,4 @@
</div>
</EditForm>
</div>
</div>

@code {
private CreateOperatorModel model = new();
private bool isSaving = false;
private string? errorMessage;

protected override async Task OnInitializedAsync()
{
await RequirePermission(PermissionSection.Operator, PermissionFunction.Create);
}

private async Task HandleSubmit()
{
isSaving = true;
errorMessage = null;

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

// Create operator
var createCommand = new Commands.CreateOperatorCommand(
correlationId,
accessToken,
estateId,
model.OperatorName!,
model.RequireCustomMerchantNumber,
model.RequireCustomTerminalNumber
);

var createResult = await Mediator.Send(createCommand);

if (!createResult.IsSuccess)
{
errorMessage = createResult.Message ?? "Failed to create operator";
return;
}

// Navigate to operators list with success
NavigationManager.NavigateTo("/operators");
}
catch (Exception ex)
{
errorMessage = $"An error occurred: {ex.Message}";
}
finally
{
isSaving = false;
}
}

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

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

public bool RequireCustomMerchantNumber { get; set; }

public bool RequireCustomTerminalNumber { get; set; }
}
}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using EstateManagementUI.BlazorServer.Permissions;
using EstateManagementUI.BusinessLogic.Requests;
using System.ComponentModel.DataAnnotations;

namespace EstateManagementUI.BlazorServer.Components.Pages.Operators
{
public partial class New
{
private CreateOperatorModel model = new();
private bool isSaving = 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.Create);
}

private async Task HandleSubmit()
{
isSaving = true;
errorMessage = null;

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

// Create operator
var createCommand = new OperatorCommands.CreateOperatorCommand(
correlationId,
estateId,
model.OperatorName!,
model.RequireCustomMerchantNumber,
model.RequireCustomTerminalNumber
);

var createResult = await Mediator.Send(createCommand);

if (!createResult.IsSuccess)
{
errorMessage = createResult.Message ?? "Failed to create operator";
return;
}

// Show success message briefly before navigating away
successMessage = "Operator created successfully.";
StateHasChanged();

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


// Navigate to operators list with success
NavigationManager.NavigateTo("/operators");
}
catch (Exception ex)
{
errorMessage = $"An error occurred: {ex.Message}";
}
finally
{
isSaving = false;
}
}

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

public class CreateOperatorModel
{
[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 @@ -19,6 +19,9 @@ Task<Result<OperatorModel>> GetOperator(OperatorQueries.GetOperatorQuery request

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

Task<Result> CreateOperator(OperatorCommands.CreateOperatorCommand request,
CancellationToken cancellationToken);
}

public partial class ApiClient : IApiClient {
Expand Down Expand Up @@ -71,5 +74,21 @@ public async Task<Result> UpdateOperator(OperatorCommands.UpdateOperatorCommand

return Result.Success();
}

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

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

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

return Result.Success();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,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<OperatorCommands.CreateOperatorCommand, Result>,
IRequestHandler<OperatorCommands.UpdateOperatorCommand, Result>
{
private readonly IApiClient ApiClient;
Expand All @@ -242,9 +242,9 @@ public async Task<Result<OperatorModel>> Handle(OperatorQueries.GetOperatorQuery
CancellationToken cancellationToken) {
return await this.ApiClient.GetOperator(request, cancellationToken);
}
public async Task<Result> Handle(Commands.CreateOperatorCommand request,
public async Task<Result> Handle(OperatorCommands.CreateOperatorCommand request,
CancellationToken cancellationToken) {
return Result.Success();
return await this.ApiClient.CreateOperator(request, cancellationToken);
}
public async Task<Result> Handle(OperatorCommands.UpdateOperatorCommand request,
CancellationToken cancellationToken) {
Expand Down
3 changes: 2 additions & 1 deletion EstateManagmentUI.BusinessLogic/Requests/Requests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,15 @@ public record CreateMerchantCommand(CorrelationId CorrelationId, Guid EstateId,

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

public record CreateOperatorCommand(CorrelationId CorrelationId, Guid EstateId, string Name, bool RequireCustomMerchantNumber, bool RequireCustomTerminalNumber) : IRequest<Result>;
}

public static class Commands
{

public record CreateContractCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, string Description, Guid OperatorId) : IRequest<Result>;
public record CreateMerchantUserCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid MerchantId, string EmailAddress, string Password) : IRequest<Result>;
public record CreateOperatorCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, string Name, bool RequireCustomMerchantNumber, bool RequireCustomTerminalNumber) : IRequest<Result>;



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, Cancellation
// Commands - execute against test data store
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)),
OperatorCommands.CreateOperatorCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteCreateOperator(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)),
Expand Down Expand Up @@ -170,7 +170,7 @@ private Result ExecuteUpdateMerchant(MerchantCommands.UpdateMerchantCommand cmd)
return Result.Success();
}

private Result ExecuteCreateOperator(Commands.CreateOperatorCommand cmd)
private Result ExecuteCreateOperator(OperatorCommands.CreateOperatorCommand cmd)
{
var operatorModel = new OperatorModel
{
Expand Down
Loading