Show the NPC portrait on the detail page

Npc::getPortraitPath() maps the name to image/npc-pictures/<NameNoSpaces>.png;
the edit page renders it beside the heading (with family · occupation), and
drops the <img> via onerror when a portrait is missing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Frank
2026-09-06 16:10:00 +02:00
co-authored by Claude Sonnet 5
parent 4d5c3253ed
commit 71b5cb6633
2 changed files with 21 additions and 4 deletions
+10
View File
@@ -227,4 +227,14 @@ class Npc
{
return $this->updatedAt;
}
/**
* AssetMapper logical path of this NPC's portrait, e.g.
* "image/npc-pictures/GarrickVoss.png". The file may not exist for
* NPCs added after the portrait sets were generated.
*/
public function getPortraitPath(): string
{
return 'image/npc-pictures/'.str_replace(' ', '', $this->name).'.png';
}
}
+8 -1
View File
@@ -3,10 +3,17 @@
{% block title %}{{ npc.name }} · NPC's · 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-start mb-3 gap-3">
<div class="d-flex gap-3">
<img src="{{ asset(npc.portraitPath) }}" alt="Portrait of {{ npc.name }}"
width="96" height="120"
class="rounded border object-fit-cover flex-shrink-0"
onerror="this.remove()">
<div>
<a href="{{ path('app_npcs') }}" class="text-decoration-none small">&larr; All NPC's</a>
<h1 class="h3 mb-0">{{ npc.name }}</h1>
<span class="text-body-secondary">{{ npc.family }}{% if npc.occupation %} · {{ npc.occupation }}{% endif %}</span>
</div>
</div>
{% if npc.updatedAt %}
<span class="text-body-secondary small">Updated {{ npc.updatedAt|date('Y-m-d H:i') }}</span>