feat(tmdb): clickable director/creator chips and directing credits on person pages (#1227)

* feat(tmdb): clickable director/creator chips and directing credits on person pages

Directors were plain merged text — no photos, no navigation — while the
data was already sitting in the cached TMDB payloads (credits.crew and
created_by both carry id + profile_path; they just were not typed or
parsed).

- tmdb-merge: enrichedDirectors (crew, job === 'Director', deduped by
  person id) and enrichedCreators (created_by) produce the same chip
  shape as the cast (TmdbEnrichedCastMember) into a new tmdb_directors
  field on all three merges (Xtream VOD, Xtream series, Stalker); types
  widened (crew id/profile_path, created_by id/profile_path).
- Detail views (shared VodDetailsComponent, Xtream vod/serial routes,
  Stalker series view) render the Director row as clickable avatar chips
  when tmdb_directors is present — same markup and openActor handler as
  the cast strip — falling back to the plain text otherwise. Stalker
  re-normalization allowlist preserves the new field.
- Person pages: mapPersonFilmography now merges combined_credits.crew
  (jobs Director/Creator) into the filmography — acting wins the
  per-title dedup, directing-only titles show the job in the character
  slot. Everything else (library matching, All-portals scope, filters,
  search fallback, back button) works unchanged because the person page
  is role-agnostic. Existing caches work as-is: crew/created_by were
  always part of the stored payloads.

Tests: merge spec (director/creator chips + crew-row dedup ×3 merges),
person spec (crew credits, Producer excluded, acting-wins dedup),
stalker-vod.utils passthrough. Docs updated (CLAUDE.md + architecture).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(tmdb): address director-pages review — split oversized spec, stable track keys, translated crew roles

- tmdb-merge.spec.ts grew past the 400-line lint ceiling — the Stalker
  merge suite moved to tmdb-merge-stalker.spec.ts (fixes the CI Lint job).
- All cast/director chip loops now track by TMDB person id with an
  index fallback ('p<id>' / 'i<index>') instead of member.name — distinct
  people can share a name and creator payloads carry no dedup (greptile).
- Directing-only filmography credits carry the role in a new crewJob
  field ('Director' | 'Creator') instead of stuffing TMDB's raw English
  job into character; ActorViewComponent renders it through translated
  labels (XTREAM.CREW_JOB_DIRECTOR/CREATOR, added to all 18 locales via
  the i18n patch workflow, matching each locale's existing glossary —
  pt "Diretor", de "Regisseur") (Codex).

Tests: person spec asserts character/crewJob separation; merge suites
green after the split (15 + stalker file).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 4.8 authored and GitHub committed 2026-07-24 08:42:41 +02:00
1 parent 59c15493a7
commit 5aa44d19d4
40 files changed
+528 -154

No files matched your search

+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "الممثلون",
"DIRECTOR": "المخرج",
"SIMILAR": "مشابه",
"CREW_JOB_DIRECTOR": "المخرج",
"CREW_JOB_CREATOR": "المبتكر",
"ACTOR_FILMOGRAPHY": "الأعمال الفنية",
"ACTOR_FILTER_ALL": "الكل",
"ACTOR_SCOPE_THIS_PORTAL": "هذه البوابة",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "الممثلون",
"DIRECTOR": "المخرج",
"SIMILAR": "بحال هادو",
"CREW_JOB_DIRECTOR": "المخرج",
"CREW_JOB_CREATOR": "المبتكر",
"ACTOR_FILMOGRAPHY": "الأفلام ديالو",
"ACTOR_FILTER_ALL": "كلشي",
"ACTOR_SCOPE_THIS_PORTAL": "هاد البوابة",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Акцёры",
"DIRECTOR": "Рэжысёр",
"SIMILAR": "Падобнае",
"CREW_JOB_DIRECTOR": "Рэжысёр",
"CREW_JOB_CREATOR": "Стваральнік",
"ACTOR_FILMOGRAPHY": "Фільмаграфія",
"ACTOR_FILTER_ALL": "Усе",
"ACTOR_SCOPE_THIS_PORTAL": "Гэты партал",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Schauspieler",
"DIRECTOR": "Regisseur",
"SIMILAR": "Ähnliche Titel",
"CREW_JOB_DIRECTOR": "Regisseur",
"CREW_JOB_CREATOR": "Schöpfer",
"ACTOR_FILMOGRAPHY": "Filmografie",
"ACTOR_FILTER_ALL": "Alle",
"ACTOR_SCOPE_THIS_PORTAL": "Dieses Portal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Ηθοποιοί",
"DIRECTOR": "Σκηνοθέτης",
"SIMILAR": "Παρόμοια",
"CREW_JOB_DIRECTOR": "Σκηνοθέτης",
"CREW_JOB_CREATOR": "Δημιουργός",
"ACTOR_FILMOGRAPHY": "Φιλμογραφία",
"ACTOR_FILTER_ALL": "Όλα",
"ACTOR_SCOPE_THIS_PORTAL": "Αυτή η πύλη",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Actors",
"DIRECTOR": "Director",
"SIMILAR": "Similar",
"CREW_JOB_DIRECTOR": "Director",
"CREW_JOB_CREATOR": "Creator",
"ACTOR_FILMOGRAPHY": "Filmography",
"ACTOR_FILTER_ALL": "All",
"ACTOR_SCOPE_THIS_PORTAL": "This portal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Actores",
"DIRECTOR": "Director",
"SIMILAR": "Similares",
"CREW_JOB_DIRECTOR": "Director",
"CREW_JOB_CREATOR": "Creador",
"ACTOR_FILMOGRAPHY": "Filmografía",
"ACTOR_FILTER_ALL": "Todas",
"ACTOR_SCOPE_THIS_PORTAL": "Este portal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Acteurs",
"DIRECTOR": "Réalisateur",
"SIMILAR": "Similaires",
"CREW_JOB_DIRECTOR": "Réalisateur",
"CREW_JOB_CREATOR": "Créateur",
"ACTOR_FILMOGRAPHY": "Filmographie",
"ACTOR_FILTER_ALL": "Tout",
"ACTOR_SCOPE_THIS_PORTAL": "Ce portail",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Attori",
"DIRECTOR": "Regista",
"SIMILAR": "Simili",
"CREW_JOB_DIRECTOR": "Regista",
"CREW_JOB_CREATOR": "Ideatore",
"ACTOR_FILMOGRAPHY": "Filmografia",
"ACTOR_FILTER_ALL": "Tutti",
"ACTOR_SCOPE_THIS_PORTAL": "Questo portale",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "出演者",
"DIRECTOR": "監督",
"SIMILAR": "類似作品",
"CREW_JOB_DIRECTOR": "監督",
"CREW_JOB_CREATOR": "クリエイター",
"ACTOR_FILMOGRAPHY": "出演作品",
"ACTOR_FILTER_ALL": "すべて",
"ACTOR_SCOPE_THIS_PORTAL": "このポータル",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "배우",
"DIRECTOR": "감독",
"SIMILAR": "비슷한 콘텐츠",
"CREW_JOB_DIRECTOR": "감독",
"CREW_JOB_CREATOR": "크리에이터",
"ACTOR_FILMOGRAPHY": "출연 작품",
"ACTOR_FILTER_ALL": "전체",
"ACTOR_SCOPE_THIS_PORTAL": "현재 포털",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Acteurs",
"DIRECTOR": "Regisseur",
"SIMILAR": "Vergelijkbaar",
"CREW_JOB_DIRECTOR": "Regisseur",
"CREW_JOB_CREATOR": "Bedenker",
"ACTOR_FILMOGRAPHY": "Filmografie",
"ACTOR_FILTER_ALL": "Alles",
"ACTOR_SCOPE_THIS_PORTAL": "Dit portaal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Aktorzy",
"DIRECTOR": "Reżyser",
"SIMILAR": "Podobne",
"CREW_JOB_DIRECTOR": "Reżyser",
"CREW_JOB_CREATOR": "Twórca",
"ACTOR_FILMOGRAPHY": "Filmografia",
"ACTOR_FILTER_ALL": "Wszystkie",
"ACTOR_SCOPE_THIS_PORTAL": "Ten portal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Atores",
"DIRECTOR": "Diretor",
"SIMILAR": "Semelhantes",
"CREW_JOB_DIRECTOR": "Diretor",
"CREW_JOB_CREATOR": "Criador",
"ACTOR_FILMOGRAPHY": "Filmografia",
"ACTOR_FILTER_ALL": "Todos",
"ACTOR_SCOPE_THIS_PORTAL": "Este portal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Актеры",
"DIRECTOR": "Режиссёр",
"SIMILAR": "Похожее",
"CREW_JOB_DIRECTOR": "Режиссёр",
"CREW_JOB_CREATOR": "Создатель",
"ACTOR_FILMOGRAPHY": "Фильмография",
"ACTOR_FILTER_ALL": "Все",
"ACTOR_SCOPE_THIS_PORTAL": "Этот портал",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "Oyuncular",
"DIRECTOR": "Yönetmen",
"SIMILAR": "Benzerler",
"CREW_JOB_DIRECTOR": "Yönetmen",
"CREW_JOB_CREATOR": "Yaratıcı",
"ACTOR_FILMOGRAPHY": "Filmografi",
"ACTOR_FILTER_ALL": "Tümü",
"ACTOR_SCOPE_THIS_PORTAL": "Bu portal",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "演员",
"DIRECTOR": "导演",
"SIMILAR": "类似影片",
"CREW_JOB_DIRECTOR": "导演",
"CREW_JOB_CREATOR": "主创",
"ACTOR_FILMOGRAPHY": "参演作品",
"ACTOR_FILTER_ALL": "全部",
"ACTOR_SCOPE_THIS_PORTAL": "当前门户",
+2
View File
@@ -785,6 +785,8 @@
"ACTORS": "演員",
"DIRECTOR": "導演",
"SIMILAR": "類似作品",
"CREW_JOB_DIRECTOR": "導演",
"CREW_JOB_CREATOR": "主創",
"ACTOR_FILMOGRAPHY": "參演作品",
"ACTOR_FILTER_ALL": "全部",
"ACTOR_SCOPE_THIS_PORTAL": "目前入口",