260 lines
6.8 KiB
C#
260 lines
6.8 KiB
C#
using RobotNet10.MapEditor.Shared.DTOs.Station;
|
|
using RobotNet10.MapEditor.Services.API;
|
|
|
|
namespace RobotNet10.MapEditor.Services.State;
|
|
|
|
/// <summary>
|
|
/// State management for Station Manager
|
|
/// </summary>
|
|
public class StationManagerState
|
|
{
|
|
private readonly MapManagerApiService _apiService;
|
|
|
|
// Context
|
|
public Guid? CurrentLayoutLevelId { get; private set; }
|
|
|
|
// Data
|
|
public List<StationDto> Stations { get; private set; } = new();
|
|
public StationDto? SelectedStation { get; private set; }
|
|
|
|
// Filters & Search
|
|
public string? SearchQuery { get; set; }
|
|
|
|
// UI State
|
|
public bool IsLoading { get; private set; }
|
|
public bool IsSaving { get; private set; }
|
|
public string? ErrorMessage { get; private set; }
|
|
|
|
// Events
|
|
public event Action? OnStateChanged;
|
|
|
|
public StationManagerState(MapManagerApiService apiService)
|
|
{
|
|
_apiService = apiService;
|
|
}
|
|
|
|
// ==========================================
|
|
// PUBLIC METHODS
|
|
// ==========================================
|
|
|
|
/// <summary>
|
|
/// Initialize or switch to a different layout level
|
|
/// </summary>
|
|
public async Task InitializeAsync(Guid layoutLevelId)
|
|
{
|
|
CurrentLayoutLevelId = layoutLevelId;
|
|
await LoadStationsAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load all stations for the current layout level
|
|
/// </summary>
|
|
public async Task LoadStationsAsync()
|
|
{
|
|
if (!CurrentLayoutLevelId.HasValue)
|
|
{
|
|
ErrorMessage = "No layout level selected";
|
|
NotifyStateChanged();
|
|
return;
|
|
}
|
|
|
|
IsLoading = true;
|
|
ErrorMessage = null;
|
|
NotifyStateChanged();
|
|
|
|
try
|
|
{
|
|
Stations = await _apiService.GetStationsByLevelAsync(CurrentLayoutLevelId.Value);
|
|
NotifyStateChanged();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ErrorMessage = ex.Message;
|
|
Stations = new();
|
|
NotifyStateChanged();
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
NotifyStateChanged();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Search stations by StationId or StationName
|
|
/// </summary>
|
|
public void Search(string? query)
|
|
{
|
|
SearchQuery = query;
|
|
NotifyStateChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select a station for viewing/editing
|
|
/// </summary>
|
|
public async Task SelectStationAsync(Guid? stationId)
|
|
{
|
|
if (!stationId.HasValue)
|
|
{
|
|
SelectedStation = null;
|
|
NotifyStateChanged();
|
|
return;
|
|
}
|
|
|
|
// Try to find in local list first
|
|
SelectedStation = Stations.FirstOrDefault(s => s.Id == stationId.Value);
|
|
|
|
// If not found or need fresh data, fetch from API
|
|
if (SelectedStation == null)
|
|
{
|
|
try
|
|
{
|
|
SelectedStation = await _apiService.GetStationAsync(stationId.Value);
|
|
}
|
|
catch
|
|
{
|
|
SelectedStation = null;
|
|
}
|
|
}
|
|
|
|
NotifyStateChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear selected station
|
|
/// </summary>
|
|
public void ClearSelection()
|
|
{
|
|
SelectedStation = null;
|
|
NotifyStateChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new station
|
|
/// </summary>
|
|
public async Task<StationDto> CreateStationAsync(RobotNet10.MapEditor.Shared.DTOs.Requests.CreateStationRequest request)
|
|
{
|
|
IsSaving = true;
|
|
ErrorMessage = null;
|
|
NotifyStateChanged();
|
|
|
|
try
|
|
{
|
|
var created = await _apiService.CreateStationAsync(request);
|
|
await LoadStationsAsync();
|
|
await SelectStationAsync(created.Id);
|
|
return created;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ErrorMessage = ex.Message;
|
|
NotifyStateChanged();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
IsSaving = false;
|
|
NotifyStateChanged();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update an existing station
|
|
/// </summary>
|
|
public async Task<StationDto> UpdateStationAsync(Guid stationId, RobotNet10.MapEditor.Shared.DTOs.Requests.UpdateStationRequest request)
|
|
{
|
|
IsSaving = true;
|
|
ErrorMessage = null;
|
|
NotifyStateChanged();
|
|
|
|
try
|
|
{
|
|
var updated = await _apiService.UpdateStationAsync(stationId, request);
|
|
|
|
// Update local cache
|
|
var index = Stations.FindIndex(s => s.Id == stationId);
|
|
if (index >= 0)
|
|
{
|
|
Stations[index] = updated;
|
|
}
|
|
|
|
// Update selected if it's the same station
|
|
if (SelectedStation?.Id == stationId)
|
|
{
|
|
SelectedStation = updated;
|
|
}
|
|
|
|
NotifyStateChanged();
|
|
return updated;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ErrorMessage = ex.Message;
|
|
NotifyStateChanged();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
IsSaving = false;
|
|
NotifyStateChanged();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete a station
|
|
/// </summary>
|
|
public async Task DeleteStationAsync(Guid stationId)
|
|
{
|
|
try
|
|
{
|
|
await _apiService.DeleteStationAsync(stationId);
|
|
|
|
// Remove from local list
|
|
Stations.RemoveAll(s => s.Id == stationId);
|
|
|
|
// Clear selection if it was the deleted station
|
|
if (SelectedStation?.Id == stationId)
|
|
{
|
|
SelectedStation = null;
|
|
}
|
|
|
|
NotifyStateChanged();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ErrorMessage = ex.Message;
|
|
NotifyStateChanged();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// ==========================================
|
|
// HELPER METHODS
|
|
// ==========================================
|
|
|
|
/// <summary>
|
|
/// Get filtered stations based on search query
|
|
/// </summary>
|
|
public List<StationDto> GetFilteredStations()
|
|
{
|
|
var query = Stations.AsQueryable();
|
|
|
|
if (!string.IsNullOrWhiteSpace(SearchQuery))
|
|
{
|
|
var searchLower = SearchQuery.ToLowerInvariant();
|
|
query = query.Where(s =>
|
|
s.StationId.ToLower().Contains(searchLower) ||
|
|
(s.StationName != null && s.StationName.ToLower().Contains(searchLower)));
|
|
}
|
|
|
|
return query.OrderBy(s => s.StationId).ToList();
|
|
}
|
|
|
|
private void NotifyStateChanged()
|
|
{
|
|
OnStateChanged?.Invoke();
|
|
}
|
|
}
|
|
|
|
|