@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 Edit 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 - Leave empty to keep current image) Upload New Image (PNG) @if (selectedFile != null) { @selectedFile.Name (@FormatFileSize(selectedFile.Size)) } Cancel @if (isUpdating) { Updating... } else { Update } @code { [CascadingParameter] private IMudDialogInstance? MudDialog { get; set; } [Parameter] public RobotModelApiService ApiService { get; set; } = null!; [Parameter] public RobotModelDto RobotModel { get; set; } = null!; private UpdateRobotModelRequest request = new(); private IBrowserFile? selectedFile; private Dictionary validationErrors = new(); private bool isUpdating = false; private List? vehicleTypes; private bool isLoadingVehicleTypes = false; protected override async Task OnInitializedAsync() { // Pre-fill with existing data request.ModelName = RobotModel.ModelName; request.Length = RobotModel.Length; request.Width = RobotModel.Width; request.NavigationPointX = RobotModel.NavigationPointX; request.NavigationPointY = RobotModel.NavigationPointY; request.NavigationType = RobotModel.NavigationType; // This is nullable, but we set it to the actual value request.VehicleTypeId = RobotModel.VehicleTypeId; 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) && request.ModelName.Length > 256) { validationErrors["ModelName"] = "Model Name must be 256 characters or less"; } if (request.Length.HasValue && request.Length.Value <= 0) { validationErrors["Length"] = "Length must be greater than 0"; } if (request.Width.HasValue && request.Width.Value <= 0) { validationErrors["Width"] = "Width must be greater than 0"; } 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()) { Snackbar.Add("Please fix validation errors", Severity.Warning); StateHasChanged(); return; } isUpdating = true; StateHasChanged(); try { // Update robot model var updated = await ApiService.UpdateAsync(RobotModel.Id, request); // Upload new image if provided if (selectedFile != null) { using var stream = selectedFile.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024); // 10MB await ApiService.UploadImageAsync(updated.Id, stream, selectedFile.Name); } Snackbar.Add($"Robot model '{updated.ModelName}' updated successfully", Severity.Success); MudDialog?.Close(DialogResult.Ok(updated)); } catch (Exception ex) { Snackbar.Add($"Error updating robot model: {ex.Message}", Severity.Error); } finally { isUpdating = false; StateHasChanged(); } } }