More notes and added store precons
This commit is contained in:
@@ -6,8 +6,13 @@
|
||||
<div class="decks-page">
|
||||
<div class="decks-header">
|
||||
<h1>Decks</h1>
|
||||
<p class="text-secondary">@decks.Count deck@(decks.Count != 1 ? "s" : "")</p>
|
||||
<p class="text-primary">Please note these are my crafted decks. They are probably not optimal or good. See <a href="https://runeterra.ar/chrono/home">Runeterra.ar</a> and check out the decks from recognizable names there. This is not an ad, just common sense.</p>
|
||||
<div class="decks-header-row">
|
||||
<p class="text-secondary">@decks.Count deck@(decks.Count != 1 ? "s" : "")</p>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="showPrecons" @bind="showPrecons" @bind:after="RefreshDecks">
|
||||
<label class="form-check-label" for="showPrecons">Show Precons</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="deck-list">
|
||||
@@ -25,6 +30,11 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="deck-card-factions">
|
||||
<span class="faction-badge">@deck.DeckType</span>
|
||||
</div>
|
||||
|
||||
<div class="deck-card-meta">
|
||||
<span>@deck.Cards.Distinct().Count() unique, @deck.Cards.Count total</span>
|
||||
@if (deck.Keycards.Count > 0)
|
||||
@@ -56,10 +66,22 @@
|
||||
|
||||
@code {
|
||||
private List<DeckData> decks = [];
|
||||
private bool showPrecons = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
decks = DeckDatabase.Decks.Where(d => d.IsVisible).ToList();
|
||||
RefreshDecks();
|
||||
}
|
||||
|
||||
private void RefreshDecks()
|
||||
{
|
||||
decks = DeckDatabase.Decks
|
||||
.Where(d => d.IsVisible)
|
||||
.Where(d =>
|
||||
showPrecons
|
||||
? d.DeckType is "precon" or "store" :
|
||||
d.DeckType is "custom")
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static string Truncate(string text, int maxLength)
|
||||
|
||||
@@ -8,6 +8,16 @@
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.decks-header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.decks-header-row p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.decks-header h1 {
|
||||
margin: 0 0 0.25rem;
|
||||
}
|
||||
|
||||
+41
-125
@@ -39,10 +39,7 @@
|
||||
<div class="doc-card" @onclick="() => SelectDoc(doc)">
|
||||
<div class="doc-card-category">@doc.Category</div>
|
||||
<h3 class="doc-card-title">@doc.Title</h3>
|
||||
@{
|
||||
var desc = GetDescription(doc);
|
||||
}
|
||||
@if (desc != null)
|
||||
@if (GetField(doc, "description") is { Length: > 0 } desc)
|
||||
{
|
||||
<p class="doc-card-desc">@desc</p>
|
||||
}
|
||||
@@ -67,37 +64,34 @@
|
||||
<header class="doc-header">
|
||||
<div class="doc-meta">@selectedDoc.Category</div>
|
||||
<h1>@selectedDoc.Title</h1>
|
||||
@{
|
||||
var desc = GetDescription(selectedDoc);
|
||||
}
|
||||
@if (desc != null)
|
||||
{
|
||||
<p class="doc-description">@desc</p>
|
||||
}
|
||||
</header>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(selectedDoc.Content))
|
||||
{
|
||||
<div class="doc-body">
|
||||
@((MarkupString)FormatContent(selectedDoc.Content))
|
||||
</div>
|
||||
}
|
||||
<div class="doc-fields">
|
||||
@{
|
||||
var fm = selectedDoc.Frontmatter;
|
||||
}
|
||||
|
||||
@if (HasExtraFrontmatter(selectedDoc))
|
||||
{
|
||||
<div class="doc-extra">
|
||||
<h3>Details</h3>
|
||||
<div class="doc-frontmatter">
|
||||
@foreach (var kvp in selectedDoc.Frontmatter.Where(kvp => kvp.Key != "category" && kvp.Key != "description"))
|
||||
@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="fm-item">
|
||||
<span class="fm-key">@kvp.Key</span>
|
||||
<span class="fm-value">@kvp.Value</span>
|
||||
</div>
|
||||
<p class="doc-field-desc">@val</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="doc-field-val">@val</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
</main>
|
||||
@@ -122,8 +116,7 @@
|
||||
.Where(d => (selectedCategory == null || d.Category == selectedCategory) &&
|
||||
(string.IsNullOrWhiteSpace(searchQuery) ||
|
||||
d.Title.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ||
|
||||
(GetDescription(d)?.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ?? false) ||
|
||||
d.Content.Contains(searchQuery, StringComparison.OrdinalIgnoreCase)));
|
||||
(GetField(d, "description")?.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) ?? false)));
|
||||
|
||||
private void SelectCategory(string? category)
|
||||
{
|
||||
@@ -136,102 +129,25 @@
|
||||
selectedDoc = doc;
|
||||
}
|
||||
|
||||
private static string? GetDescription(DocData doc)
|
||||
private static string? GetField(DocData doc, string key)
|
||||
{
|
||||
return doc.Frontmatter.TryGetValue("description", out var desc) && !string.IsNullOrWhiteSpace(desc) ? desc : null;
|
||||
return doc.Frontmatter.TryGetValue(key, out var val) && !string.IsNullOrWhiteSpace(val) ? val : null;
|
||||
}
|
||||
|
||||
private static bool HasExtraFrontmatter(DocData doc)
|
||||
private static string GetLabel(string key) => key switch
|
||||
{
|
||||
var count = doc.Frontmatter.Count;
|
||||
if (count == 0) return false;
|
||||
if (count == 1 && doc.Frontmatter.ContainsKey("category")) return false;
|
||||
if (count == 2 && doc.Frontmatter.ContainsKey("category") && doc.Frontmatter.ContainsKey("description")) return false;
|
||||
return doc.Frontmatter.Any(kvp => kvp.Key != "category" && kvp.Key != "description");
|
||||
}
|
||||
|
||||
private string FormatContent(string content)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content)) return "";
|
||||
|
||||
var lines = content.Replace("\r\n", "\n").Split('\n');
|
||||
var html = new System.Text.StringBuilder();
|
||||
var inList = false;
|
||||
|
||||
foreach (var rawLine in lines)
|
||||
{
|
||||
var line = rawLine.TrimEnd();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
if (inList) { html.AppendLine("</ul>"); inList = false; }
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith("- "))
|
||||
{
|
||||
var item = line[2..].Trim();
|
||||
if (item.Length > 0)
|
||||
{
|
||||
if (!inList) { html.AppendLine("<ul class=\"doc-list-items\">"); inList = true; }
|
||||
html.Append("<li>");
|
||||
html.Append(EncodeInline(item));
|
||||
html.AppendLine("</li>");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inList) { html.AppendLine("</ul>"); inList = false; }
|
||||
|
||||
if (line.EndsWith(":") || line.Contains(":\n"))
|
||||
{
|
||||
var trimmed = line.TrimEnd(':');
|
||||
if (trimmed.Length > 0)
|
||||
{
|
||||
html.Append("<p class=\"doc-label\">");
|
||||
html.Append(System.Web.HttpUtility.HtmlEncode(trimmed));
|
||||
html.AppendLine("</p>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
html.Append("<p>");
|
||||
html.Append(EncodeInline(line));
|
||||
html.AppendLine("</p>");
|
||||
}
|
||||
}
|
||||
|
||||
if (inList) html.AppendLine("</ul>");
|
||||
|
||||
return html.ToString();
|
||||
}
|
||||
|
||||
private string EncodeInline(string text)
|
||||
{
|
||||
var result = new System.Text.StringBuilder();
|
||||
var remaining = text;
|
||||
|
||||
while (remaining.Length > 0)
|
||||
{
|
||||
var boldIdx = remaining.IndexOf("**", StringComparison.Ordinal);
|
||||
if (boldIdx >= 0)
|
||||
{
|
||||
var endBold = remaining.IndexOf("**", boldIdx + 2, StringComparison.Ordinal);
|
||||
if (endBold >= 0)
|
||||
{
|
||||
result.Append(System.Web.HttpUtility.HtmlEncode(remaining[..boldIdx]));
|
||||
result.Append("<strong>");
|
||||
result.Append(System.Web.HttpUtility.HtmlEncode(remaining[(boldIdx + 2)..endBold]));
|
||||
result.Append("</strong>");
|
||||
remaining = remaining[(endBold + 2)..];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.Append(System.Web.HttpUtility.HtmlEncode(remaining));
|
||||
break;
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
"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())),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -171,119 +171,45 @@
|
||||
}
|
||||
|
||||
.doc-header h1 {
|
||||
margin: 0 0 0.75rem;
|
||||
margin: 0;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.doc-description {
|
||||
.doc-fields {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.doc-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.doc-field-key {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.doc-field-val {
|
||||
font-size: 0.95rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.doc-field-desc {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.6;
|
||||
color: var(--text-secondary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.doc-body {
|
||||
line-height: 1.7;
|
||||
font-size: 1rem;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.doc-body p {
|
||||
margin: 0 0 0.6rem;
|
||||
}
|
||||
|
||||
.doc-body p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.doc-label {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.doc-list-items {
|
||||
margin: 0 0 0.8rem;
|
||||
padding-left: 1.5rem;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.doc-list-items li {
|
||||
position: relative;
|
||||
padding: 0.2rem 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.doc-list-items li::before {
|
||||
content: "▸";
|
||||
position: absolute;
|
||||
left: -1.2rem;
|
||||
color: var(--accent);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.doc-extra {
|
||||
margin-top: 2rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.doc-extra h3 {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.75rem;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.doc-frontmatter {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 0.4rem 1rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: var(--bg-elevated);
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.fm-item {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.fm-key {
|
||||
color: var(--text-muted);
|
||||
font-weight: 500;
|
||||
font-size: 0.85rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.fm-value {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.doc-link-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
text-decoration-color: rgba(108, 99, 255, 0.3);
|
||||
transition: color var(--transition), text-decoration-color var(--transition);
|
||||
}
|
||||
|
||||
.doc-link-btn:hover {
|
||||
color: #7b73ff;
|
||||
text-decoration-color: #7b73ff;
|
||||
border-left: 3px solid var(--accent);
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
|
||||
Reference in New Issue
Block a user