- gen-seed.mts: deterministischer Generator aus catalog.ts (Single Source); emittiert BEIDE Artefakte: generated.json (Klammer-Notation, Display) + backend.json (frozen ef/cchm/ch, für Pam EF-Migrationen). Kein magisches Artefakt mehr. - package.json: npm run gen:catalog (npx tsx gen-seed.mts) - catalog-drift.test.ts: Drift-Guard — liest generated.json von Disk via import.meta.url + readFileSync, vergleicht mit live CATALOG; Fail-Meldung zeigt 'npm run gen:catalog'. 5 Test-Files, 93 Tests grün. - colorVarietySeed.backend.json: 66 Zeilen frozen symbols (ef/cchm/ch), kein sofortiger Backend-Eingriff (AR-5 Guardrail; Pam konsumiert bei nächster Reseed-Migration). - README.md: Katalog-Generator-Doku (wann laufen, was erzeugt wird). Gate: build ✓ eslint ✓ vitest 93/93 ✓
79 lines
2.8 KiB
Markdown
79 lines
2.8 KiB
Markdown
# gerbil-manager-web
|
|
|
|
Frontend des Rennmaus-Managers — React + TypeScript + Vite, mobile-first (Smartphone und Laptop).
|
|
|
|
## Entwicklung
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
npm run build
|
|
npm run preview
|
|
```
|
|
|
|
## Farbschlag-Katalog (AR-5)
|
|
|
|
Der Katalog lebt in `src/genetics/catalog.ts` (Single Source of Truth).
|
|
Nach jeder Änderung dort den Generator laufen lassen:
|
|
|
|
```bash
|
|
npm run gen:catalog
|
|
```
|
|
|
|
Erzeugt zwei Artefakte und committet beide:
|
|
|
|
| Datei | Notation | Verwendung |
|
|
|---|---|---|
|
|
| `src/genetics/colorVarietySeed.generated.json` | Klammer (`e[f]`, `c[chm]`) | UI-Dropdowns, Frontend-Suche |
|
|
| `src/genetics/colorVarietySeed.backend.json` | Frozen symbols (`ef`, `cchm`) | EF-Seed-Migrationen (Pam, DATA-Lane) |
|
|
|
|
Der vitest-Drift-Guard (`catalog-drift.test.ts`) schlägt fehl, wenn
|
|
`generated.json` nach einer Katalog-Änderung nicht aktualisiert wurde.
|
|
|
|
## E2E-Tests (QA-1, Playwright)
|
|
|
|
```bash
|
|
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`.
|