From 86849adeab1371cbef4b78da6b4d7756fc0df196 Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:34:32 +0000 Subject: [PATCH 1/3] Initial plan From 032c98f1b8aebe68089053e5528c51474e90b175 Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:40:55 +0000 Subject: [PATCH 2/3] Implement Fleet Management grid with Material Dark theme and master-detail functionality Co-authored-by: dkamburov <1182001+dkamburov@users.noreply.github.com> --- .../FleetManagementComponent.razor | 138 +++++++++++++++--- .../Models/FleetData.cs | 3 + .../Models/MaintenanceData.cs | 33 +++++ .../Services/FleetService.cs | 31 +++- .../FleetManagement/Components/App.razor | 2 +- 5 files changed, 187 insertions(+), 20 deletions(-) create mode 100644 src/samples/FleetManagement.Library/Models/MaintenanceData.cs diff --git a/src/samples/FleetManagement.Library/FleetManagementComponent.razor b/src/samples/FleetManagement.Library/FleetManagementComponent.razor index a84e7c1..42aab9f 100644 --- a/src/samples/FleetManagement.Library/FleetManagementComponent.razor +++ b/src/samples/FleetManagement.Library/FleetManagementComponent.razor @@ -22,25 +22,117 @@ } else { - - - - - - - - - - - - +
+

Fleet Management

+

Master-Detail Grid for managing vehicle acquisition, operations, and maintenance records

+ + +
+
+
+
+
Total Vehicles
+

@FleetService.Data.Count

+
+
+
+
+
+
+
Active
+

@FleetService.Data.Count(v => v.Status == "Active")

+
+
+
+
+
+
+
In Maintenance
+

@FleetService.Data.Count(v => v.Status == "Maintenance")

+
+
+
+
+
+
+
Avg Fuel Level
+

@(FleetService.Data.Any() ? FleetService.Data.Average(v => v.FuelLevel).ToString("N1") : "0")%

+
+
+
+
+
+ + +
+
+
Vehicle Fleet
+
+
+ + + + + + + + + + + +
+
+ + + @if (selectedVehicle != null) + { +
+
+
Maintenance History - @selectedVehicle.VehicleId (@selectedVehicle.Make @selectedVehicle.Model)
+
+
+ @{ + var maintenanceRecords = FleetService.GetMaintenanceForVehicle(selectedVehicle.VehicleId); + } + @if (maintenanceRecords.Any()) + { + + + + + + + + + + } + else + { +
+

No maintenance records found for this vehicle.

+
+ } +
+
+ } + else + { + + } +
- Data updates every 3 seconds to simulate live fleet tracking + Data updates every 3 seconds to simulate live fleet tracking. Click on a row to view maintenance history.
} @@ -50,6 +142,8 @@ private bool isLoading = true; private System.Timers.Timer? updateTimer; private IgbGrid? grid; + private IgbGrid? maintenanceGrid; + private FleetData? selectedVehicle = null; protected override async Task OnInitializedAsync() { @@ -64,6 +158,12 @@ FleetService.UpdateAllData(); }; updateTimer.Start(); + + // Select first vehicle by default + if (FleetService.Data.Any()) + { + selectedVehicle = FleetService.Data.First(); + } } private void OnDataChanged() @@ -75,6 +175,10 @@ { grid.MarkForCheck(); } + if (maintenanceGrid != null) + { + maintenanceGrid.MarkForCheck(); + } }); } diff --git a/src/samples/FleetManagement.Library/Models/FleetData.cs b/src/samples/FleetManagement.Library/Models/FleetData.cs index cfb0d27..8529e50 100644 --- a/src/samples/FleetManagement.Library/Models/FleetData.cs +++ b/src/samples/FleetManagement.Library/Models/FleetData.cs @@ -39,4 +39,7 @@ public class FleetData [JsonPropertyName("nextService")] public DateTime NextService { get; set; } + + // Property for child grid data (not serialized from JSON) + public List MaintenanceRecords { get; set; } = new(); } diff --git a/src/samples/FleetManagement.Library/Models/MaintenanceData.cs b/src/samples/FleetManagement.Library/Models/MaintenanceData.cs new file mode 100644 index 0000000..d16cf5f --- /dev/null +++ b/src/samples/FleetManagement.Library/Models/MaintenanceData.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; + +namespace FleetManagement.Library.Models; + +public class MaintenanceData +{ + [JsonPropertyName("id")] + public string? Id { get; set; } + + [JsonPropertyName("vehicleId")] + public string? VehicleId { get; set; } + + [JsonPropertyName("date")] + public DateTime Date { get; set; } + + [JsonPropertyName("type")] + public string? Type { get; set; } + + [JsonPropertyName("description")] + public string? Description { get; set; } + + [JsonPropertyName("cost")] + public double Cost { get; set; } + + [JsonPropertyName("technician")] + public string? Technician { get; set; } + + [JsonPropertyName("status")] + public string? Status { get; set; } + + [JsonPropertyName("mileage")] + public double Mileage { get; set; } +} diff --git a/src/samples/FleetManagement.Library/Services/FleetService.cs b/src/samples/FleetManagement.Library/Services/FleetService.cs index e870d01..43bcff7 100644 --- a/src/samples/FleetManagement.Library/Services/FleetService.cs +++ b/src/samples/FleetManagement.Library/Services/FleetService.cs @@ -19,6 +19,7 @@ public class FleetService }; public List Data { get; private set; } = new(); + public Dictionary> MaintenanceData { get; private set; } = new(); public event Action? OnDataChanged; public FleetService(HttpClient httpClient) @@ -30,8 +31,25 @@ public async Task LoadDataAsync() { try { - var jsonText = await _httpClient.GetStringAsync(VehicleDataUrl); - Data = JsonSerializer.Deserialize>(jsonText, options) ?? new(); + // Load vehicles data + var vehicleJsonText = await _httpClient.GetStringAsync(VehicleDataUrl); + Data = JsonSerializer.Deserialize>(vehicleJsonText, options) ?? new(); + + // Load maintenance data + try + { + var maintenanceJsonText = await _httpClient.GetStringAsync(MaintanenceDataUrl); + var maintenanceList = JsonSerializer.Deserialize>(maintenanceJsonText, options) ?? new(); + + // Group maintenance records by vehicleId + MaintenanceData = maintenanceList + .GroupBy(m => m.VehicleId ?? string.Empty) + .ToDictionary(g => g.Key, g => g.ToList()); + } + catch + { + // Maintenance data is optional - continue if it fails + } OnDataChanged?.Invoke(); } @@ -56,4 +74,13 @@ public void UpdateAllData() OnDataChanged?.Invoke(); } + + public List GetMaintenanceForVehicle(string? vehicleId) + { + if (string.IsNullOrEmpty(vehicleId) || !MaintenanceData.ContainsKey(vehicleId)) + { + return new List(); + } + return MaintenanceData[vehicleId]; + } } diff --git a/src/samples/FleetManagement/Components/App.razor b/src/samples/FleetManagement/Components/App.razor index c28db40..42263e2 100644 --- a/src/samples/FleetManagement/Components/App.razor +++ b/src/samples/FleetManagement/Components/App.razor @@ -9,7 +9,7 @@ - + From 87df5b878eb27db6141c43734a1ec4a6a0e07473 Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:00:32 +0000 Subject: [PATCH 3/3] Fix master-detail interaction by adding CellClick event handler Co-authored-by: dkamburov <1182001+dkamburov@users.noreply.github.com> --- .../FleetManagementComponent.razor | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/samples/FleetManagement.Library/FleetManagementComponent.razor b/src/samples/FleetManagement.Library/FleetManagementComponent.razor index 42aab9f..36ecc22 100644 --- a/src/samples/FleetManagement.Library/FleetManagementComponent.razor +++ b/src/samples/FleetManagement.Library/FleetManagementComponent.razor @@ -74,6 +74,7 @@ AllowFiltering="true" PrimaryKey="VehicleId" Height="400px" + CellClick="OnCellClick" @ref="grid"> @@ -182,6 +183,25 @@ }); } + private void OnCellClick(object args) + { + // Extract the row data from the click event + dynamic eventArgs = args; + try + { + var clickedVehicle = eventArgs.Cell.Row.Data as FleetData; + if (clickedVehicle != null) + { + selectedVehicle = clickedVehicle; + StateHasChanged(); + } + } + catch + { + // Fallback: ignore if event structure is different + } + } + public void Dispose() { updateTimer?.Stop();