Files
I150/srcs/RobotNet10/Components/RobotNet10.MapEditor/Services/State/LayoutManagerState.cs
2026-07-03 16:37:12 +07:00

243 lines
6.7 KiB
C#

using RobotNet10.MapEditor.Shared.DTOs.Layout;
using RobotNet10.MapEditor.Shared.DTOs.LayoutData;
using RobotNet10.MapEditor.Shared.DTOs.Requests;
using RobotNet10.MapEditor.Services.API;
namespace RobotNet10.MapEditor.Services.State;
/// <summary>
/// State management for LayoutManager page
/// </summary>
public class LayoutManagerState
{
// ===== DATA =====
public List<LayoutDto> Layouts { get; set; } = new();
// ===== SELECTION =====
public LayoutDto? SelectedLayout { get; set; }
public LayoutVersionDto? SelectedVersion { get; set; }
public LayoutLevelDto? SelectedLevel { get; set; }
// ===== PREVIEW DATA =====
public LayoutDataDto? PreviewData { get; set; }
public byte[]? PreviewImage { get; set; }
// ===== UI STATE =====
public bool IsLoading { get; set; }
public bool IsLoadingPreview { get; set; }
public string? SearchText { get; set; }
// ===== EVENTS =====
public event Action? OnStateChanged;
// ===== DEPENDENCIES =====
private readonly MapManagerApiService _apiService;
public LayoutManagerState(MapManagerApiService apiService)
{
_apiService = apiService;
}
// ==========================================
// PUBLIC METHODS
// ==========================================
/// <summary>
/// Load all layouts with nested versions and levels
/// </summary>
public async Task LoadLayoutsAsync(string? searchText = null)
{
IsLoading = true;
SearchText = searchText;
NotifyStateChanged();
try
{
Layouts = await _apiService.SearchLayoutsAsync(searchText);
}
catch (Exception ex)
{
Console.WriteLine($"Error loading layouts: {ex.Message}");
Layouts = new();
}
IsLoading = false;
NotifyStateChanged();
}
/// <summary>
/// Select a level and load preview data
/// </summary>
public async Task SelectLevelAsync(LayoutLevelDto level)
{
SelectedLevel = level;
// Find parent version and layout
foreach (var layout in Layouts)
{
if (layout.Versions == null) continue;
foreach (var version in layout.Versions)
{
if (version.Levels?.Any(l => l.Id == level.Id) == true)
{
SelectedLayout = layout;
SelectedVersion = version;
break;
}
}
if (SelectedVersion != null) break;
}
await LoadPreviewAsync(level.Id);
}
/// <summary>
/// Clear selection
/// </summary>
public void ClearSelection()
{
SelectedLayout = null;
SelectedVersion = null;
SelectedLevel = null;
PreviewData = null;
PreviewImage = null;
NotifyStateChanged();
}
/// <summary>
/// Create new layout
/// </summary>
public async Task<LayoutDto> CreateLayoutAsync(CreateLayoutRequest request)
{
var layout = await _apiService.CreateLayoutAsync(request);
await LoadLayoutsAsync(SearchText); // Reload
return layout;
}
/// <summary>
/// Delete layout
/// </summary>
public async Task DeleteLayoutAsync(Guid layoutId)
{
await _apiService.DeleteLayoutAsync(layoutId);
await LoadLayoutsAsync(SearchText); // Reload
// Clear selection if deleted
if (SelectedLayout?.Id == layoutId)
{
ClearSelection();
}
}
/// <summary>
/// Create new version
/// </summary>
public async Task<LayoutVersionDto> CreateVersionAsync(Guid layoutId, CreateLayoutVersionRequest request)
{
var version = await _apiService.CreateVersionAsync(layoutId, request);
await LoadLayoutsAsync(SearchText); // Reload
return version;
}
/// <summary>
/// Delete version
/// </summary>
public async Task DeleteVersionAsync(Guid versionId)
{
await _apiService.DeleteVersionAsync(versionId);
await LoadLayoutsAsync(SearchText); // Reload
// Clear selection if deleted
if (SelectedVersion?.Id == versionId)
{
ClearSelection();
}
}
/// <summary>
/// Create new level
/// </summary>
public async Task<LayoutLevelDto> CreateLevelAsync(Guid versionId, CreateLayoutLevelRequest request)
{
var level = await _apiService.CreateLevelAsync(versionId, request);
await LoadLayoutsAsync(SearchText); // Reload
return level;
}
/// <summary>
/// Delete level
/// </summary>
public async Task DeleteLevelAsync(Guid levelId)
{
await _apiService.DeleteLevelAsync(levelId);
await LoadLayoutsAsync(SearchText); // Reload
// Clear selection if deleted
if (SelectedLevel?.Id == levelId)
{
ClearSelection();
}
}
/// <summary>
/// Activate layout
/// </summary>
public async Task ActivateLayoutAsync(Guid layoutId)
{
await _apiService.ActivateLayoutAsync(layoutId);
await LoadLayoutsAsync(SearchText); // Reload to get updated IsActive status
}
/// <summary>
/// Deactivate layout
/// </summary>
public async Task DeactivateLayoutAsync(Guid layoutId)
{
await _apiService.DeactivateLayoutAsync(layoutId);
await LoadLayoutsAsync(SearchText); // Reload
}
// ==========================================
// PRIVATE METHODS
// ==========================================
/// <summary>
/// Load preview data (nodes, edges, image)
/// </summary>
private async Task LoadPreviewAsync(Guid levelId)
{
IsLoadingPreview = true;
NotifyStateChanged();
try
{
// Load layout data
PreviewData = await _apiService.GetLayoutDataAsync(levelId);
// Load background image
try
{
PreviewImage = await _apiService.GetLayoutImageAsync(levelId);
}
catch
{
PreviewImage = null; // Image might not exist yet
}
}
catch (Exception ex)
{
Console.WriteLine($"Error loading preview: {ex.Message}");
PreviewData = null;
PreviewImage = null;
}
IsLoadingPreview = false;
NotifyStateChanged();
}
private void NotifyStateChanged() => OnStateChanged?.Invoke();
}