This commit is contained in:
6d486f49
2026-06-11 16:18:36 -04:00
parent f98d37fae4
commit 11ef727efe
+384
View File
@@ -0,0 +1,384 @@
@inherits BasePage
@page "/catalog"
@using Model
@using Model.Entity.Data
@using Model.Entity.Parts
@implements IDisposable
@inject IEntityDisplayService EntityDisplayService
@inject NavigationManager NavigationManager
<LayoutLargeContentComponent>
<WebsiteTitleComponent>Catalog</WebsiteTitleComponent>
<PaperComponent>
<FormDisplayComponent Label="Patch">
<Display>
Game Patch: @Variables.GamePatch
</Display>
</FormDisplayComponent>
</PaperComponent>
<PaperComponent>
<EntityFilterComponent></EntityFilterComponent>
<div class="catalogResultCount">
@searches.Count @(searches.Count == 1 ? "entity" : "entities")
</div>
@if (searches.Any())
{
<div class="catalogGrid">
@foreach (var entity in searches)
{
<PaperComponent>
<div class="catalogCard" @onclick="() => NavigateToEntity(entity)">
<div class="catalogCardHeader">
<span class="catalogCardName">@entity.Info().Name</span>
<span class="catalogCardType type-@(entity.EntityType.ToLower().Replace("_", "-"))">@entity.EntityType.Replace("_", " ")</span>
</div>
<div class="catalogCardSubheader">
@{
var faction = entity.Faction();
}
@if (faction != null)
{
var factionName = EntityData.Get().TryGetValue(faction.Faction, out var fac) ? fac.Info().Name : "";
<span class="catalogCardFaction">@factionName</span>
}
@{
var vanguard = entity.VanguardAdded();
}
@if (vanguard != null)
{
<span class="catalogCardDivider">|</span>
var immortalName = EntityData.Get().TryGetValue(vanguard.ImmortalId, out var imm) ? imm.Info().Name : "";
<span class="catalogCardImmortal">@immortalName</span>
}
</div>
@if (!string.IsNullOrEmpty(entity.Info().Description))
{
<div class="catalogCardDesc">
@(entity.Info().Description.Length > 160
? entity.Info().Description[..157] + "..."
: entity.Info().Description)
</div>
}
<div class="catalogCardStats">
@{
var tier = entity.Tier();
if (tier != null && tier.Tier > 0)
{
<span class="catalogStat" title="Tier">T@(tier.Tier)</span>
}
}
@{
var supply = entity.Supply();
if (supply != null && (supply.Takes > 0 || supply.Grants > 0))
{
<span class="catalogStat" title="Supply">@supply.Takes@(supply.Grants > 0 ? $"/{supply.Grants}" : "")</span>
}
}
@{
var prod = entity.Production();
if (prod != null)
{
if (prod.Alloy > 0) { <span class="catalogStat catalogStatAlloy" title="Alloy">@prod.Alloy</span> }
if (prod.Ether > 0) { <span class="catalogStat catalogStatEther" title="Ether">@prod.Ether</span> }
if (prod.Pyre > 0) { <span class="catalogStat catalogStatPyre" title="Pyre">@prod.Pyre</span> }
if (prod.Energy > 0) { <span class="catalogStat catalogStatEnergy" title="Energy">@prod.Energy</span> }
if (prod.BuildTime > 0) { <span class="catalogStat" title="Build time">@prod.BuildTime"s</span> }
}
}
@{
var vitality = entity.Vitality();
if (vitality != null && vitality.Health > 0)
{
<span class="catalogStat catalogStatHealth" title="Health">@vitality.Health</span>
}
}
</div>
</div>
</PaperComponent>
}
</div>
}
else
{
<div class="catalogEmpty">No entities match the selected filters.</div>
}
</PaperComponent>
</LayoutLargeContentComponent>
<style>
.catalogResultCount {
padding: 8px 0 16px 0;
font-size: 0.85rem;
opacity: 0.6;
}
.catalogGrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 16px;
}
.catalogCard {
cursor: pointer;
}
.catalogCard:hover .catalogCardName {
color: var(--primary-hover);
}
.catalogCardHeader {
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
margin-bottom: 4px;
}
.catalogCardName {
font-size: 1.1rem;
font-weight: 800;
transition: color 0.15s ease;
}
.catalogCardType {
font-size: 0.7rem;
padding: 2px 8px;
border-radius: 4px;
font-weight: 700;
white-space: nowrap;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.type-army { background: #1a6b8a; color: #fff; }
.type-building { background: #5a7a1a; color: #fff; }
.type-building-upgrade { background: #4a6a0a; color: #fff; }
.type-ability { background: #8a1a6b; color: #fff; }
.type-passive { background: #8a6b1a; color: #fff; }
.type-immortal { background: #6b1a8a; color: #fff; }
.type-worker { background: #1a6b4a; color: #fff; }
.type-tech { background: #3a1a6b; color: #fff; }
.type-spell { background: #1a3a8a; color: #fff; }
.type-faction { background: #6b3a1a; color: #fff; }
.type-command { background: #3a6b2a; color: #fff; }
.type-none { background: #444; color: #fff; }
.catalogCardSubheader {
display: flex;
gap: 6px;
margin-bottom: 8px;
font-size: 0.8rem;
align-items: center;
}
.catalogCardFaction {
opacity: 0.8;
}
.catalogCardImmortal {
opacity: 0.6;
}
.catalogCardDivider {
opacity: 0.3;
}
.catalogCardDesc {
font-size: 0.85rem;
line-height: 1.45;
opacity: 0.8;
margin-bottom: 12px;
}
.catalogCardStats {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.catalogStat {
font-size: 0.72rem;
padding: 2px 8px;
border-radius: 4px;
background: var(--secondary);
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
}
.catalogStatAlloy {
background: #8a7a2a;
}
.catalogStatEther {
background: #2a6a8a;
}
.catalogStatPyre {
background: #8a3a2a;
}
.catalogStatEnergy {
background: #2a8a6a;
}
.catalogStatHealth {
background: #4a2a6a;
}
.catalogEmpty {
padding: 32px;
text-align: center;
opacity: 0.5;
font-style: italic;
}
@@media only screen and (max-width: 1025px) {
.catalogGrid {
grid-template-columns: 1fr;
}
}
</style>
@code {
[Inject] public IEntityFilterService EntityFilterService { get; set; } = default!;
readonly List<EntityModel> defaults = (from entity in EntityModel.GetList()
where !entity.IsSpeculative
select entity).ToList();
List<EntityModel> factions = default!;
List<EntityModel> immortals = default!;
List<EntityModel> entities = default!;
List<EntityModel> searches = default!;
string selectedFactionType = DataType.Any;
string selectedImmortalType = DataType.Any;
string selectedEntityType = EntityType.Army;
string searchText = "";
protected override void OnInitialized()
{
base.OnInitialized();
RefreshFactionSearch();
EntityFilterService.Subscribe(OnChange);
EntityDisplayService.Subscribe(StateHasChanged);
}
void IDisposable.Dispose()
{
EntityFilterService.Unsubscribe(OnChange);
EntityDisplayService.Unsubscribe(StateHasChanged);
}
void NavigateToEntity(EntityModel entity)
{
NavigationManager.NavigateTo($"/database/{Uri.EscapeDataString(entity.Info().Name)}");
}
void OnChange(EntityFilterEvent filterEntityEvent)
{
if (filterEntityEvent == EntityFilterEvent.OnRefreshFaction)
{
RefreshFactionSearch();
}
if (filterEntityEvent == EntityFilterEvent.OnRefreshImmortal)
{
RefreshImmortalSearch();
}
if (filterEntityEvent == EntityFilterEvent.OnRefreshEntity)
{
RefreshEntitySearch();
}
if (filterEntityEvent == EntityFilterEvent.OnRefreshSearch)
{
RefreshTextSearch();
}
}
void RefreshFactionSearch()
{
selectedFactionType = EntityFilterService.GetFactionType();
if (selectedFactionType == DataType.Any)
{
factions = defaults.ToList();
}
else
{
factions = (from entity in defaults
where entity.Faction() != null && entity.Faction().Faction == selectedFactionType
select entity).ToList();
}
RefreshImmortalSearch();
}
void RefreshImmortalSearch()
{
selectedImmortalType = EntityFilterService.GetImmortalType();
if (selectedImmortalType == DataType.Any)
{
immortals = factions.ToList();
}
else
{
immortals = (from entity in factions
let vanguardAdded = entity.VanguardAdded()
where vanguardAdded == null || vanguardAdded.ImmortalId == selectedImmortalType
select entity).ToList();
}
RefreshEntitySearch();
}
void RefreshEntitySearch()
{
selectedEntityType = EntityFilterService.GetEntityType();
if (selectedEntityType == EntityType.Any)
{
entities = immortals.ToList();
}
else
{
entities = (from entity in immortals
where entity.EntityType == selectedEntityType
select entity).ToList();
}
RefreshTextSearch();
}
void RefreshTextSearch()
{
searchText = EntityFilterService.GetSearchText();
if (searchText.Trim() == "")
{
searches = entities.ToList();
}
else
{
searches = (from entity in entities
where entity.Info().Name.ToLower().Contains(searchText.ToLower())
select entity).ToList();
}
StateHasChanged();
}
}