diff --git a/Chrono/Cloud/Components/Layout/MainLayout.razor b/Chrono/Cloud/Components/Layout/MainLayout.razor index 56f22af..7e6a004 100644 --- a/Chrono/Cloud/Components/Layout/MainLayout.razor +++ b/Chrono/Cloud/Components/Layout/MainLayout.razor @@ -1,4 +1,5 @@ @inherits LayoutComponentBase +@inject Shared.Services.CardPreviewService PreviewService
- - - + + + @code { private List pairings = []; diff --git a/Chrono/Shared/Pages/SyndicatePairings.razor.css b/Chrono/Shared/Pages/SyndicatePairings.razor.css new file mode 100644 index 0000000..92b6a9a --- /dev/null +++ b/Chrono/Shared/Pages/SyndicatePairings.razor.css @@ -0,0 +1,130 @@ +.syndicates-container { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; +} + +.syndicates-header { + margin-bottom: 2rem; + text-align: center; +} + +.pairings-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 1.5rem; +} + +.pairing-card { + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 1.5rem; + display: flex; + flex-direction: column; + align-items: center; + transition: transform var(--transition), box-shadow var(--transition); + cursor: pointer; +} + +.pairing-card:hover { + transform: translateY(-4px); + box-shadow: var(--shadow); + border-color: var(--accent); +} + +.pairing-display { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1rem; + width: 100%; + justify-content: center; +} + +.syndicate-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + flex: 1; +} + +.syn-icon { + width: 24px; + height: 24px; + border-radius: 50%; + background: currentColor; + box-shadow: 0 0 10px currentColor; +} + +.syn-name { + font-size: 0.9rem; + font-weight: 600; + color: var(--text-primary); +} + +.pairing-separator { + color: var(--text-muted); + font-size: 0.8rem; + opacity: 0.5; +} + +.pairing-info { + border-top: 1px solid var(--border); + padding-top: 0.75rem; + width: 100%; + text-align: center; +} + +.pairing-label { + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-muted); +} + +.syn-icon { + width: 24px; + height: 24px; + border-radius: 50%; + background: currentColor; + box-shadow: 0 0 10px currentColor; + display: inline-block; /* Ensure visibility */ +} + +/* Syndicate Colors */ +.singularity { + color: #ffffff; +} + +.phasetide { + color: #2196f3; +} + +.silence { + color: #9c27b0; +} + +.lifeblood { + color: #4caf50; +} + +.sungrace { + color: #ff9800; +} + +.splintergleam { + color: #f44336; +} + +@media (max-width: 600px) { + .pairings-grid { + grid-template-columns: 1fr; + } + + .syndicates-container { + padding: 1rem; + } +} diff --git a/Chrono/Standalone/Components/Syndicates.razor b/Chrono/Shared/Pages/Syndicates.razor similarity index 87% rename from Chrono/Standalone/Components/Syndicates.razor rename to Chrono/Shared/Pages/Syndicates.razor index e79e9b2..ed08ef8 100644 --- a/Chrono/Standalone/Components/Syndicates.razor +++ b/Chrono/Shared/Pages/Syndicates.razor @@ -1,5 +1,5 @@ -@page "/syndicates" -@using Chrono.Components +@page "/syndicates" +@namespace Shared.Pages @@ -30,9 +30,9 @@ - - - + + + @code { private List syndicates = []; diff --git a/Chrono/Standalone/Components/Syndicates.razor.css b/Chrono/Shared/Pages/Syndicates.razor.css similarity index 100% rename from Chrono/Standalone/Components/Syndicates.razor.css rename to Chrono/Shared/Pages/Syndicates.razor.css diff --git a/Chrono/Shared/Services/CardPreviewService.cs b/Chrono/Shared/Services/CardPreviewService.cs index 522a55b..10fc1f1 100644 --- a/Chrono/Shared/Services/CardPreviewService.cs +++ b/Chrono/Shared/Services/CardPreviewService.cs @@ -5,6 +5,7 @@ namespace Shared.Services; public class CardPreviewService { public CardData? HoveredCard { get; private set; } + public DocData? SelectedDoc { get; private set; } public double X { get; private set; } public double Y { get; private set; } public bool IsVisible { get; private set; } @@ -26,6 +27,12 @@ public class CardPreviewService NotifyStateChanged(); } + public void SelectDoc(DocData? doc) + { + SelectedDoc = doc; + NotifyStateChanged(); + } + private void NotifyStateChanged() { OnChange?.Invoke(); diff --git a/Chrono/Shared/Services/CardRenderingService.cs b/Chrono/Shared/Services/CardRenderingService.cs index 0a4c7e5..91d0adb 100644 --- a/Chrono/Shared/Services/CardRenderingService.cs +++ b/Chrono/Shared/Services/CardRenderingService.cs @@ -7,8 +7,9 @@ namespace Shared.Services; public class CardRenderingService { private readonly Dictionary _cardLookup; - private readonly List _cardNames; - private readonly Regex _nameRegex; + private readonly Dictionary _docLookup; + private readonly List _allTerms; + private readonly Regex _termRegex; public CardRenderingService() { @@ -20,16 +21,25 @@ public class CardRenderingService .GroupBy(c => c.Name, StringComparer.OrdinalIgnoreCase) .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); - _cardNames = allCards - .Select(c => c.Name) + var allDocs = DocDatabase.Docs + .Where(d => !string.IsNullOrWhiteSpace(d.Title)) + .ToList(); + + _docLookup = allDocs + .GroupBy(d => d.Title, StringComparer.OrdinalIgnoreCase) + .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); + + _allTerms = _cardLookup.Keys + .Concat(_docLookup.Keys) + .Distinct(StringComparer.OrdinalIgnoreCase) .OrderByDescending(n => n.Length) .ToList(); - var pattern = string.Join("|", _cardNames.Select(n => $@"\b{Regex.Escape(n)}\b")); - _nameRegex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); + var pattern = string.Join("|", _allTerms.Select(n => $@"\b{Regex.Escape(n)}\b")); + _termRegex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); } - public RenderFragment RenderDescription(string description, Action onCardClick) + public RenderFragment RenderDescription(string description, Action onCardClick, Action? onDocClick = null, CardPreviewService? previewService = null) { return builder => { @@ -40,7 +50,7 @@ public class CardRenderingService { builder.OpenElement(sequence++, "p"); - var matches = _nameRegex.Matches(paragraph); + var matches = _termRegex.Matches(paragraph); var lastIndex = 0; foreach (Match match in matches) @@ -48,14 +58,33 @@ public class CardRenderingService if (match.Index > lastIndex) builder.AddContent(sequence++, paragraph.Substring(lastIndex, match.Index - lastIndex)); - var cardName = match.Value; - var card = LookupCard(cardName); + var term = match.Value; + var card = LookupCard(term); + var doc = LookupDoc(term); builder.OpenElement(sequence++, "button"); builder.AddAttribute(sequence++, "class", "inline-card-btn"); - builder.AddAttribute(sequence++, "onclick", - EventCallback.Factory.Create(this, () => onCardClick(card))); - builder.AddContent(sequence++, cardName); + + if (card != null) + { + builder.AddAttribute(sequence++, "onclick", + EventCallback.Factory.Create(this, () => onCardClick(card))); + + if (previewService != null) + { + builder.AddAttribute(sequence++, "onmouseenter", + EventCallback.Factory.Create(this, e => previewService.Show(card, e.ClientX, e.ClientY))); + builder.AddAttribute(sequence++, "onmouseleave", + EventCallback.Factory.Create(this, () => previewService.Hide())); + } + } + else if (doc != null && onDocClick != null) + { + builder.AddAttribute(sequence++, "onclick", + EventCallback.Factory.Create(this, () => onDocClick(doc))); + } + + builder.AddContent(sequence++, term); builder.CloseElement(); lastIndex = match.Index + match.Length; @@ -68,8 +97,13 @@ public class CardRenderingService }; } - private CardData? LookupCard(string cardName) + private CardData? LookupCard(string name) { - return _cardLookup.GetValueOrDefault(cardName); + return _cardLookup.GetValueOrDefault(name); + } + + private DocData? LookupDoc(string name) + { + return _docLookup.GetValueOrDefault(name); } } \ No newline at end of file diff --git a/Chrono/Standalone/Components/Layout/MainLayout.razor b/Chrono/Standalone/Components/Layout/MainLayout.razor index 56f22af..7e6a004 100644 --- a/Chrono/Standalone/Components/Layout/MainLayout.razor +++ b/Chrono/Standalone/Components/Layout/MainLayout.razor @@ -1,4 +1,5 @@ @inherits LayoutComponentBase +@inject Shared.Services.CardPreviewService PreviewService