diff --git a/gerbil-manager-web/e2e/stammbaum.spec.ts b/gerbil-manager-web/e2e/stammbaum.spec.ts index db9da06..2f55793 100644 --- a/gerbil-manager-web/e2e/stammbaum.spec.ts +++ b/gerbil-manager-web/e2e/stammbaum.spec.ts @@ -110,3 +110,30 @@ test('+-Knopf ist sichtbar und lädt weitere Vorfahren nach (STAMMBAUM-EXPAND) await expandBtn.click({ force: true }) await expect(page.getByRole('link', { name: 'Max' })).toBeVisible({ timeout: 8000 }) }) + +test('Würfe-Panel zeigt Würfe des Wurzeltiers + Link öffnet Wurf (STAMMBAUM-LITTERS)', async ({ page }) => { + skipUnlessMock() + // Fridolin ist Vater von Wurf K (5 Junge) — Panel muss erscheinen. + await page.goto('/rennmaeuse/fridolin/stammbaum') + await expect(page.locator('.pedigree-card').first()).toBeVisible() + + const panel = page.locator('.stammbaum-litters-panel') + await expect(panel).toBeVisible() + await expect(panel).toContainText(t.littersTitle) + await expect(panel).toContainText('Wurf K') + await expect(panel).toContainText('5') + + // Link-Klick → Wurf-Detailseite + const wurfLink = panel.getByRole('link', { name: /Wurf K/ }) + await expect(wurfLink).toBeVisible() + await wurfLink.click() + await expect(page).toHaveURL(/\/wuerfe\/w-kruemel/) +}) + +test('Kein Würfe-Panel wenn Wurzeltier keine Würfe hat (STAMMBAUM-LITTERS)', async ({ page }) => { + skipUnlessMock() + // Krümel hat noch keine Würfe als Elternteil → Panel muss fehlen. + await page.goto('/rennmaeuse/kruemel/stammbaum') + await expect(page.locator('.pedigree-card').first()).toBeVisible() + await expect(page.locator('.stammbaum-litters-panel')).not.toBeVisible() +}) diff --git a/gerbil-manager-web/src/pages/StammbaumPage.tsx b/gerbil-manager-web/src/pages/StammbaumPage.tsx index 8f93b01..9e511c0 100644 --- a/gerbil-manager-web/src/pages/StammbaumPage.tsx +++ b/gerbil-manager-web/src/pages/StammbaumPage.tsx @@ -22,9 +22,10 @@ import Tree from 'react-d3-tree' import type { CustomNodeElementProps, Point, RawNodeDatum } from 'react-d3-tree' import { de } from '../strings/de' import { ApiError } from '../api/client' +import { listLitters } from '../api/litters' import { listColorVarieties } from '../api/lookups' import { getInbreedingCoefficient } from '../api/pedigree' -import type { Gender, Gerbil } from '../api/types' +import type { Gender, Gerbil, Litter } from '../api/types' import { useApi } from '../hooks/useApi' import { formatDate, genderLabel } from '../format/labels' import { UNKNOWN_FARBSCHLAG, fromDisplayString, genotypeToFarbschlag } from '../genetics' @@ -156,6 +157,13 @@ export default function StammbaumPage() { ? `${(inbreeding.data * 100).toLocaleString('de-DE', { maximumFractionDigits: 1 })} %` : t.inbreeding.unavailable + /* ── Würfe des Wurzeltiers (STAMMBAUM-LITTERS): aktualisiert bei Umwurzeln ── */ + const rootLitters = useApi( + () => listLitters({ filter: `fatherId=${id}|motherId=${id}`, orderBy: 'date desc', pageSize: 50 }), + [id], + ) + const rootLitterItems = rootLitters.data?.items ?? [] + /* ── react-d3-tree-Daten ── */ const nodesByPath = useMemo(() => (root ? collectNodes(root) : null), [root]) const datum = useMemo(() => (root ? toRawNodeDatum(root, t.unknown) : null), [root, t]) @@ -315,25 +323,30 @@ export default function StammbaumPage() { -
- {view && ( - +
+ {rootLitterItems.length > 0 && ( + )} +
+ {view && ( + + )} +