| | | 1 | | @using Chronicis.Shared.DTOs |
| | | 2 | | |
| | | 3 | | @* Refactored OutgoingLinksPanel - Now accepts data as parameters instead of fetching directly *@ |
| | | 4 | | |
| | | 5 | | <div class="links-panel"> |
| | | 6 | | <div class="links-panel-header"> |
| | | 7 | | <span class="links-panel-title">Links To</span> |
| | 9 | 8 | | @if (IsLoading) |
| | | 9 | | { |
| | | 10 | | <span class="links-panel-loading">...</span> |
| | | 11 | | } |
| | 9 | 12 | | <span class="links-panel-count">@OutgoingLinks.Count</span> |
| | | 13 | | </div> |
| | | 14 | | |
| | 9 | 15 | | @if (OutgoingLinks.Any()) |
| | | 16 | | { |
| | | 17 | | <div class="links-chip-container"> |
| | 30 | 18 | | @foreach (var link in OutgoingLinks) |
| | | 19 | | { |
| | | 20 | | <span class="link-chip" |
| | 1 | 21 | | @onclick="() => OnNavigateToArticle.InvokeAsync(link.ArticleId)" |
| | | 22 | | title="@link.DisplayPath"> |
| | 9 | 23 | | @link.Title |
| | | 24 | | </span> |
| | | 25 | | } |
| | | 26 | | </div> |
| | | 27 | | } |
| | 3 | 28 | | else if (!IsLoading) |
| | | 29 | | { |
| | | 30 | | <div class="links-panel-empty">No outgoing links</div> |
| | | 31 | | } |
| | | 32 | | </div> |
| | | 33 | | |
| | | 34 | | @code { |
| | | 35 | | /// <summary> |
| | | 36 | | /// The list of outgoing links to display. |
| | | 37 | | /// Parent component is responsible for loading this data. |
| | | 38 | | /// </summary> |
| | | 39 | | [Parameter, EditorRequired] |
| | 40 | 40 | | public List<BacklinkDto> OutgoingLinks { get; set; } = new(); |
| | | 41 | | |
| | | 42 | | /// <summary> |
| | | 43 | | /// Whether data is currently being loaded. |
| | | 44 | | /// Controls the loading indicator display. |
| | | 45 | | /// </summary> |
| | | 46 | | [Parameter] |
| | 14 | 47 | | public bool IsLoading { get; set; } |
| | | 48 | | |
| | | 49 | | /// <summary> |
| | | 50 | | /// Callback when user clicks an outgoing link. |
| | | 51 | | /// Parent handles the navigation logic. |
| | | 52 | | /// </summary> |
| | | 53 | | [Parameter] |
| | 2 | 54 | | public EventCallback<Guid> OnNavigateToArticle { get; set; } |
| | | 55 | | } |
| | | 56 | | |
| | | 57 | | <style> |
| | | 58 | | .links-panel { |
| | | 59 | | padding: 12px 16px; |
| | | 60 | | } |
| | | 61 | | |
| | | 62 | | .links-panel-header { |
| | | 63 | | display: flex; |
| | | 64 | | align-items: center; |
| | | 65 | | gap: 8px; |
| | | 66 | | margin-bottom: 10px; |
| | | 67 | | } |
| | | 68 | | |
| | | 69 | | .links-panel-title { |
| | | 70 | | font-size: 13px; |
| | | 71 | | font-weight: 600; |
| | | 72 | | color: var(--mud-palette-text-secondary); |
| | | 73 | | text-transform: uppercase; |
| | | 74 | | letter-spacing: 0.5px; |
| | | 75 | | } |
| | | 76 | | |
| | | 77 | | .links-panel-loading { |
| | | 78 | | font-size: 12px; |
| | | 79 | | color: #C4AF8E; |
| | | 80 | | } |
| | | 81 | | |
| | | 82 | | .links-panel-count { |
| | | 83 | | font-size: 11px; |
| | | 84 | | background: rgba(196, 175, 142, 0.2); |
| | | 85 | | color: var(--mud-palette-text-secondary); |
| | | 86 | | padding: 2px 6px; |
| | | 87 | | border-radius: 10px; |
| | | 88 | | margin-left: auto; |
| | | 89 | | } |
| | | 90 | | |
| | | 91 | | .links-chip-container { |
| | | 92 | | display: flex; |
| | | 93 | | flex-wrap: wrap; |
| | | 94 | | gap: 6px; |
| | | 95 | | } |
| | | 96 | | |
| | | 97 | | .link-chip { |
| | | 98 | | display: inline-block; |
| | | 99 | | padding: 4px 10px; |
| | | 100 | | font-size: 12px; |
| | | 101 | | background: rgba(196, 175, 142, 0.1); |
| | | 102 | | border: 1px solid rgba(196, 175, 142, 0.25); |
| | | 103 | | border-radius: 12px; |
| | | 104 | | color: var(--mud-palette-text-primary); |
| | | 105 | | cursor: pointer; |
| | | 106 | | transition: all 0.15s ease; |
| | | 107 | | max-width: 150px; |
| | | 108 | | overflow: hidden; |
| | | 109 | | text-overflow: ellipsis; |
| | | 110 | | white-space: nowrap; |
| | | 111 | | } |
| | | 112 | | |
| | | 113 | | .link-chip:hover { |
| | | 114 | | background: rgba(196, 175, 142, 0.25); |
| | | 115 | | border-color: rgba(196, 175, 142, 0.5); |
| | | 116 | | color: #C4AF8E; |
| | | 117 | | } |
| | | 118 | | |
| | | 119 | | .links-panel-empty { |
| | | 120 | | font-size: 12px; |
| | | 121 | | color: var(--mud-palette-text-secondary); |
| | | 122 | | opacity: 0.6; |
| | | 123 | | font-style: italic; |
| | | 124 | | } |
| | | 125 | | </style> |