@using System.ComponentModel.DataAnnotations @using RackPeek.Domain.Persistence @using RackPeek.Domain.Resources.SystemResources @inject IResourceCollection Repo @if (IsOpen) {
@Title
@* ReSharper disable once CSharpWarnings::CS8619 *@
@foreach (var group in FilteredSystems) { @foreach (var system in group.Value) { } }
} @code { /* ---------- Parameters ---------- */ [Parameter] public bool IsOpen { get; set; } [Parameter] public EventCallback IsOpenChanged { get; set; } [Parameter] [EditorRequired] public string Title { get; set; } = "Select system"; /// /// Default / pre-selected system name (may be null) /// [Parameter] public string? Value { get; set; } /// /// Called with the selected system name /// [Parameter] public EventCallback OnAccept { get; set; } /* ---------- State ---------- */ private SelectionFormModel _model = new(); private string _search = string.Empty; private List _systems = new(); private bool CanAccept => !string.IsNullOrWhiteSpace(_model.Value); /* ---------- Lifecycle ---------- */ protected override async Task OnParametersSetAsync() { if (IsOpen) { _systems = (await Repo.GetAllOfTypeAsync()) .OrderBy(s => s.Type) .ThenBy(s => s.Name) .ToList(); _model = new SelectionFormModel { Value = Value }; _search = string.Empty; } } /* ---------- Computed ---------- */ private Dictionary> FilteredSystems => _systems .Where(s => string.IsNullOrWhiteSpace(_search) || s.Name.Contains(_search.Trim(), StringComparison.OrdinalIgnoreCase)) .GroupBy(s => s.Type ?? "None") .ToDictionary( g => g.Key, g => g.OrderBy(s => s.Name).ToList()); /* ---------- Actions ---------- */ private async Task HandleAccept() { await OnAccept.InvokeAsync(_model.Value); await Close(); } private async Task Cancel() { await Close(); } private async Task Close() { _model = new SelectionFormModel(); _search = string.Empty; await IsOpenChanged.InvokeAsync(false); } /* ---------- Model ---------- */ private sealed class SelectionFormModel { [Required] public string? Value { get; set; } } /* ---------- Search ---------- */ private void OnSearchChanged(string? value) { _search = value ?? string.Empty; } private void OnSearchInput(ChangeEventArgs e) { _search = e.Value?.ToString() ?? string.Empty; // Clear selection if it is no longer visible if (FilteredSystems .SelectMany(g => g.Value) .All(s => s.Name != _model.Value)) { _model.Value = null; } } }