< Summary

Information
Class: Chronicis.Client.Services.QuestApiService
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Services/QuestApiService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 62
Coverable lines: 62
Total lines: 120
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 6
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetArcQuestsAsync()100%210%
GetQuestAsync()100%210%
CreateQuestAsync()100%210%
UpdateQuestAsync()0%2040%
DeleteQuestAsync()100%210%
GetQuestUpdatesAsync()0%620%
AddQuestUpdateAsync()100%210%
DeleteQuestUpdateAsync()100%210%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Services/QuestApiService.cs

#LineLine coverage
 1using System.Net.Http.Json;
 2using Chronicis.Shared.DTOs.Quests;
 3using MudBlazor;
 4
 5namespace Chronicis.Client.Services;
 6
 7/// <summary>
 8/// Service for communicating with the Quest API.
 9/// Uses HttpClientExtensions for consistent error handling and logging.
 10/// Handles RowVersion concurrency for quest updates.
 11/// </summary>
 12public class QuestApiService : IQuestApiService
 13{
 14    private readonly HttpClient _http;
 15    private readonly ILogger<QuestApiService> _logger;
 16    private readonly ISnackbar _snackbar;
 17
 018    public QuestApiService(
 019        HttpClient http,
 020        ILogger<QuestApiService> logger,
 021        ISnackbar snackbar)
 22    {
 023        _http = http;
 024        _logger = logger;
 025        _snackbar = snackbar;
 026    }
 27
 28    public async Task<List<QuestDto>> GetArcQuestsAsync(Guid arcId)
 29    {
 030        return await _http.GetListAsync<QuestDto>(
 031            $"arcs/{arcId}/quests",
 032            _logger,
 033            $"quests for arc {arcId}");
 034    }
 35
 36    public async Task<QuestDto?> GetQuestAsync(Guid questId)
 37    {
 038        return await _http.GetEntityAsync<QuestDto>(
 039            $"quests/{questId}",
 040            _logger,
 041            $"quest {questId}");
 042    }
 43
 44    public async Task<QuestDto?> CreateQuestAsync(Guid arcId, QuestCreateDto createDto)
 45    {
 046        return await _http.PostEntityAsync<QuestDto>(
 047            $"arcs/{arcId}/quests",
 048            createDto,
 049            _logger,
 050            "create quest");
 051    }
 52
 53    public async Task<QuestDto?> UpdateQuestAsync(Guid questId, QuestEditDto editDto)
 54    {
 55        try
 56        {
 057            var response = await _http.PutAsJsonAsync($"quests/{questId}", editDto);
 58
 059            if (response.StatusCode == System.Net.HttpStatusCode.Conflict)
 60            {
 61                // 409 Conflict - rowversion mismatch
 062                _logger.LogWarning("Quest {QuestId} update conflict (stale RowVersion)", questId);
 63
 64                // Read the current server state from response body
 065                var currentQuest = await response.Content.ReadFromJsonAsync<QuestDto>();
 066                if (currentQuest != null)
 67                {
 068                    _snackbar.Add("Quest was modified by another user. Changes reloaded.", Severity.Warning);
 069                    return currentQuest;
 70                }
 71
 072                _snackbar.Add("Quest update conflict. Please reload.", Severity.Error);
 073                return null;
 74            }
 75
 076            response.EnsureSuccessStatusCode();
 077            return await response.Content.ReadFromJsonAsync<QuestDto>();
 78        }
 079        catch (Exception ex)
 80        {
 081            _logger.LogError(ex, "Failed to update quest {QuestId}", questId);
 082            _snackbar.Add("Failed to update quest", Severity.Error);
 083            return null;
 84        }
 085    }
 86
 87    public async Task<bool> DeleteQuestAsync(Guid questId)
 88    {
 089        return await _http.DeleteEntityAsync(
 090            $"quests/{questId}",
 091            _logger,
 092            $"quest {questId}");
 093    }
 94
 95    public async Task<PagedResult<QuestUpdateEntryDto>> GetQuestUpdatesAsync(Guid questId, int skip = 0, int take = 20)
 96    {
 097        return await _http.GetEntityAsync<PagedResult<QuestUpdateEntryDto>>(
 098            $"quests/{questId}/updates?skip={skip}&take={take}",
 099            _logger,
 0100            $"updates for quest {questId}")
 0101            ?? new PagedResult<QuestUpdateEntryDto>();
 0102    }
 103
 104    public async Task<QuestUpdateEntryDto?> AddQuestUpdateAsync(Guid questId, QuestUpdateCreateDto createDto)
 105    {
 0106        return await _http.PostEntityAsync<QuestUpdateEntryDto>(
 0107            $"quests/{questId}/updates",
 0108            createDto,
 0109            _logger,
 0110            "add quest update");
 0111    }
 112
 113    public async Task<bool> DeleteQuestUpdateAsync(Guid questId, Guid updateId)
 114    {
 0115        return await _http.DeleteEntityAsync(
 0116            $"quests/{questId}/updates/{updateId}",
 0117            _logger,
 0118            $"quest update {updateId}");
 0119    }
 120}