< Summary

Information
Class: Chronicis.Client.Components.Shared.QuickAddSession
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Shared/QuickAddSession.razor
Line coverage
0%
Covered lines: 0
Uncovered lines: 66
Coverable lines: 66
Total lines: 157
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 36
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
BuildRenderTree(...)0%2040%
.ctor()100%210%
OnInitialized()100%210%
OnTreeStateChanged()100%210%
CheckActiveContextAsync()0%156120%
CreateSessionNote()0%342180%
Dispose()100%210%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Shared/QuickAddSession.razor

#LineLine coverage
 1@using Chronicis.Shared.DTOs
 2@using Chronicis.Shared.Enums
 3@inject ICampaignApiService CampaignApi
 4@inject IArticleApiService ArticleApi
 5@inject ITreeStateService TreeState
 6@inject ISnackbar Snackbar
 7@inject NavigationManager Navigation
 8
 09@if (_showButton)
 10{
 11    <div class="quick-add-session-container">
 12        <MudButton Variant="Variant.Filled"
 13                   Color="Color.Primary"
 14                   FullWidth="true"
 15                   OnClick="CreateSessionNote"
 16                   Disabled="_isCreating"
 17                   Class="quick-add-session-btn">
 018            @if (_isCreating)
 19            {
 20                <MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
 21                <span>Creating...</span>
 22            }
 23            else
 24            {
 25                <span>New Session Note</span>
 26            }
 27        </MudButton>
 028        @if (!string.IsNullOrEmpty(_contextLabel))
 29        {
 30            <MudText Typo="Typo.caption" Class="quick-add-context-label">
 031                @_contextLabel
 32            </MudText>
 33        }
 34    </div>
 35}
 36
 37@code {
 38    private bool _showButton = false;
 39    private bool _isCreating = false;
 040    private string _contextLabel = string.Empty;
 41    private ActiveContextDto? _activeContext;
 42    private Guid? _worldId;
 43
 44    protected override void OnInitialized()
 45    {
 046        TreeState.OnStateChanged += OnTreeStateChanged;
 047    }
 48
 49    private async void OnTreeStateChanged()
 50    {
 051        await CheckActiveContextAsync();
 052        await InvokeAsync(StateHasChanged);
 053    }
 54
 55    private async Task CheckActiveContextAsync()
 56    {
 057        _showButton = false;
 058        _contextLabel = string.Empty;
 059        _activeContext = null;
 060        _worldId = null;
 61
 62        // Get all world nodes from tree state
 063        var worldNodes = TreeState.RootNodes.Where(n => n.NodeType == TreeNodeType.World).ToList();
 064        if (!worldNodes.Any()) return;
 65
 66        try
 67        {
 68            // Check each world for an active context
 069            foreach (var worldNode in worldNodes)
 70            {
 071                var context = await CampaignApi.GetActiveContextAsync(worldNode.Id);
 72
 073                if (context != null && context.HasActiveContext)
 74                {
 075                    _activeContext = context;
 076                    _worldId = worldNode.Id;
 077                    _showButton = true;
 78
 79                    // Build context label
 080                    var parts = new List<string>();
 081                    if (!string.IsNullOrEmpty(_activeContext.CampaignName))
 082                        parts.Add(_activeContext.CampaignName);
 083                    if (!string.IsNullOrEmpty(_activeContext.ArcName))
 084                        parts.Add(_activeContext.ArcName);
 85
 086                    _contextLabel = string.Join(" › ", parts);
 087                    break; // Found an active context, stop searching
 88                }
 089            }
 090        }
 091        catch (Exception)
 92        {
 93            // Silently fail - button just won't show
 094        }
 095    }
 96
 97    private async Task CreateSessionNote()
 98    {
 099        if (_activeContext?.ArcId == null || _activeContext?.CampaignId == null || _worldId == null || _isCreating)
 0100            return;
 101
 0102        _isCreating = true;
 0103        StateHasChanged();
 104
 105        try
 106        {
 107            // Generate session name as YYYY-MM-DD
 0108            var sessionName = DateTime.Now.ToString("yyyy-MM-dd");
 109
 0110            var createDto = new ArticleCreateDto
 0111            {
 0112                Title = sessionName,
 0113                WorldId = _worldId,
 0114                CampaignId = _activeContext.CampaignId,
 0115                ArcId = _activeContext.ArcId,
 0116                Type = ArticleType.Session
 0117            };
 118
 0119            var newArticle = await ArticleApi.CreateArticleAsync(createDto);
 120
 0121            if (newArticle != null)
 122            {
 123                // Refresh tree to show new session
 0124                await TreeState.RefreshAsync();
 0125                TreeState.ExpandPathToAndSelect(newArticle.Id);
 126
 127                // Fetch the full article to get breadcrumbs for navigation
 0128                var articleDetail = await ArticleApi.GetArticleDetailAsync(newArticle.Id);
 0129                if (articleDetail != null && articleDetail.Breadcrumbs.Any())
 130                {
 0131                    var path = string.Join("/", articleDetail.Breadcrumbs.Select(b => b.Slug));
 0132                    Navigation.NavigateTo($"/article/{path}");
 133                }
 134
 0135                Snackbar.Add($"Session '{sessionName}' created", Severity.Success);
 136            }
 137            else
 138            {
 0139                Snackbar.Add("Failed to create session", Severity.Error);
 140            }
 0141        }
 0142        catch (Exception ex)
 143        {
 0144            Snackbar.Add($"Error: {ex.Message}", Severity.Error);
 0145        }
 146        finally
 147        {
 0148            _isCreating = false;
 0149            StateHasChanged();
 150        }
 0151    }
 152
 153    public void Dispose()
 154    {
 0155        TreeState.OnStateChanged -= OnTreeStateChanged;
 0156    }
 157}