Add NPC database table with server-side DataTable and per-NPC game notes

- Npc entity (village spreadsheet columns) + game_notes text field for
  the DM's live play notes, plus updated_at touched on every change
- Race / VillageStatus / BloodCartInvolvement / MysteryImportance as
  string-backed PHP enums, rendered as dropdowns on the edit form
- /npcs: server-side DataTables (paging, global search and column sort
  all run in the backend via NpcRepository::findForDataTable); name cell
  links to the edit page, game notes shown truncated
- /npcs/{id}: Bootstrap-themed edit form (all fields + a large game
  notes textarea); Symfony forms now use the bootstrap_5 theme
- app.js: generic server-side DataTable wiring driven by data-* on the
  <table>/<th> (data-datatable-src, data-row-url, data-format)
- app:npc:import console command - upserts from data/npcs.csv by
  (family, name), never overwrites game_notes; --purge / --dry-run
- data/npcs.csv: 180 villagers exported from the working spreadsheet

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Frank
2026-09-06 15:04:39 +02:00
co-authored by Claude Sonnet 5
parent cc4fbf425d
commit 1ccab6ed68
15 changed files with 1010 additions and 9 deletions
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace App\Enum;
enum BloodCartInvolvement: string
{
case None = 'None';
case Donor = 'Donor';
case OccasionalDonor = 'Occasional donor';
case BloodCollector = 'Blood collector';
case BloodCartDriver = 'Blood-cart driver';
case CouncilOversight = 'Council oversight';
public function label(): string
{
return $this->value;
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace App\Enum;
enum MysteryImportance: string
{
case Low = 'Low';
case Medium = 'Medium';
case High = 'High';
case Critical = 'Critical';
public function label(): string
{
return $this->value;
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Enum;
enum Race: string
{
case Human = 'Human';
case Dwarf = 'Dwarf';
case Elf = 'Elf';
case HalfElf = 'Half-Elf';
case Halfling = 'Halfling';
case Gnome = 'Gnome';
case HalfOrc = 'Half-Orc';
case Tiefling = 'Tiefling';
case Dragonborn = 'Dragonborn';
case Other = 'Other';
public function label(): string
{
return $this->value;
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace App\Enum;
enum VillageStatus: string
{
case Established = 'Established villager';
case Young = 'Young villager';
case Adopted = 'Adopted villager';
case NewlyEligibleDonor = 'Newly eligible donor';
public function label(): string
{
return $this->value;
}
}