Files
GerbilManager/gerbil-manager-web
Gulum 972570b142 GEN-3f: reconcile cchm colourpoint catalog to the breeder's CP- naming
Computed Farbschlag now == the breeder's dropdown/seed names for colourpoints,
so the mismatch hint stops and the live re-import name-matches her data
(god: she uses the CP- prefix form + Marder/Siam/Zobel/Zobel-Hell; ZERO of the
old portal suffix names). FULL collapse (god-approved, data-safe).

Catalog (BASE_COLORS) 73 -> 61: the 24 portal cchm rows collapse to 12 breeder
varieties — Marder, Siam, Zobel, Zobel-Hell (aa marten/sable group; E & D
irrelevant per the merged GEN-3e rule) and CP-Agouti, CP-Silberagouti,
CP-Algierfuchs, CP-Polarfuchs, CP-Fuchs, CP-Fuchs-Hell, CP-Blaufuchs,
CP-Orangeschimmel (A- 'CP-<base>'; -Hell shade variants collapsed).

- representativeGenotype() now splits a heterozygous 'x/y' token, so the het
  colourpoints Siam & Zobel-Hell (C: 'cchm/ch') carry the correct het canonical
  genotype and the engine computes their own names (verified).
- Engine covers all fox(ee)/dilute(dd) A- cchm bases via the E-family fallback
  (no Unbekannt). KNOWN BEST-EFFORT GAP: CP-Fuchs-Hell and CP-Blaufuchs both
  compute 'CP-Fuchs' (the het-lighter / blue-dilute distinction isn't encoded);
  their distinct rows remain for hand-pick + import name-match. Closing this
  fully needs the breeder's exact fox-CP genotype rule.

Regenerated colorVarietySeed.generated.json (61 rows) for Pam's re-seed
migration. Gate green: build, eslint, vitest 78, e2e 80. de.ts untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 11:47:40 +02:00
..

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.tsx registriert, Seiten liegen in src/pages/.
  • Mutationen (useMutation aus src/hooks/useApi.ts): run() wirft NIE, sondern liefert ein MutationOutcome<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.error treibt die Inline-Anzeige; für Spezialfälle (z. B. HTTP 409) r.cause prüfen (r.cause instanceof ApiError && r.cause.status === 409). So sind unbehandelte Promise-Rejections an Aufrufstellen ausgeschlossen (siehe auch src/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.ts fä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.