AI: Remove Telerik — ZeroSpace.Web/Pages/Units.razor
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
@page "/units"
|
@page "/units"
|
||||||
@using ZeroSpace.Model
|
@using ZeroSpace.Model
|
||||||
@using ZeroSpace.Web.Services
|
@using ZeroSpace.Web.Services
|
||||||
@using Telerik.Blazor
|
|
||||||
@using Telerik.Blazor.Components
|
|
||||||
@inject IUnitsApiClient UnitsApiClient
|
@inject IUnitsApiClient UnitsApiClient
|
||||||
|
|
||||||
<PageTitle>Units</PageTitle>
|
<PageTitle>Units</PageTitle>
|
||||||
@@ -29,7 +27,7 @@ else if (errorMessage != null)
|
|||||||
<button class="btn btn-outline-danger btn-sm" @onclick="LoadUnitsAsync">Retry</button>
|
<button class="btn btn-outline-danger btn-sm" @onclick="LoadUnitsAsync">Retry</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
else if (gearNotes == null || gearNotes.Count == 0)
|
else if (units == null || units.Count == 0)
|
||||||
{
|
{
|
||||||
<div class="alert alert-warning" role="alert">
|
<div class="alert alert-warning" role="alert">
|
||||||
No units found.
|
No units found.
|
||||||
@@ -37,42 +35,159 @@ else if (gearNotes == null || gearNotes.Count == 0)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<div class="grid-container">
|
<div class="table-responsive">
|
||||||
<TelerikGrid Data="@gearNotes" Pageable="true" PageSize="50" Sortable="true" FilterMode="@GridFilterMode.FilterRow"
|
<table class="table table-striped table-hover table-sm align-middle text-nowrap">
|
||||||
Height="calc(100vh - 250px)">
|
<thead class="table-light">
|
||||||
<GridColumns>
|
<tr>
|
||||||
<GridColumn Field="@(nameof(UnitData.Name))" Title="Name" Width="200px"/>
|
@foreach (var col in Columns)
|
||||||
<GridColumn Field="@(nameof(UnitData.Hexite))" Title="Hexite" Width="90px" />
|
{
|
||||||
<GridColumn Field="@(nameof(UnitData.Flux))" Title="Flux" Width="90px" />
|
<th style="min-width:@col.Width">
|
||||||
|
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none text-body fw-bold" @onclick="() => ToggleSort(col.Key)" title="Sort by @col.Title">
|
||||||
<GridColumn Field="@(nameof(UnitData.DpsPerTotalCost))" Title="DpsPerTotalCost" Width="90px" />
|
@col.Title
|
||||||
|
<span class="text-muted">@SortGlyph(col.Key)</span>
|
||||||
<GridColumn Field="@(nameof(UnitData.HealthPerTotalCost))" Title="HealthPerTotalCost" Width="90px" />
|
</button>
|
||||||
|
</th>
|
||||||
<GridColumn Field="@(nameof(UnitData.Supply))" Title="Supply" Width="90px" />
|
}
|
||||||
<GridColumn Field="@(nameof(UnitData.ProductionTime))" Title="Production Time" Width="90px" />
|
</tr>
|
||||||
<GridColumn Field="@(nameof(UnitData.Health))" Title="Health" Width="90px" />
|
<tr>
|
||||||
<GridColumn Field="@(nameof(UnitData.Shields))" Title="Shields" Width="90px" />
|
@foreach (var col in Columns)
|
||||||
<GridColumn Field="@(nameof(UnitData.ArmorRating))" Title="Armor Rating" Width="90px" />
|
{
|
||||||
<GridColumn Field="@(nameof(UnitData.MovementSpeed))" Title="Movement Speed" Width="90px" />
|
<th>
|
||||||
<GridColumn Field="@(nameof(UnitData.DamagePerSecond))" Title="Damage Per Second" Width="90px" />
|
<input class="form-control form-control-sm" placeholder="Filter" aria-label="Filter @col.Title"
|
||||||
<GridColumn Field="@(nameof(UnitData.AttackRange))" Title="Attack Range" Width="90px" />
|
value="@GetFilter(col.Key)"
|
||||||
<GridColumn Field="@(nameof(UnitData.Attributes))" Title="Attributes" Width="90px" />
|
@oninput="(e) => SetFilter(col.Key, e.Value?.ToString())" />
|
||||||
<GridColumn Field="@(nameof(UnitData.Tier))" Title="Tier" Width="90px" />
|
</th>
|
||||||
<GridColumn Field="@(nameof(UnitData.Faction))" Title="Faction" Width="90px" />
|
}
|
||||||
<GridColumn Field="@(nameof(UnitData.Hotkey))" Title="Hotkey" Width="90px" />
|
</tr>
|
||||||
<GridColumn Field="@(nameof(UnitData.BuildAtSameTime))" Title="Build At Same Time" Width="90px" />
|
</thead>
|
||||||
<GridColumn Field="@(nameof(UnitData.Limit))" Title="Limit" Width="90px" />
|
<tbody>
|
||||||
</GridColumns>
|
@foreach (var unit in PagedUnits)
|
||||||
</TelerikGrid>
|
{
|
||||||
|
<tr>
|
||||||
|
@foreach (var col in Columns)
|
||||||
|
{
|
||||||
|
<td>@col.Display(unit)</td>
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center gap-2 mt-2">
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-sm" disabled="@(page <= 1)" @onclick="() => ChangePage(page - 1)">Previous</button>
|
||||||
|
<span class="text-muted">Page @(page) of @TotalPages (@SortedUnits.Count units)</span>
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-sm" disabled="@(page >= TotalPages)" @onclick="() => ChangePage(page + 1)">Next</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<UnitData>? gearNotes;
|
private List<UnitData>? units;
|
||||||
private bool isLoading = true;
|
private bool isLoading = true;
|
||||||
private string? errorMessage;
|
private string? errorMessage;
|
||||||
|
|
||||||
|
private string? sortKey;
|
||||||
|
private bool sortAscending = true;
|
||||||
|
private int page = 1;
|
||||||
|
private const int PageSize = 50;
|
||||||
|
private readonly Dictionary<string, string> filters = new();
|
||||||
|
|
||||||
|
private sealed record ColumnDef(
|
||||||
|
string Key,
|
||||||
|
string Title,
|
||||||
|
string Width,
|
||||||
|
Func<UnitData, IComparable?> SortValue,
|
||||||
|
Func<UnitData, string> Display);
|
||||||
|
|
||||||
|
private static readonly IReadOnlyList<ColumnDef> Columns = new List<ColumnDef>
|
||||||
|
{
|
||||||
|
new("Name", "Name", "200px", u => u.Name, u => u.Name),
|
||||||
|
new("Hexite", "Hexite", "90px", u => u.Hexite, u => u.Hexite.ToString()),
|
||||||
|
new("Flux", "Flux", "90px", u => u.Flux, u => u.Flux.ToString()),
|
||||||
|
new("DpsPerTotalCost", "DpsPerTotalCost", "90px", u => u.DpsPerTotalCost, u => u.DpsPerTotalCost.ToString()),
|
||||||
|
new("HealthPerTotalCost", "HealthPerTotalCost", "90px", u => u.HealthPerTotalCost, u => u.HealthPerTotalCost.ToString()),
|
||||||
|
new("Supply", "Supply", "90px", u => u.Supply, u => u.Supply.ToString()),
|
||||||
|
new("ProductionTime", "Production Time", "90px", u => u.ProductionTime, u => u.ProductionTime.ToString()),
|
||||||
|
new("Health", "Health", "90px", u => u.Health, u => u.Health.ToString()),
|
||||||
|
new("Shields", "Shields", "90px", u => u.Shields, u => u.Shields.ToString()),
|
||||||
|
new("ArmorRating", "Armor Rating", "90px", u => u.ArmorRating, u => u.ArmorRating.ToString()),
|
||||||
|
new("MovementSpeed", "Movement Speed", "90px", u => u.MovementSpeed, u => u.MovementSpeed.ToString()),
|
||||||
|
new("DamagePerSecond", "Damage Per Second", "90px", u => u.DamagePerSecond, u => u.DamagePerSecond.ToString()),
|
||||||
|
new("AttackRange", "Attack Range", "90px", u => u.AttackRange, u => u.AttackRange.ToString()),
|
||||||
|
new("Attributes", "Attributes", "90px", u => string.Join(", ", u.Attributes), u => string.Join(", ", u.Attributes)),
|
||||||
|
new("Tier", "Tier", "90px", u => u.Tier, u => u.Tier.ToString()),
|
||||||
|
new("Faction", "Faction", "90px", u => u.Faction, u => u.Faction),
|
||||||
|
new("Hotkey", "Hotkey", "90px", u => u.Hotkey, u => u.Hotkey ?? string.Empty),
|
||||||
|
new("BuildAtSameTime", "Build At Same Time", "90px", u => u.BuildAtSameTime, u => u.BuildAtSameTime.ToString()),
|
||||||
|
new("Limit", "Limit", "90px", u => u.Limit, u => u.Limit?.ToString() ?? string.Empty),
|
||||||
|
};
|
||||||
|
|
||||||
|
private List<UnitData> SortedUnits
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var query = (units ?? new List<UnitData>()).AsEnumerable();
|
||||||
|
|
||||||
|
foreach (var col in Columns)
|
||||||
|
{
|
||||||
|
if (filters.TryGetValue(col.Key, out var text) && !string.IsNullOrWhiteSpace(text))
|
||||||
|
{
|
||||||
|
query = query.Where(u => col.Display(u).Contains(text, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sortCol = Columns.FirstOrDefault(c => c.Key == sortKey);
|
||||||
|
if (sortCol != null)
|
||||||
|
{
|
||||||
|
query = sortAscending
|
||||||
|
? query.OrderBy(u => sortCol.SortValue(u))
|
||||||
|
: query.OrderByDescending(u => sortCol.SortValue(u));
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int TotalPages => Math.Max(1, (int)Math.Ceiling(SortedUnits.Count / (double)PageSize));
|
||||||
|
|
||||||
|
private List<UnitData> PagedUnits => SortedUnits.Skip((page - 1) * PageSize).Take(PageSize).ToList();
|
||||||
|
|
||||||
|
private void ToggleSort(string key)
|
||||||
|
{
|
||||||
|
if (sortKey == key)
|
||||||
|
{
|
||||||
|
sortAscending = !sortAscending;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sortKey = key;
|
||||||
|
sortAscending = true;
|
||||||
|
}
|
||||||
|
page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SortGlyph(string key) => sortKey == key ? (sortAscending ? "▲" : "▼") : string.Empty;
|
||||||
|
|
||||||
|
private string GetFilter(string key) => filters.TryGetValue(key, out var value) ? value : string.Empty;
|
||||||
|
|
||||||
|
private void SetFilter(string key, string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
filters.Remove(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filters[key] = value;
|
||||||
|
}
|
||||||
|
page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangePage(int newPage)
|
||||||
|
{
|
||||||
|
page = Math.Clamp(newPage, 1, TotalPages);
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await LoadUnitsAsync();
|
await LoadUnitsAsync();
|
||||||
@@ -85,8 +200,8 @@ else
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var units = await UnitsApiClient.GetUnitsAsync();
|
var result = await UnitsApiClient.GetUnitsAsync();
|
||||||
gearNotes = units.ToList();
|
units = result.ToList();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user