From d5f4be76be529383121e4fad92f8bdeaf5f00f86 Mon Sep 17 00:00:00 2001 From: Gulum Date: Sat, 6 Jun 2026 21:39:14 +0200 Subject: [PATCH] =?UTF-8?q?ANIMAL-LITTERS:=20Tier-Detailseite=20zeigt=20W?= =?UTF-8?q?=C3=BCrfe=20dieses=20Tiers=20als=20Elternteil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GerbilDetailPage: listLittersPaged({filter: fatherId={id}|motherId={id}}) + neue Sektion 'Würfe als Elternteil' vor den Tabs; je Wurf: Link /wuerfe/{id}, Vater/Mutter-Badge, Datum, Wurfstärke; Leer-Zustand wenn keine Würfe - de.ts: parentLittersTitle, parentLittersEmpty, parentLittersRoleVater/Mutter (append-only in detail-Sektion) - e2e: +2 Tests (Fridolin hat Wurf K als Vater; Krümel hat Leer-Zustand) Gate: vitest 104/104, e2e 160/160, tsc clean --- gerbil-manager-web/e2e/tiere.spec.ts | 24 ++++++++++++++ .../src/pages/GerbilDetailPage.tsx | 31 +++++++++++++++++++ gerbil-manager-web/src/strings/de.ts | 5 +++ 3 files changed, 60 insertions(+) diff --git a/gerbil-manager-web/e2e/tiere.spec.ts b/gerbil-manager-web/e2e/tiere.spec.ts index 30f7a02..30868d5 100644 --- a/gerbil-manager-web/e2e/tiere.spec.ts +++ b/gerbil-manager-web/e2e/tiere.spec.ts @@ -172,3 +172,27 @@ test('Tier bearbeiten — isDeaf Tristate round-trip (FORM-FIELDS-1)', async ({ await page.goto('/rennmaeuse/kruemel/bearbeiten') await expect(page.getByLabel(t.fields.isDeaf)).toHaveValue('true') }) + +test('Detailseite: Würfe als Elternteil zeigt verlinkten Wurf (ANIMAL-LITTERS)', async ({ page }) => { + skipUnlessMock() + // Fridolin ist fatherId von 'w-kruemel' (Wurf K) + await page.goto('/rennmaeuse/fridolin') + await expect(page.getByRole('heading', { name: 'Fridolin' })).toBeVisible() + await expect(page.getByText(t.detail.parentLittersTitle)).toBeVisible() + // Wurf K als Link sichtbar + const litterLink = page.getByRole('link', { name: /Wurf K/ }) + await expect(litterLink).toBeVisible() + // Vater-Badge sichtbar + await expect(page.getByText(t.detail.parentLittersRoleVater)).toBeVisible() + // Navigation zum Wurf funktioniert + await litterLink.first().click() + await expect(page.getByRole('heading', { name: 'Wurf K' })).toBeVisible() +}) + +test('Detailseite: Keine Würfe als Elternteil zeigt Leer-Zustand (ANIMAL-LITTERS)', async ({ page }) => { + skipUnlessMock() + // Krümel hat keine Würfe als Elternteil (nur als Kind von w-kruemel) + await page.goto('/rennmaeuse/kruemel') + await expect(page.getByText(t.detail.parentLittersTitle)).toBeVisible() + await expect(page.getByText(t.detail.parentLittersEmpty)).toBeVisible() +}) diff --git a/gerbil-manager-web/src/pages/GerbilDetailPage.tsx b/gerbil-manager-web/src/pages/GerbilDetailPage.tsx index e6ea159..898baf3 100644 --- a/gerbil-manager-web/src/pages/GerbilDetailPage.tsx +++ b/gerbil-manager-web/src/pages/GerbilDetailPage.tsx @@ -2,6 +2,7 @@ import { useMemo, useState, type ReactNode } from 'react' import { Link, useParams } from 'react-router-dom' import { de } from '../strings/de' import { getGerbil, updateGerbil } from '../api/gerbils' +import { listLitters as listLittersPaged } from '../api/litters' import { listColorVarieties, listContacts, listEnclosures, listLitters } from '../api/lookups' import { useApi, useMutation } from '../hooks/useApi' import { formatDate, genderLabel, statusLabel } from '../format/labels' @@ -55,6 +56,10 @@ export default function GerbilDetailPage() { const enclosures = useApi(() => listEnclosures(), []) const contacts = useApi(() => listContacts(), []) const litters = useApi(() => listLitters(), []) + const parentLitters = useApi( + () => listLittersPaged({ filter: `fatherId=${id}|motherId=${id}`, orderBy: 'date desc', pageSize: 50 }), + [id], + ) const colorName = useMemo( () => new Map((colorVarieties.data ?? []).map((c) => [c.id, c.name])), @@ -237,6 +242,32 @@ export default function GerbilDetailPage() { {saveCharacter.error && {saveCharacter.error}} +

{t.detail.parentLittersTitle}

+ {parentLitters.loading &&

{de.common.loading}

} + {!parentLitters.loading && (parentLitters.data?.items.length ?? 0) === 0 && ( +

{t.detail.parentLittersEmpty}

+ )} + {(parentLitters.data?.items.length ?? 0) > 0 && ( + + )} +

{t.detail.moreData}

{(['photos', 'health', 'weight'] as const).map((key) => ( diff --git a/gerbil-manager-web/src/strings/de.ts b/gerbil-manager-web/src/strings/de.ts index 25aaae4..dda656d 100644 --- a/gerbil-manager-web/src/strings/de.ts +++ b/gerbil-manager-web/src/strings/de.ts @@ -105,6 +105,11 @@ export const de = { tabPlaceholder: 'Dieser Bereich entsteht in einem späteren Schritt.', notFound: 'Diese Rennmaus wurde nicht gefunden.', moreData: 'Weitere Daten', + // ANIMAL-LITTERS: Würfe als Elternteil + parentLittersTitle: 'Würfe als Elternteil', + parentLittersEmpty: 'Keine Würfe als Elternteil erfasst.', + parentLittersRoleVater: 'Vater', + parentLittersRoleMutter: 'Mutter', }, // Formular (anlegen/bearbeiten) form: {