178 lines
5.9 KiB
C#
178 lines
5.9 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.JSInterop;
|
|
using RpgRoller.Contracts;
|
|
|
|
namespace RpgRoller.Components.Pages;
|
|
|
|
[ExcludeFromCodeCoverage]
|
|
public sealed class WorkspaceCampaignCoordinator(
|
|
WorkspaceState state,
|
|
WorkspaceFeedbackService feedback,
|
|
IJSRuntime js,
|
|
RpgRollerApiClient apiClient,
|
|
Func<Task> loadKnownUsernamesAsync,
|
|
Func<Guid?, Task> reloadCampaignsAsync,
|
|
Func<Task> reloadCharacterCampaignOptionsAsync,
|
|
Func<Task> refreshCampaignScopeAsync,
|
|
Func<Task> syncStateEventsAsync,
|
|
Func<Task> requestRefreshAsync)
|
|
{
|
|
public async Task OnCampaignSelectionChangedAsync(ChangeEventArgs args)
|
|
{
|
|
if (!Guid.TryParse(args.Value?.ToString(), out var campaignId))
|
|
return;
|
|
|
|
state.SelectedCampaignId = campaignId;
|
|
await js.InvokeVoidAsync("rpgRollerApi.setSessionValue", CampaignSessionKey, campaignId.ToString());
|
|
await refreshCampaignScopeAsync();
|
|
await syncStateEventsAsync();
|
|
state.IsScreenMenuOpen = false;
|
|
}
|
|
|
|
public async Task OnCampaignCreatedAsync(Guid campaignId)
|
|
{
|
|
await reloadCampaignsAsync(campaignId);
|
|
await reloadCharacterCampaignOptionsAsync();
|
|
await refreshCampaignScopeAsync();
|
|
await syncStateEventsAsync();
|
|
feedback.SetStatus("Campaign created.", false);
|
|
await requestRefreshAsync();
|
|
}
|
|
|
|
public void OpenCreateCharacterModal()
|
|
{
|
|
state.CreateCharacterInitialModel = new()
|
|
{
|
|
Name = string.Empty,
|
|
CampaignId = state.SelectedCampaignId?.ToString() ??
|
|
state.CharacterCampaignOptions.FirstOrDefault()?.Id.ToString() ?? string.Empty,
|
|
OwnerUsername = string.Empty
|
|
};
|
|
|
|
state.CreateCharacterFormVersion += 1;
|
|
state.CanEditCharacterOwner = false;
|
|
state.ShowCreateCharacterModal = true;
|
|
}
|
|
|
|
public async Task OpenEditCharacterModal(CharacterSummary character)
|
|
{
|
|
if (state.IsCurrentUserGm || state.IsCurrentUserAdmin)
|
|
await loadKnownUsernamesAsync();
|
|
|
|
state.EditingCharacterId = character.Id;
|
|
state.EditCharacterInitialModel = new()
|
|
{
|
|
Name = character.Name,
|
|
CampaignId = character.CampaignId?.ToString() ?? string.Empty,
|
|
OwnerUsername = string.Empty
|
|
};
|
|
|
|
state.EditCharacterFormVersion += 1;
|
|
state.CanEditCharacterOwner = state.IsCurrentUserGm || state.IsCurrentUserAdmin;
|
|
state.ShowEditCharacterModal = true;
|
|
}
|
|
|
|
public void CloseCharacterModals()
|
|
{
|
|
state.ShowCreateCharacterModal = false;
|
|
state.ShowEditCharacterModal = false;
|
|
state.CanEditCharacterOwner = false;
|
|
state.EditingCharacterId = null;
|
|
}
|
|
|
|
public async Task OnCharacterCreatedAsync(Guid? campaignId)
|
|
{
|
|
CloseCharacterModals();
|
|
await reloadCampaignsAsync(campaignId);
|
|
await reloadCharacterCampaignOptionsAsync();
|
|
await refreshCampaignScopeAsync();
|
|
await syncStateEventsAsync();
|
|
feedback.SetStatus("Character created.", false);
|
|
await requestRefreshAsync();
|
|
}
|
|
|
|
public async Task OnCharacterUpdatedAsync(Guid? campaignId)
|
|
{
|
|
CloseCharacterModals();
|
|
await reloadCampaignsAsync(campaignId);
|
|
await reloadCharacterCampaignOptionsAsync();
|
|
await refreshCampaignScopeAsync();
|
|
await syncStateEventsAsync();
|
|
feedback.SetStatus(campaignId.HasValue ? "Character updated." : "Character unlinked from campaign.", false);
|
|
await requestRefreshAsync();
|
|
}
|
|
|
|
public async Task DeleteSelectedCampaignAsync()
|
|
{
|
|
if (state.SelectedCampaign is null || state.IsMutating || !state.CanDeleteSelectedCampaign)
|
|
return;
|
|
|
|
var confirmed = await js.InvokeAsync<bool>("confirm", $"Delete campaign '{state.SelectedCampaign.Name}'?");
|
|
if (!confirmed)
|
|
return;
|
|
|
|
state.IsMutating = true;
|
|
try
|
|
{
|
|
_ = await apiClient.RequestAsync<bool>("DELETE", $"/api/campaigns/{state.SelectedCampaign.Id}");
|
|
await reloadCampaignsAsync(null);
|
|
await reloadCharacterCampaignOptionsAsync();
|
|
await refreshCampaignScopeAsync();
|
|
await syncStateEventsAsync();
|
|
feedback.SetStatus("Campaign deleted.", false);
|
|
}
|
|
catch (ApiRequestException ex)
|
|
{
|
|
feedback.SetStatus(ex.Message, true);
|
|
}
|
|
finally
|
|
{
|
|
state.IsMutating = false;
|
|
await requestRefreshAsync();
|
|
}
|
|
}
|
|
|
|
public async Task DeleteCharacterAsync(CharacterSummary character)
|
|
{
|
|
if (state.IsMutating || !CanDeleteCharacter(character))
|
|
return;
|
|
|
|
var confirmed = await js.InvokeAsync<bool>("confirm", $"Delete character '{character.Name}'?");
|
|
if (!confirmed)
|
|
return;
|
|
|
|
state.IsMutating = true;
|
|
try
|
|
{
|
|
_ = await apiClient.RequestAsync<bool>("DELETE", $"/api/characters/{character.Id}");
|
|
await reloadCampaignsAsync(state.SelectedCampaignId);
|
|
await reloadCharacterCampaignOptionsAsync();
|
|
await refreshCampaignScopeAsync();
|
|
await syncStateEventsAsync();
|
|
feedback.SetStatus("Character deleted.", false);
|
|
}
|
|
catch (ApiRequestException ex)
|
|
{
|
|
feedback.SetStatus(ex.Message, true);
|
|
}
|
|
finally
|
|
{
|
|
state.IsMutating = false;
|
|
await requestRefreshAsync();
|
|
}
|
|
}
|
|
|
|
public bool CanEditCharacter(CharacterSummary character)
|
|
{
|
|
return state.User is not null &&
|
|
(character.OwnerUserId == state.User.Id || state.IsCurrentUserGm || state.IsCurrentUserAdmin);
|
|
}
|
|
|
|
public bool CanDeleteCharacter(CharacterSummary character)
|
|
{
|
|
return state.User is not null && (character.OwnerUserId == state.User.Id || state.IsCurrentUserAdmin);
|
|
}
|
|
|
|
private const string CampaignSessionKey = "campaign";
|
|
} |