- /npcs/family/{family} (app_npc_family) renders a parent->child tree for
everyone sharing that family name; co-parents who are both in the family
are paired into one couple node, elders first
- FamilyTreeBuilder does the flat-list -> tree assembly
- the NPC detail page's family name (subtitle + Details row) now links there
- .family-tree CSS: nested list with connector lines, small portrait avatars
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
51 lines
1.7 KiB
Twig
51 lines
1.7 KiB
Twig
{% extends 'base.html.twig' %}
|
|
|
|
{% block title %}{{ family }} family · NPC's · dmtools{% endblock %}
|
|
|
|
{% macro person(npc, muted) %}
|
|
<a class="ft-person{{ muted ? ' text-body-secondary' : '' }}" href="{{ path('app_npc_show', {id: npc.id}) }}">
|
|
<img src="{{ asset(npc.portraitPath) }}" alt="" width="34" height="42"
|
|
class="rounded object-fit-cover" onerror="this.remove()">
|
|
<span class="ft-name">{{ npc.name }}</span>
|
|
<span class="ft-meta">{{ npc.age ?? '?' }}{% if npc.occupation %} · {{ npc.occupation }}{% endif %}</span>
|
|
</a>
|
|
{% endmacro %}
|
|
|
|
{% macro node(n) %}
|
|
{% import _self as tree %}
|
|
<li>
|
|
<div class="ft-couple">
|
|
{{ tree.person(n.npc) }}
|
|
{% if n.spouse %}
|
|
<span class="ft-amp">&</span>
|
|
{{ tree.person(n.spouse) }}
|
|
{% endif %}
|
|
</div>
|
|
{% if n.children %}
|
|
<ul>
|
|
{% for c in n.children %}{{ tree.node(c) }}{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
</li>
|
|
{% endmacro %}
|
|
|
|
{% import _self as tree %}
|
|
|
|
{% block body %}
|
|
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
<div>
|
|
<a href="{{ path('app_npcs') }}" class="text-decoration-none small">← All NPC's</a>
|
|
<h1 class="h3 mb-0">The {{ family }} family</h1>
|
|
<span class="text-body-secondary">{{ count }} member{{ count == 1 ? '' : 's' }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<ul class="family-tree">
|
|
{% for r in roots %}{{ tree.node(r) }}{% endfor %}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|