@using RobotNet10.FleetManager.Shared.DTOs.RobotModel
@using RobotNet10.FleetManager.Shared.Enums
@using RobotNet10.FleetManager.Client.Services
@using RobotNet10.MapEditor.Services.API
@using RobotNet10.MapEditor.Shared.DTOs.VehicleType
@inject ISnackbar Snackbar
@inject MapManagerApiService MapApiService
Create Robot Model
@foreach (NavigationType navType in Enum.GetValues())
{
@navType.ToString()
}
@if (isLoadingVehicleTypes)
{
Loading vehicle types...
}
else if (vehicleTypes != null && vehicleTypes.Any())
{
None
@foreach (var vehicleType in vehicleTypes)
{
@($"{vehicleType.VehicleTypeId} - {vehicleType.VehicleTypeName}")
}
}
else
{
No vehicle types available
}
Image Upload (Optional)
Upload Image (PNG)
@if (selectedFile != null)
{
@selectedFile.Name (@FormatFileSize(selectedFile.Size))
}
Cancel
@if (isCreating)
{
Creating...
}
else
{
Create
}
@code {
[CascadingParameter] private IMudDialogInstance? MudDialog { get; set; }
[Parameter] public RobotModelApiService ApiService { get; set; } = null!;
private CreateRobotModelRequest request = new()
{
NavigationType = NavigationType.Differential, // Default value
ImageWidth = 100, // Default value, will be updated if image is uploaded
ImageHeight = 100 // Default value, will be updated if image is uploaded
};
private IBrowserFile? selectedFile;
private Dictionary validationErrors = new();
private bool isCreating = false;
private List? vehicleTypes;
private bool isLoadingVehicleTypes = false;
protected override async Task OnInitializedAsync()
{
await LoadVehicleTypesAsync();
}
private async Task LoadVehicleTypesAsync()
{
isLoadingVehicleTypes = true;
StateHasChanged();
try
{
vehicleTypes = await MapApiService.GetVehicleTypesAsync(isActive: true);
}
catch (Exception ex)
{
Snackbar.Add($"Error loading vehicle types: {ex.Message}", Severity.Warning);
vehicleTypes = new List();
}
finally
{
isLoadingVehicleTypes = false;
StateHasChanged();
}
}
private bool Validate()
{
validationErrors.Clear();
if (string.IsNullOrWhiteSpace(request.ModelName))
{
validationErrors["ModelName"] = "Model Name is required";
}
else if (request.ModelName.Length > 256)
{
validationErrors["ModelName"] = "Model Name must not exceed 256 characters";
}
if (request.Length <= 0)
{
validationErrors["Length"] = "Length must be greater than 0";
}
else if (request.Length > 1000)
{
validationErrors["Length"] = "Length must not exceed 1000 meters";
}
if (request.Width <= 0)
{
validationErrors["Width"] = "Width must be greater than 0";
}
else if (request.Width > 1000)
{
validationErrors["Width"] = "Width must not exceed 1000 meters";
}
// ImageWidth and ImageHeight are set to default values (100) when request is initialized
// They will be updated by server if image is uploaded
// No need to validate them here as they're always set to valid values (100)
// NavigationPointX and NavigationPointY can be 0 or any decimal value
// They are required fields but can be 0, so no validation needed here
// Server-side validation will handle range checks if needed
return validationErrors.Count == 0;
}
private string? GetValidationError(string fieldName)
{
return validationErrors.TryGetValue(fieldName, out var error) ? error : null;
}
private string FormatFileSize(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB" };
double len = bytes;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1)
{
order++;
len = len / 1024;
}
return $"{len:0.##} {sizes[order]}";
}
private void Cancel()
{
MudDialog?.Cancel();
}
private async Task Submit()
{
if (!Validate())
{
var errorMessages = string.Join(", ", validationErrors.Values);
Snackbar.Add($"Please fix validation errors: {errorMessages}", Severity.Warning);
StateHasChanged();
return;
}
isCreating = true;
StateHasChanged();
try
{
// ImageWidth and ImageHeight are already set to default values (100) in request initialization
// If image is provided, server will update these values after extracting dimensions
// If no image, default values (100x100) will be used
// Create robot model first
var created = await ApiService.CreateAsync(request);
// Upload image if provided
if (selectedFile != null)
{
try
{
using var stream = selectedFile.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024); // 10MB
await ApiService.UploadImageAsync(created.Id, stream, selectedFile.Name);
}
catch (Exception imageEx)
{
// Log image upload error but don't fail the entire operation
// The robot model was created successfully, image can be uploaded later
Snackbar.Add($"Robot model created but image upload failed: {imageEx.Message}", Severity.Warning);
}
}
Snackbar.Add($"Robot model '{request.ModelName}' created successfully", Severity.Success);
MudDialog?.Close(DialogResult.Ok(created));
}
catch (HttpRequestException httpEx)
{
var errorMessage = httpEx.Message;
if (httpEx.Data.Contains("Response"))
{
errorMessage = $"Network error: {httpEx.Message}";
}
Snackbar.Add($"Error creating robot model: {errorMessage}", Severity.Error);
}
catch (Exception ex)
{
Snackbar.Add($"Error creating robot model: {ex.Message}", Severity.Error);
}
finally
{
isCreating = false;
StateHasChanged();
}
}
}