...
This commit is contained in:
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user