diff --git a/README.md b/README.md
index c782a76..00f462f 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,7 @@ Gameplay capabilities now include:
- Character edit flow supports unlinking from campaigns (owner/GM/admin) and assigning to any existing campaign via expanded campaign options
- Campaign management supports character deletion by character owner or admin
- Shared top header control across workspace and admin views (consistent navigation/logout behavior)
+- Admin menu navigation now directly targets `Play` or `Campaign Management` workspace screens
## Prerequisites
diff --git a/RpgRoller/Components/Pages/Home.razor b/RpgRoller/Components/Pages/Home.razor
index 8366693..c653c61 100644
--- a/RpgRoller/Components/Pages/Home.razor
+++ b/RpgRoller/Components/Pages/Home.razor
@@ -22,10 +22,10 @@
break;
case HomeViewMode.Workspace:
-
+
break;
case HomeViewMode.Admin:
-
+
break;
}
diff --git a/RpgRoller/Components/Pages/Home.razor.cs b/RpgRoller/Components/Pages/Home.razor.cs
index e7cf0f5..52aeace 100644
--- a/RpgRoller/Components/Pages/Home.razor.cs
+++ b/RpgRoller/Components/Pages/Home.razor.cs
@@ -22,50 +22,60 @@ public partial class Home
try
{
_ = await ApiClient.RequestAsync("GET", "/api/me");
+ WorkspaceScreenOverride = null;
CurrentView = HomeViewMode.Workspace;
ClearStatus();
}
catch (ApiRequestException ex) when (ex.StatusCode == 401)
{
+ WorkspaceScreenOverride = null;
CurrentView = HomeViewMode.Anonymous;
ClearStatus();
}
catch (ApiRequestException ex)
{
+ WorkspaceScreenOverride = null;
CurrentView = HomeViewMode.Anonymous;
SetStatus(ex.Message, true);
}
}
- private void OnLoggedInAsync()
+ private Task OnLoggedInAsync()
{
+ WorkspaceScreenOverride = null;
CurrentView = HomeViewMode.Workspace;
ClearStatus();
+ return InvokeAsync(StateHasChanged);
}
- private void OnAdminRequested()
+ private Task OnAdminRequestedAsync()
{
CurrentView = HomeViewMode.Admin;
ClearStatus();
+ return InvokeAsync(StateHasChanged);
}
- private void OnWorkspaceRequested()
+ private Task OnWorkspaceRequestedAsync(string screen)
{
+ WorkspaceScreenOverride = NormalizeWorkspaceScreen(screen) ?? "play";
CurrentView = HomeViewMode.Workspace;
ClearStatus();
+ return InvokeAsync(StateHasChanged);
}
- private void OnLoggedOutAsync(string? message)
+ private Task OnLoggedOutAsync(string? message)
{
+ WorkspaceScreenOverride = null;
CurrentView = HomeViewMode.Anonymous;
if (string.IsNullOrWhiteSpace(message))
{
ClearStatus();
- return;
+ return InvokeAsync(StateHasChanged);
}
var isError = message.Contains("expired", StringComparison.OrdinalIgnoreCase);
SetStatus(message, isError);
+ return InvokeAsync(StateHasChanged);
}
private void SetStatus(string message, bool isError)
@@ -80,7 +90,19 @@ public partial class Home
StatusIsError = false;
}
+ private static string? NormalizeWorkspaceScreen(string? screen)
+ {
+ if (string.Equals(screen, "management", StringComparison.OrdinalIgnoreCase))
+ return "management";
+
+ if (string.Equals(screen, "play", StringComparison.OrdinalIgnoreCase))
+ return "play";
+
+ return null;
+ }
+
private HomeViewMode CurrentView { get; set; } = HomeViewMode.Loading;
+ private string? WorkspaceScreenOverride { get; set; }
private string? StatusMessage { get; set; }
private bool StatusIsError { get; set; }
private bool HasInitialized { get; set; }
diff --git a/RpgRoller/Components/Pages/HomeControls/AdminHome.razor.cs b/RpgRoller/Components/Pages/HomeControls/AdminHome.razor.cs
index d015df4..94f61fc 100644
--- a/RpgRoller/Components/Pages/HomeControls/AdminHome.razor.cs
+++ b/RpgRoller/Components/Pages/HomeControls/AdminHome.razor.cs
@@ -46,18 +46,14 @@ public partial class AdminHome
}
}
- private async Task OpenPlayAsync()
+ private Task OpenPlayAsync()
{
- IsScreenMenuOpen = false;
- await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", ScreenSessionKey, "play");
- await WorkspaceRequested.InvokeAsync();
+ return OpenWorkspaceAsync("play");
}
- private async Task OpenCampaignManagementAsync()
+ private Task OpenCampaignManagementAsync()
{
- IsScreenMenuOpen = false;
- await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", ScreenSessionKey, "management");
- await WorkspaceRequested.InvokeAsync();
+ return OpenWorkspaceAsync("management");
}
private Task OpenAdminAsync()
@@ -168,6 +164,12 @@ public partial class AdminHome
IsScreenMenuOpen = !IsScreenMenuOpen;
}
+ private async Task OpenWorkspaceAsync(string screen)
+ {
+ IsScreenMenuOpen = false;
+ await WorkspaceRequested.InvokeAsync(screen);
+ }
+
[Inject]
private RpgRollerApiClient ApiClient { get; set; } = null!;
@@ -195,11 +197,9 @@ public partial class AdminHome
}
}
- private const string ScreenSessionKey = "screen";
-
[Parameter]
public EventCallback LoggedOut { get; set; }
[Parameter]
- public EventCallback WorkspaceRequested { get; set; }
+ public EventCallback WorkspaceRequested { get; set; }
}
diff --git a/RpgRoller/Components/Pages/Workspace.razor.cs b/RpgRoller/Components/Pages/Workspace.razor.cs
index f05fec4..1478879 100644
--- a/RpgRoller/Components/Pages/Workspace.razor.cs
+++ b/RpgRoller/Components/Pages/Workspace.razor.cs
@@ -22,9 +22,18 @@ public partial class Workspace : IAsyncDisposable
private async Task InitializeAsync()
{
- var storedScreen = await JS.InvokeAsync("rpgRollerApi.getSessionValue", ScreenSessionKey);
- if (string.Equals(storedScreen, "management", StringComparison.OrdinalIgnoreCase))
- CurrentScreen = "management";
+ var requestedScreen = NormalizeRequestedScreen(RequestedScreen);
+ if (requestedScreen is not null)
+ {
+ CurrentScreen = requestedScreen;
+ await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", ScreenSessionKey, CurrentScreen);
+ }
+ else
+ {
+ var storedScreen = await JS.InvokeAsync("rpgRollerApi.getSessionValue", ScreenSessionKey);
+ if (string.Equals(storedScreen, "management", StringComparison.OrdinalIgnoreCase))
+ CurrentScreen = "management";
+ }
var storedPanel = await JS.InvokeAsync("rpgRollerApi.getSessionValue", MobilePanelSessionKey);
if (string.Equals(storedPanel, "log", StringComparison.OrdinalIgnoreCase))
@@ -225,7 +234,7 @@ public partial class Workspace : IAsyncDisposable
private async Task SwitchScreenAsync(string screen)
{
- CurrentScreen = string.Equals(screen, "management", StringComparison.OrdinalIgnoreCase) ? "management" : "play";
+ CurrentScreen = NormalizeRequestedScreen(screen) ?? "play";
IsScreenMenuOpen = false;
await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", ScreenSessionKey, CurrentScreen);
}
@@ -522,6 +531,17 @@ public partial class Workspace : IAsyncDisposable
return string.Equals(visibility, "private", StringComparison.OrdinalIgnoreCase) ? "private" : "public";
}
+ private static string? NormalizeRequestedScreen(string? screen)
+ {
+ if (string.Equals(screen, "management", StringComparison.OrdinalIgnoreCase))
+ return "management";
+
+ if (string.Equals(screen, "play", StringComparison.OrdinalIgnoreCase))
+ return "play";
+
+ return null;
+ }
+
private bool CanEditSkill(SkillSummary skill)
{
if (SelectedCampaign is null)
@@ -822,6 +842,9 @@ public partial class Workspace : IAsyncDisposable
[Parameter]
public EventCallback AdminRequested { get; set; }
+ [Parameter]
+ public string? RequestedScreen { get; set; }
+
private string? SelectedCampaignName => SelectedCampaign?.Name;
private CharacterSummary? SelectedCharacter =>