@using RobotNet10.FleetManager.Shared.DTOs.Robot @using RobotNet10.FleetManager.Shared.DTOs.RobotModel @using RobotNet10.FleetManager.Client.Services @using RobotNet10.MapEditor.Services.API @using RobotNet10.MapEditor.Shared.DTOs.Layout @inject ISnackbar Snackbar @inject MapManagerApiService MapApiService Edit Robot @if (isLoadingModels) { } else { @foreach (var model in robotModels) { @model.ModelName } } @if (isLoadingMaps) { Loading maps... } else if (mapLevels != null && mapLevels.Any()) { No Map @foreach (var mapLevel in mapLevels) { @mapLevel.DisplayName } } else { No maps available } Cancel @if (isUpdating) { Updating... } else { Update } @code { [CascadingParameter] private IMudDialogInstance? MudDialog { get; set; } [Parameter] public RobotApiService RobotApiService { get; set; } = null!; [Parameter] public RobotModelApiService RobotModelApiService { get; set; } = null!; [Parameter] public RobotDto Robot { get; set; } = null!; private UpdateRobotRequest request = new(); private List robotModels = new(); private List mapLevels = new(); private Dictionary validationErrors = new(); private bool isUpdating = false; private bool isLoadingModels = true; private bool isLoadingMaps = false; protected override void OnInitialized() { // Pre-fill with existing data request.RobotId = Robot.RobotId; request.Name = Robot.Name; request.ModelId = Robot.ModelId; request.MapId = Robot.MapId; } protected override async Task OnInitializedAsync() { await Task.WhenAll( LoadRobotModelsAsync(), LoadMapsAsync() ); } private async Task LoadRobotModelsAsync() { isLoadingModels = true; try { robotModels = await RobotModelApiService.GetAllAsync(); } catch (Exception ex) { Snackbar.Add($"Error loading robot models: {ex.Message}", Severity.Error); } finally { isLoadingModels = false; StateHasChanged(); } } private async Task LoadMapsAsync() { isLoadingMaps = true; StateHasChanged(); try { // Load all layouts (with nested versions and levels) var layouts = await MapApiService.SearchLayoutsAsync(); if (layouts is null) return; // Get all levels from all layouts (not just active layouts) mapLevels = new List(); foreach (var layout in layouts.Where(l => l.Versions != null)) { if (layout.Versions is null) continue; foreach (var version in layout.Versions.Where(v => v.Levels != null)) { if (version.Levels is null) continue; foreach (var level in version.Levels.OrderBy(l => l.LevelOrder)) { mapLevels.Add(new MapLevelInfo { LevelId = level.Id, DisplayName = $"{layout.LayoutName} - {version.Version} - {level.LayoutLevelId}" }); } } } } catch (Exception ex) { Snackbar.Add($"Error loading maps: {ex.Message}", Severity.Warning); mapLevels = new List(); } finally { isLoadingMaps = false; StateHasChanged(); } } private bool Validate() { validationErrors.Clear(); if (!string.IsNullOrWhiteSpace(request.RobotId) && request.RobotId.Length > 64) { validationErrors["RobotId"] = "Robot ID must be 64 characters or less"; } if (!string.IsNullOrWhiteSpace(request.Name) && request.Name.Length > 256) { validationErrors["Name"] = "Name must be 256 characters or less"; } return validationErrors.Count == 0; } private string? GetValidationError(string fieldName) { return validationErrors.TryGetValue(fieldName, out var error) ? error : null; } 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 { var updated = await RobotApiService.UpdateAsync(Robot.Id, request); Snackbar.Add($"Robot '{updated.Name}' updated successfully", Severity.Success); MudDialog?.Close(DialogResult.Ok(updated)); } catch (Exception ex) { Snackbar.Add($"Error updating robot: {ex.Message}", Severity.Error); } finally { isUpdating = false; StateHasChanged(); } } // Helper class for map level display private class MapLevelInfo { public Guid LevelId { get; set; } public string DisplayName { get; set; } = string.Empty; } }