Files
ChronoCCG/Chrono/Shared/Pages/Docs.razor
T

164 lines
5.9 KiB
Plaintext

@inject Shared.Services.CardRenderingService CardRenderer
@inject Shared.Services.CardPreviewService PreviewService
@namespace Shared.Pages
@page "/docs"
<PageTitle>Docs</PageTitle>
<div class="docs-page">
<div class="docs-header">
<h1>Documentation</h1>
<p class="text-muted">Rules, keywords, factions, and more.</p>
</div>
<div class="docs-container">
<aside class="docs-sidebar">
<div class="search-box">
<i class="bi bi-search"></i>
<input type="text" placeholder="Search docs..." @bind="searchQuery" @bind:event="oninput"/>
</div>
<div class="category-list">
<div class="category-item @(selectedCategory == null ? "active" : "")"
@onclick="() => SelectCategory(null)">
All Pages
</div>
@foreach (var category in categories)
{
var cat = category;
<div class="category-item @(selectedCategory == cat ? "active" : "")"
@onclick="() => SelectCategory(cat)">
@cat
</div>
}
</div>
</aside>
<main class="docs-content">
@if (selectedDoc == null)
{
<div class="doc-list">
@foreach (var doc in filteredDocs)
{
<div class="doc-card" @onclick="() => SelectDoc(doc)">
<div class="doc-card-category">@doc.Category</div>
<h3 class="doc-card-title">@doc.Title</h3>
@if (GetField(doc, "description") is { Length: > 0 } desc)
{
<p class="doc-card-desc">@desc</p>
}
</div>
}
@if (!filteredDocs.Any())
{
<div class="empty-state">
<i class="bi bi-search"></i>
<p>No documentation found matching your search.</p>
</div>
}
</div>
}
else
{
<article class="doc-article">
<button class="btn-back" @onclick="() => SelectDoc(null)">
<i class="bi bi-arrow-left"></i> Back to list
</button>
<header class="doc-header">
<div class="doc-meta">@selectedDoc.Category</div>
<h1>@selectedDoc.Title</h1>
</header>
<div class="doc-fields">
@{
var fm = selectedDoc.Frontmatter;
}
@foreach (var kvp in fm)
{
var key = kvp.Key;
var val = kvp.Value;
if (string.IsNullOrWhiteSpace(val)) continue;
<div class="doc-field">
<span class="doc-field-key">@GetLabel(key)</span>
@if (key == "description")
{
<div class="doc-field-desc">
@CardRenderer.RenderDescription(val, _ => {}, doc => PreviewService.SelectDoc(doc), PreviewService)
</div>
}
else
{
<span class="doc-field-val">@val</span>
}
</div>
}
</div>
</article>
}
</main>
</div>
</div>
@code {
private string searchQuery = "";
private string? selectedCategory;
private DocData? selectedDoc;
private List<string> categories = [];
private List<DocData> allDocs = [];
protected override void OnInitialized()
{
allDocs = DocDatabase.Docs.OrderBy(d => d.Category).ThenBy(d => d.Title).ToList();
categories = allDocs.Select(d => d.Category).Distinct().OrderBy(c => c).ToList();
}
private IEnumerable<DocData> filteredDocs => allDocs
.Where(d => (selectedCategory == null || d.Category == selectedCategory) &&
(string.IsNullOrWhiteSpace(searchQuery) ||
d.Title.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ||
(GetField(d, "description")?.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ?? false)));
private void SelectCategory(string? category)
{
selectedCategory = category;
selectedDoc = null;
}
private void SelectDoc(DocData? doc)
{
selectedDoc = doc;
}
private static string? GetField(DocData doc, string key)
{
return doc.Frontmatter.TryGetValue(key, out var val) && !string.IsNullOrWhiteSpace(val) ? val : null;
}
private static string GetLabel(string key)
{
return key switch
{
"category" => "Category",
"description" => "Description",
"essencePrice" => "Essence Price",
"crytalPrice" => "Crystal Price",
"coreChargesPrice" => "Core Charges Price",
"pricePerPack" => "Price per Pack",
"codeCharges" => "Code Charges",
"coreCharges" => "Core Charges",
"currency" => "Currency",
"faction" => "Faction",
"exp" => "EXP Reward",
"see" => "See Also",
_ => string.Concat(key.Select((c, i) => i > 0 && char.IsUpper(c) ? " " + c : c.ToString()))
};
}
}