Add combat HP tracker

- one running tracker (Combatant rows); no encounters to manage
- Enemies list gets a "Track" column (checkbox + count) and an
  "Add to tracker" button; picking N of an enemy makes "Goblin 1..N",
  numbering continues if some are already on the tracker
- /tracker: per-combatant current/max HP with an HP bar, Damage / Heal
  by amount, remove one, "Clear all". HP is clamped to [0, max];
  0 HP shows a "Down" badge. Stats are snapshotted from the Enemy on add.
- "Tracker" nav item; tracker_picker Stimulus controller; app.js gains a
  data-format="pick" cell renderer

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Frank
2026-09-06 19:16:12 +02:00
co-authored by Claude Sonnet 5
parent e417ff9655
commit 9854e6c034
9 changed files with 461 additions and 2 deletions
+11 -2
View File
@@ -3,9 +3,17 @@
{% block title %}Enemies · dmtools{% endblock %}
{% block body %}
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="d-flex justify-content-between align-items-center mb-3 gap-2 flex-wrap">
<h1 class="h3 mb-0">Enemies</h1>
<a href="{{ path('app_enemies_new') }}" class="btn btn-primary btn-sm">Add enemy</a>
<div class="d-flex gap-2"
data-controller="tracker-picker"
data-tracker-picker-url-value="{{ path('app_tracker_add') }}"
data-tracker-picker-token-value="{{ csrf_token('track-add') }}">
<button type="button" class="btn btn-outline-primary btn-sm" data-action="tracker-picker#submit">
Add to tracker
</button>
<a href="{{ path('app_enemies_new') }}" class="btn btn-primary btn-sm">Add enemy</a>
</div>
</div>
<div class="card shadow-sm">
@@ -22,6 +30,7 @@
<th data-data="challengeRating">CR</th>
<th data-data="armorClass">AC</th>
<th data-data="gameNotes" data-format="truncate" data-orderable="false">Game notes</th>
<th data-data="id" data-format="pick" data-orderable="false">Track</th>
</tr>
</thead>
<tbody></tbody>