Katalog (catalog.ts): - 8 'X dd'/'dd X' Einträge → 'Dilute X' (Agouti/Silberagouti/Kohlfuchs/Anthrazit/ Topas/Blaufuchs dd + dd Gold/Platin → Dilute Gold/Platin etc.) - 4 neue Dilute-Fuchs-Basiseinträge (Dilute Algierfuchs/Goldfuchs/Rotfuchs/Polarfuchs) → verhindert naked 'Fuchs' Fallback für agouti+dilute+fox Genotypen. 66→70 Einträge. - colourpointName: 'Dilute X' Base → 'Dilute CP-X' statt 'CP-Dilute X' (Präfix-Reihenfolge) → AA cchmcchm dd ee GG PP = 'Dilute CP-Algierfuchs' statt 'CP-Fuchs'. Engine (farbschlagFor): - REW-Check: c0==cchm && c1==cchm && p0==p && p1==p → 'REW' (Rotaugenweiß). Unabhängig von A/D/E/G. Flagged to god zur Bestätigung. BreedingResultView: - Gencode (bracket notation) pro Farbschlag-Karte (erster/wahrscheinlichster Genotyp). - Layout-Fix: flexbox body (name+gencode gestapelt), min-width:0 gegen Overflow, word-break, grid min 15rem, prob flex-shrink:0 rechtsbündig. Tests: GEN-4 describe (Dilute/REW/no-bare-Fuchs Fixtures); CATALOG_SIZE 66→70; CP-Fuchs/CP-Fuchs-Hell → Dilute CP-Algierfuchs(-Hell) in bestehenden Tests. Gate: build ✓ eslint ✓ vitest 95/95 ✓ e2e 148/148 ✓
gerbil-manager-web
Frontend des Rennmaus-Managers — React + TypeScript + Vite, mobile-first (Smartphone und Laptop).
Entwicklung
npm install
npm run dev
Erwartet die laufende GerbilManagerWebAPI unter http://localhost:5179
(Profil http in GerbilManagerWebAPI/Properties/launchSettings.json).
Konfiguration
| Variable | Standard | Beschreibung |
|---|---|---|
VITE_API_BASE_URL |
http://localhost:5179 |
Basis-URL der GerbilManagerWebAPI |
Konventionen
- Alle für Benutzer sichtbaren Texte sind Deutsch und liegen zentral in
src/strings/de.ts— keine Texte direkt in Komponenten hartkodieren. - API-Zugriffe laufen über
src/api/client.ts. - Routen werden in
src/App.tsxregistriert, Seiten liegen insrc/pages/. - Mutationen (
useMutationaussrc/hooks/useApi.ts):run()wirft NIE, sondern liefert einMutationOutcome<T>—{ ok: true, value }oder{ ok: false, error, cause }. Aufrufer MÜSSEN verzweigen:const r = await m.run(x); if (r.ok) navigate(r.value.id).m.errortreibt die Inline-Anzeige; für Spezialfälle (z. B. HTTP 409)r.causeprüfen (r.cause instanceof ApiError && r.cause.status === 409). So sind unbehandelte Promise-Rejections an Aufrufstellen ausgeschlossen (siehe auchsrc/dev/unhandledRejectionGuard.ts).
Build
npm run build
npm run preview
E2E-Tests (QA-1, Playwright)
npm run e2e # Mock-Modus: startet Vite auf :5199, API wird gemockt
npx playwright test --project=phone # nur Smartphone-Viewport (390px)
- Mock-Modus (Standard): kein Backend nötig.
e2e/mock-api.tsfängt alle API-Aufrufe ab (DATA-2-Vertrag: Gridify-Paging, camelCase, 409-Konflikte) mit frischem Datenbestand pro Test (e2e/mock-data.ts). - Live-Modus: dieselbe Suite gegen den echten Stack —
$env:E2E_BASE_URL = 'http://localhost:5173'; npm run e2e(vorher AppHost starten). Tests, die Mock-Seed-Daten voraussetzen, überspringen sich selbst; die übrigen legen eigene Datensätze an. - Beide Viewports (Smartphone 390px, Laptop 1280px) laufen für jede Spec;
alle Assertions prüfen die deutschen Oberflächentexte direkt aus
src/strings/de.ts.