Skip to content

feat: Player Character UI (Character Management) (spec #24) #25

@Fortinbra

Description

@Fortinbra

Feature Spec: Player Character UI (Character Management)

Field Value
Feature Player Character UI (Character Management)
Issue #TBD
Status Draft
Author The Doctor
Date 2026-04-10

Overview

What it does

Adds a Blazor WASM interface for viewing and managing player character sheets. The DM can view all characters in a campaign and apply inline overrides (HP, AC, conditions). Players, once auth is wired, can view their own character sheets.

Why it's needed

Character state must be visible outside Discord to support DM oversight and player self-service. This UI provides a canonical view of character stats, equipment, spells, and proficiencies, aligned with the domain model in spec #9.

Out of scope


Architecture Notes (The Doctor)

Projects / layers touched

  • DungeonMaster.Web — character pages + components
  • DungeonMaster.Api — character query + override endpoints
  • DungeonMaster.Core — query services and DTOs
  • DungeonMaster.Shared — character sheet DTOs

New interfaces in DungeonMaster.Core

  • IPlayerCharacterQueryService — read-only character sheets + campaign list
  • IPlayerCharacterOverrideService — DM override operations

Integration points with existing systems


Domain Model

Records

public sealed record PlayerCharacterSummary(Guid Id, string Name, string ClassName, string RaceName, int Level);

public sealed record PlayerCharacterDetail(
    Guid Id,
    string Name,
    string ClassName,
    string RaceName,
    int Level,
    int CurrentHitPoints,
    int MaxHitPoints,
    int ArmorClass,
    AbilityScores AbilityScores,
    IReadOnlyList<string> Proficiencies,
    IReadOnlyList<string> Spells,
    Guid? ImageId);

API Contract (Rory)

Endpoints

  • GET /api/campaigns/{id}/characters — DM-only list of characters
  • GET /api/characters/{id} — DM + owning player
  • PUT /api/characters/{id}/overrides — DM-only inline overrides (HP/AC/conditions)

UI Specification (Clara)

Page / component breakdown

  • CampaignCharacterList (/campaigns/{id}/characters) — DM view for all PCs
  • CharacterDetail (/characters/{id}) — detailed sheet view

Blazor component list

Component File Purpose
CampaignCharacterList Pages/Characters/CampaignCharacterList.razor / .razor.cs List all characters in a campaign
CharacterDetail Pages/Characters/CharacterDetail.razor / .razor.cs Full character sheet view
CharacterPortraitCard Components/Characters/CharacterPortraitCard.razor / .razor.cs Displays portrait image from spec #17
AbilityScoreGrid Components/Characters/AbilityScoreGrid.razor / .razor.cs STR/DEX/CON/INT/WIS/CHA grid
EquipmentPanel Components/Characters/EquipmentPanel.razor / .razor.cs Shows equipped items and backpack (spec #27)
SpellListPanel Components/Characters/SpellListPanel.razor / .razor.cs Known/prepared spells
OverrideModal Components/Characters/OverrideModal.razor / .razor.cs DM-only inline overrides

Theme / styling requirements

  • Use var(--color-surface) for card backgrounds
  • Use var(--spacing-md) for layout spacing
  • Use var(--font-size-lg) for character name heading

User interaction flow

  1. DM opens CampaignCharacterList → selects a character
  2. CharacterDetail loads full sheet with portrait
  3. DM clicks "Override" → modal edits HP/AC/conditions → saves
  4. Changes persist and update the UI

Test Scenarios (Danny) ⚠️ COMPLETE BEFORE IMPLEMENTATION

Happy path

  1. Given a campaign with two characters
    When the DM opens the character list
    Then both characters display with name, class, and level

  2. Given a DM updates HP via OverrideModal
    When the API returns success
    Then the UI reflects the new HP value

Edge cases

  1. Given a character has no portrait
    When CharacterDetail loads
    Then a placeholder image is displayed

  2. Given the player is not the owner
    When they request /api/characters/{id}
    Then the API returns 403 Forbidden

Error / failure cases

  1. Given invalid override data (negative HP)
    When PUT /overrides is called
    Then the API returns 400 Bad Request

  2. Given the API is unavailable
    When the character detail page loads
    Then an error state is shown


Acceptance Criteria

Functional

  • DM can view all characters in a campaign
  • Players can view their own character sheets (auth permitting)
  • DM can apply HP/AC/condition overrides
  • Character portraits render using Image Management assets

Non-functional

  • UI uses code-behind pattern and CSS custom properties only
  • bUnit tests cover list + detail components

Dependencies


Agent Work Breakdown

Agent Task Depends On
The Doctor Approve spec
Danny Write failing bUnit tests Spec approved
Clara Implement character UI components Danny's tests
Rory Implement API endpoints + query services Core entities
Danny Confirm all tests pass All implementation

Definition of Done

  • Test Scenarios section completed and approved by The Doctor before implementation
  • All failing tests written by Danny before implementation (TDD)
  • All tests written and passing (bUnit + API tests)
  • Code reviewed and approved by The Doctor
  • All Razor components follow code-behind pattern
  • GitHub issue closed and linked to merged PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspecSpecification work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions