diff --git a/gerbil-manager-web/e2e/stammbaum.spec.ts b/gerbil-manager-web/e2e/stammbaum.spec.ts index 2f55793..e9d6ecf 100644 --- a/gerbil-manager-web/e2e/stammbaum.spec.ts +++ b/gerbil-manager-web/e2e/stammbaum.spec.ts @@ -137,3 +137,20 @@ test('Kein Würfe-Panel wenn Wurzeltier keine Würfe hat (STAMMBAUM-LITTERS)', a await expect(page.locator('.pedigree-card').first()).toBeVisible() await expect(page.locator('.stammbaum-litters-panel')).not.toBeVisible() }) + +test('Knoten-Karte zeigt volles Geburtsdatum (STAMMBAUM-FULLDATE)', async ({ page }) => { + skipUnlessMock() + // Krümel: dateOfBirth '2025-03-12' → formatDate → '12.03.2025' + await page.goto('/rennmaeuse/kruemel/stammbaum') + await expect(page.locator('.pedigree-card').first()).toBeVisible() + await expect(page.locator('.pedigree-card__year').first()).toContainText('12.03.2025') +}) + +test('Gencode-Chip zeigt Genotyp statt Farbname (STAMMBAUM-GENCODE)', async ({ page }) => { + skipUnlessMock() + // Fridolin ist Vater von Krümel — genotype 'aa CC DD EE GG PP spsp rere' + await page.goto('/rennmaeuse/kruemel/stammbaum') + await expect(page.locator('.pedigree-card').first()).toBeVisible() + const fridolinCard = page.locator('.pedigree-card').filter({ hasText: 'Fridolin' }) + await expect(fridolinCard.locator('.pedigree-chip')).toContainText('aa CC') +}) diff --git a/gerbil-manager-web/src/components/AppShell.tsx b/gerbil-manager-web/src/components/AppShell.tsx index 043260f..06b2c93 100644 --- a/gerbil-manager-web/src/components/AppShell.tsx +++ b/gerbil-manager-web/src/components/AppShell.tsx @@ -1,19 +1,21 @@ import { useState } from 'react' +import type { ReactNode } from 'react' import { NavLink, Outlet } from 'react-router-dom' import { de } from '../strings/de' +import GerbilIcon from './GerbilIcon' import './appShell.css' interface NavItem { to: string label: string - icon: string + icon: ReactNode end?: boolean } // Primary items are always visible in the phone bottom bar; secondary items // move into the "Mehr" sheet on phones and appear inline in the desktop sidebar. const PRIMARY: NavItem[] = [ - { to: '/rennmaeuse', label: de.nav.gerbils, icon: '🐭' }, + { to: '/rennmaeuse', label: de.nav.gerbils, icon: }, { to: '/wuerfe', label: de.nav.litters, icon: '🍼' }, { to: '/genetik', label: de.nav.genetics, icon: '🧬' }, ] @@ -46,7 +48,7 @@ export default function AppShell() { return (
- +

{de.app.title}

diff --git a/gerbil-manager-web/src/components/GerbilIcon.tsx b/gerbil-manager-web/src/components/GerbilIcon.tsx new file mode 100644 index 0000000..7209852 --- /dev/null +++ b/gerbil-manager-web/src/components/GerbilIcon.tsx @@ -0,0 +1,35 @@ +import type { CSSProperties } from 'react' + +interface Props { + size?: string | number + style?: CSSProperties + className?: string +} + +/** Reusable gerbil silhouette icon — upright sitting pose, long tail with tuft. fill=currentColor. */ +export default function GerbilIcon({ size = '1em', style, className }: Props) { + return ( + + {/* body — sitting upright */} + + {/* ear */} + + {/* hind paw */} + + {/* long curved tail with tuft */} + + {/* front paw */} + + + ) +} diff --git a/gerbil-manager-web/src/pages/StammbaumPage.tsx b/gerbil-manager-web/src/pages/StammbaumPage.tsx index 120051c..a450599 100644 --- a/gerbil-manager-web/src/pages/StammbaumPage.tsx +++ b/gerbil-manager-web/src/pages/StammbaumPage.tsx @@ -28,6 +28,7 @@ import { getInbreedingCoefficient } from '../api/pedigree' import type { Gender, Gerbil, Litter } from '../api/types' import { useApi } from '../hooks/useApi' import { formatDate, genderLabel } from '../format/labels' +import GerbilIcon from '../components/GerbilIcon' import { UNKNOWN_FARBSCHLAG, fromDisplayString, genotypeToFarbschlag, toDisplayString } from '../genetics' import { DEFAULT_GENERATIONS, @@ -379,7 +380,7 @@ function PedigreeCard({ const t = de.pages.stammbaum const g = node.gerbil const chip = farbschlag ? chipColorFor(farbschlag) : null - const year = g.dateOfBirth ? g.dateOfBirth.slice(0, 4) : null + const dob = g.dateOfBirth ? formatDate(g.dateOfBirth) : null return (
{/* Foto-Platzhalter — echte Fotos kommen mit FEAT-6. */}
@@ -406,11 +407,12 @@ function PedigreeCard({ - {farbschlag} + {g.genotype || farbschlag} )} - {year && * {year}} + {dob && * {dob}}
{node.expandable && (