UI-POLISH-1: namenlose Tiere + Leerwert-Konsistenz
- de.ts: nameless = '(ohne Namen)' (neuer Platzhalter-String) - GerbilsPage: g.name || t.nameless in Karten-Name + Checkbox-Aria - GerbilDetailPage: g.name || nameless im h2-Header; g.causeOfDeath/notes via || null (leer-string-sicher wie Herkunft) - AnimalPicker: g.name || nameless im Picker-Button e2e: +1 nameless-stub in mock-data; 2 neue Tests (Liste + Detail-Header) Gate: vitest 82/82, e2e 130/130, tsc clean
This commit is contained in:
@@ -149,6 +149,8 @@ export function seedDb(): MockDb {
|
|||||||
enclosureId: 'enc-leer',
|
enclosureId: 'enc-leer',
|
||||||
notes: 'neugieriger Entdecker',
|
notes: 'neugieriger Entdecker',
|
||||||
},
|
},
|
||||||
|
// UI-POLISH-1: Import-Stub ohne Namen — testet den '(ohne Namen)'-Platzhalter in Liste + Detail.
|
||||||
|
gerbil('nameless-stub', '', 'male', '2023-01-01', null, null),
|
||||||
]
|
]
|
||||||
|
|
||||||
const litters: Litter[] = [
|
const litters: Litter[] = [
|
||||||
|
|||||||
@@ -127,6 +127,19 @@ test('Detailseite: Herkunft zeigt Kontaktlink wenn originContactId gesetzt (WURF
|
|||||||
await expect(originLink).toHaveAttribute('href', '/kontakte/con-meier')
|
await expect(originLink).toHaveAttribute('href', '/kontakte/con-meier')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Namenlose Tiere zeigen Platzhalter in der Liste (UI-POLISH-1)', async ({ page }) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
await page.goto('/rennmaeuse')
|
||||||
|
// 'nameless-stub' hat name='' → Platzhalter '(ohne Namen)' soll als Link sichtbar sein
|
||||||
|
await expect(page.getByRole('link', { name: de.pages.gerbils.nameless })).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Namenlose Tiere zeigen Platzhalter im Detail-Header (UI-POLISH-1)', async ({ page }) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
await page.goto('/rennmaeuse/nameless-stub')
|
||||||
|
await expect(page.getByRole('heading', { name: de.pages.gerbils.nameless })).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
test('Tier bearbeiten — Notizen ändern', async ({ page }) => {
|
test('Tier bearbeiten — Notizen ändern', async ({ page }) => {
|
||||||
skipUnlessMock()
|
skipUnlessMock()
|
||||||
await page.goto('/rennmaeuse/kruemel/bearbeiten')
|
await page.goto('/rennmaeuse/kruemel/bearbeiten')
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { de } from '../strings/de'
|
import { de } from '../strings/de'
|
||||||
|
|
||||||
|
const nameless = de.pages.gerbils.nameless
|
||||||
import { listGerbils } from '../api/gerbils'
|
import { listGerbils } from '../api/gerbils'
|
||||||
import { andFilter, condition } from '../api/gridify'
|
import { andFilter, condition } from '../api/gridify'
|
||||||
import type { Gender, Gerbil, Paged } from '../api/types'
|
import type { Gender, Gerbil, Paged } from '../api/types'
|
||||||
@@ -62,7 +64,7 @@ export default function AnimalPicker({ gender, onPick }: AnimalPickerProps) {
|
|||||||
setOpen(false)
|
setOpen(false)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{g.name}
|
{g.name || nameless}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export default function GerbilDetailPage() {
|
|||||||
<header className="page-head">
|
<header className="page-head">
|
||||||
<div>
|
<div>
|
||||||
<GerbilProfilePhoto gerbilId={g.id} />
|
<GerbilProfilePhoto gerbilId={g.id} />
|
||||||
<h2>{g.name}</h2>
|
<h2>{g.name || de.pages.gerbils.nameless}</h2>
|
||||||
<span className={`badge badge--${g.status.toLowerCase()}`}>{statusLabel(g.status)}</span>
|
<span className={`badge badge--${g.status.toLowerCase()}`}>{statusLabel(g.status)}</span>
|
||||||
{g.isResident === false && (
|
{g.isResident === false && (
|
||||||
<span className="badge badge--external" title={de.pages.gerbils.externalTitle}>
|
<span className="badge badge--external" title={de.pages.gerbils.externalTitle}>
|
||||||
@@ -153,7 +153,7 @@ export default function GerbilDetailPage() {
|
|||||||
{g.status === 'Deceased' && (
|
{g.status === 'Deceased' && (
|
||||||
<>
|
<>
|
||||||
<Row label={t.fields.dateOfDeath} value={formatDate(g.dateOfDeath)} />
|
<Row label={t.fields.dateOfDeath} value={formatDate(g.dateOfDeath)} />
|
||||||
<Row label={t.fields.causeOfDeath} value={g.causeOfDeath} />
|
<Row label={t.fields.causeOfDeath} value={g.causeOfDeath || null} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{g.status === 'GivenAway' && (
|
{g.status === 'GivenAway' && (
|
||||||
@@ -190,7 +190,7 @@ export default function GerbilDetailPage() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Row label={t.fields.receiver} value={lookup(contactName, g.receiverContactId)} />
|
<Row label={t.fields.receiver} value={lookup(contactName, g.receiverContactId)} />
|
||||||
<Row label={t.fields.notes} value={g.notes} />
|
<Row label={t.fields.notes} value={g.notes || null} />
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h3>{t.detail.genetics}</h3>
|
<h3>{t.detail.genetics}</h3>
|
||||||
|
|||||||
@@ -256,11 +256,11 @@ export default function GerbilsPage() {
|
|||||||
className="gerbil-row__check"
|
className="gerbil-row__check"
|
||||||
checked={selected.has(g.id)}
|
checked={selected.has(g.id)}
|
||||||
onChange={() => toggleSelect(g.id)}
|
onChange={() => toggleSelect(g.id)}
|
||||||
aria-label={g.name}
|
aria-label={g.name || t.nameless}
|
||||||
/>
|
/>
|
||||||
<Link to={`/rennmaeuse/${g.id}`} className="gerbil-card">
|
<Link to={`/rennmaeuse/${g.id}`} className="gerbil-card">
|
||||||
<span className="gerbil-card__name">
|
<span className="gerbil-card__name">
|
||||||
{g.name}
|
{g.name || t.nameless}
|
||||||
{g.isResident === false && (
|
{g.isResident === false && (
|
||||||
<span className="badge badge--external" title={t.externalTitle}>
|
<span className="badge badge--external" title={t.externalTitle}>
|
||||||
{t.externalBadge}
|
{t.externalBadge}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export const de = {
|
|||||||
pages: {
|
pages: {
|
||||||
gerbils: {
|
gerbils: {
|
||||||
title: 'Rennmäuse',
|
title: 'Rennmäuse',
|
||||||
|
nameless: '(ohne Namen)',
|
||||||
// Liste
|
// Liste
|
||||||
newButton: 'Neue Rennmaus',
|
newButton: 'Neue Rennmaus',
|
||||||
empty: 'Keine Rennmäuse gefunden.',
|
empty: 'Keine Rennmäuse gefunden.',
|
||||||
|
|||||||
Reference in New Issue
Block a user