feat(JUVENILE-AVATARS): Foto-Avatare pro Jungtier im Wurf-Detail

- JuvenileCard-Komponente in WurfDetailPage mit 36px-Kreis-Avatar links
- Fallback auf GerbilIcon (SVG-Silhouette) wenn kein profilePhotoUrl
- URL-basiertes Fehler-Tracking (failedUrl) statt useEffect+imgError
- wuerfe.css: Flex-Layout fuer Card+Avatar, overflow:hidden/object-fit:cover
- StammbaumPage: gleiche Lint-Verletzung (react-hooks/set-state-in-effect)
  behoben (failedUrl-Pattern, kein useEffect mehr fuer Bild-Reset)
- E2E: profilePhotoUrl auf Pippa (pup-abgabe), neuer Avatar-Test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 08:20:19 +02:00
parent ecd7ad2658
commit 299c038449
5 changed files with 110 additions and 21 deletions

View File

@@ -381,14 +381,13 @@ function PedigreeCard({
const g = node.gerbil
const chip = farbschlag ? chipColorFor(farbschlag) : null
const dob = g.dateOfBirth ? formatDate(g.dateOfBirth) : null
const [imgError, setImgError] = useState(false)
useEffect(() => setImgError(false), [g.id])
const photoUrl =
!imgError && g.profilePhotoUrl
? /^(https?:|data:|\/\/)/.test(g.profilePhotoUrl)
? g.profilePhotoUrl
: `${API_BASE_URL}${g.profilePhotoUrl}`
: null
const [failedUrl, setFailedUrl] = useState<string | null>(null)
const rawUrl = g.profilePhotoUrl
? /^(https?:|data:|\/\/)/.test(g.profilePhotoUrl)
? g.profilePhotoUrl
: `${API_BASE_URL}${g.profilePhotoUrl}`
: null
const photoUrl = rawUrl !== failedUrl ? rawUrl : null
return (
<div
className={isRoot ? 'pedigree-card pedigree-card--root' : 'pedigree-card'}
@@ -402,7 +401,7 @@ function PedigreeCard({
src={photoUrl}
alt={g.name || ''}
className="pedigree-card__avatar"
onError={() => setImgError(true)}
onError={() => setFailedUrl(rawUrl)}
/>
) : (
<GerbilIcon size="1.6rem" aria-hidden="true" />