docs(crm): add Phase 2.1 Custom Fields frontend completion report

Documents all new/changed files, architecture decisions, supported
field types, admin UI features, and deployment notes for the CRM
custom fields frontend integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas Reitz 2026-03-12 18:39:50 +01:00
parent aaedf68085
commit b000353298

View file

@ -2281,13 +2281,79 @@ Das Array enthaelt ALLE definierten Custom Fields fuer den jeweiligen Entity-Typ
- **Orphan-Cleanup**: Beim Loeschen eines Contacts/Company/Deal werden zugehoerige Custom-Field-Werte automatisch entfernt.
- **isRequired** wird aktuell nur client-seitig ausgewertet (das Flag wird mitgeliefert). Server-seitige Pflichtfeld-Pruefung kann spaeter ergaenzt werden.
### TODO fuer Frontend
### ~~TODO fuer Frontend~~ — ERLEDIGT (2026-03-12)
1. **Admin-Bereich:** CRUD-UI fuer Custom Field Definitionen (pro Entity-Typ: PERSON, COMPANY, DEAL)
- Felder: Label (→ Slug auto), Feldtyp (immutable nach Erstellung), Options-Editor fuer DROPDOWN/MULTI_SELECT, Pflichtfeld-Toggle, Drag&Drop fuer Position
2. **Entity-Detail-Pages:** `customFields`-Array aus Response auslesen und dynamisch rendern
- Pro Feldtyp: Text-Input, Textarea, Number-Input, Date-Picker, Select, Multi-Select, Checkbox, URL-Input
3. **Entity-Formulare:** Custom Fields im Erstellen/Bearbeiten-Formular einbinden
- `PUT /custom-fields/:entityId/values` nach Entity-Speichern aufrufen
- `isRequired` client-seitig validieren
4. **API-Aufrufe:** `GET /custom-fields?entityType=PERSON` fuer Feld-Definitionen, `PUT/GET /custom-fields/:entityId/values` fuer Werte
Alle 4 Punkte wurden im Frontend umgesetzt und deployed (Commit `aaedf68`).
---
## 2026-03-12 | Frontend: Phase 2.1 Custom Fields — Frontend-Integration
### Was wurde umgesetzt
Die komplette Frontend-Integration fuer Custom Fields ist implementiert und auf dem Server deployed.
#### Neue Dateien (2 Dateien)
```
packages/frontend/src/crm/
CustomFieldsDisplay.tsx -- Read-only Anzeige von Custom Fields in Detail-Pages
CustomFieldsForm.tsx -- Editierbare Custom Fields in Entity-Formularen
```
#### Geaenderte Dateien (10 Dateien)
| Datei | Aenderung |
|-------|-----------|
| `types.ts` | Neue Typen: `CustomFieldEntityType`, `CustomFieldType`, `CustomFieldDef`, `CustomFieldValue`, `CustomFieldOption`, Payload-Interfaces. `customFields?: CustomFieldValue[]` zu Contact/Company/Deal hinzugefuegt. |
| `api.ts` | `customFieldsApi`-Objekt mit 7 Methoden: listDefs, getDef, createDef, updateDef, deleteDef, getValues, setValues |
| `hooks.ts` | 6 neue Hooks: `useCustomFieldDefs`, `useCreateCustomFieldDef`, `useUpdateCustomFieldDef`, `useDeleteCustomFieldDef`, `useCustomFieldValues`, `useSetCustomFieldValues`. Query-Key-Factory `crmKeys.customFields`. |
| `settings/CrmSettingsPage.tsx` | Neuer Tab "Eigene Felder" mit `CustomFieldsConfig`-Komponente (~490 Zeilen): Entity-Typ-Filter, Add/Edit-Formular, Options-Editor fuer DROPDOWN/MULTI_SELECT, Sortierung, Loeschen mit Warnung. |
| `contacts/ContactDetailPage.tsx` | `CustomFieldsDisplay` nach Notizen-Sektion eingebunden |
| `companies/CompanyDetailPage.tsx` | `CustomFieldsDisplay` nach Notizen-Sektion eingebunden |
| `deals/DealDetailPage.tsx` | `CustomFieldsDisplay` nach Notizen-Sektion eingebunden |
| `contacts/ContactFormModal.tsx` | `CustomFieldsForm` + `useSetCustomFieldValues` integriert, `saveCustomFields` in onSuccess-Handlers |
| `companies/CompanyFormModal.tsx` | Gleiche Integration wie ContactFormModal |
| `deals/DealFormModal.tsx` | Gleiche Integration wie ContactFormModal |
### Architektur-Entscheidungen
1. **Zwei getrennte Komponenten**: `CustomFieldsDisplay` (read-only, Detail-Pages) und `CustomFieldsForm` (editierbar, Formulare) — saubere Trennung von Anzeige und Bearbeitung.
2. **Ref-basierter State in Formularen**: `customFieldValuesRef` statt useState, um unnoetige Re-Renders zu vermeiden. Werte werden erst beim Submit ausgelesen.
3. **Post-Save-Pattern**: Custom Fields werden NACH dem Entity-Save gespeichert (`PUT /custom-fields/:entityId/values`), da bei Create die Entity-ID erst aus der Response kommt.
4. **DROPDOWN Fallback**: `CustomFieldValue` liefert keine Options-Liste (nur Definitionen haben sie). DROPDOWN rendert daher als Text-Input. Verbesserung: Options aus Definitionen nachladen.
### Unterstuetzte Feldtypen (alle 8)
| Typ | Display (Detail) | Form (Formular) |
|-----|-------------------|------------------|
| TEXT | String | `<input type="text">` |
| TEXTAREA | Pre-wrap String | `<textarea>` |
| NUMBER | Locale-formatiert (de-DE) | `<input type="number">` |
| DATE | Formatiert (dd.MM.yyyy) | `<input type="date">` |
| CHECKBOX | "Ja" / "Nein" | `<input type="checkbox">` |
| URL | Klickbarer Link | `<input type="url">` |
| DROPDOWN | String | `<input type="text">` (Fallback) |
| MULTI_SELECT | Farbige Badges | Tag-Input mit Enter-to-Add |
### Admin-Bereich (CRM Einstellungen > Eigene Felder)
- **Entity-Typ-Filter**: Buttons fuer Kontakte/Unternehmen/Vorgaenge
- **Feld hinzufuegen**: Label, Feldtyp (Dropdown), Pflichtfeld-Toggle
- **Options-Editor**: Fuer DROPDOWN und MULTI_SELECT — dynamische Wert/Label-Paare
- **Inline-Bearbeitung**: Label, Pflichtfeld, Options aendern
- **Sortierung**: Hoch/Runter-Buttons fuer Position
- **Loeschen**: Mit Warnung ueber Cascading (alle gespeicherten Werte werden geloescht)
### Deployment-Notiz
Das Docker-Volume `/app/node_modules` im CRM-Container cached den alten Prisma-Client. Bei Schema-Aenderungen muss der Container mit `-V` Flag neu erstellt werden:
```bash
docker compose -f docker-compose.yml -f docker-compose.crm.yml up -d crm --force-recreate -V
```
### Offene Punkte / Verbesserungen
- [ ] DROPDOWN/MULTI_SELECT im Formular: Options aus Feld-Definitionen laden statt Freitext-Fallback
- [ ] `isRequired` client-seitig validieren (Flag wird geliefert, Validierung noch nicht implementiert)
- [ ] Drag & Drop fuer Position-Sortierung (aktuell: Hoch/Runter-Buttons)