feat(akquise): Auswahllisten statt Freitext, Felder abgesetzt

"Von", "Anbieter", "Kanal" und "Berater" sind Dropdowns. Ihre Inhalte stehen in
crm_acquisition_options und werden im neuen Reiter Einstellungen -> Akquise
gepflegt. Freitext hat aus "Hays", "hays" und "Hays AG" drei Anbieter gemacht;
der Unique-Schluessel greift ueber die Kollation auch bei abweichender
Gross-/Kleinschreibung.

Eine Tabelle mit Feldkennzeichen statt vier Tabellen: die Felder verhalten sich
gleich, also ist jede weitere Liste ein Wert im ENUM statt einer neuen Route und
einer neuen Oberflaeche.

Zwei Entscheidungen dabei:

- Pflegen darf jeder Angemeldete, nicht nur ein Administrator. Eine Liste, die
  nur ein Admin ergaenzen kann, blockiert die Eingabe genau dann, wenn ein neuer
  Anbieter auftaucht.
- Die Eintraege halten den Text, keinen Fremdschluessel. Umbenennen zieht sie
  darum ausdruecklich mit (in einer Transaktion), Loeschen nicht: eine Liste
  aufzuraeumen darf keine Daten aendern. Ein Wert, der nicht mehr in der Liste
  steht, wird im Dropdown weiter angeboten und als solcher gekennzeichnet -
  sonst wuerde das Bearbeiten eines alten Eintrags ihn stillschweigend
  ueberschreiben.

Das Backend prueft beim Speichern eines Eintrags nur noch die Laenge und nicht
mehr die Zugehoerigkeit zur Liste - aus demselben Grund.

Dazu: die Felder der Akquise-Eingabe sind abgesetzt (getoente Flaeche,
deutlicherer Rahmen, beim Hineinklicken weiss). Auf der weissen Karte gingen sie
unter, und im Formular stehen bis zu fuenfzehn davon nebeneinander.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sascha Wolf
2026-08-18 12:13:21 +02:00
co-authored by Claude Opus 5
parent b8a78f609c
commit 05cc261900
14 changed files with 762 additions and 137 deletions
+29
View File
@@ -1,6 +1,9 @@
import type {
Acquisition,
AcquisitionList,
AcquisitionOption,
AcquisitionOptionField,
AcquisitionOptions,
AppUser,
CalendarEvent,
Lead,
@@ -245,6 +248,32 @@ export const acquisitionsApi = {
}),
};
/**
* Inhalte der Dropdowns "Von", "Anbieter", "Kanal" und "Berater". Pflegen darf
* jeder Angemeldete: eine Liste, die nur ein Administrator ergaenzen kann, wuerde
* die Eingabe genau dann blockieren, wenn ein neuer Anbieter auftaucht.
*/
export const acquisitionOptionsApi = {
list: () => request<AcquisitionOptions>('/acquisitions/options'),
create: (field: AcquisitionOptionField, value: string) =>
request<AcquisitionOption & { field: AcquisitionOptionField }>('/acquisitions/options', {
method: 'POST',
body: JSON.stringify({ field, value }),
}),
/** Umbenennen zieht die vorhandenen Akquise-Eintraege mit; `updated` sagt wie viele. */
update: (id: number, value: string) =>
request<AcquisitionOption & { field: AcquisitionOptionField; updated: number }>(
`/acquisitions/options/${id}`,
{ method: 'PATCH', body: JSON.stringify({ value }) }
),
/** Entfernt nur die Auswahl; `still_in_use` zaehlt die Eintraege, die den Wert behalten. */
remove: (id: number) =>
request<{ ok: true; still_in_use: number }>(`/acquisitions/options/${id}`, { method: 'DELETE' }),
};
// ---------- Interviews (Termine) ----------
export interface EventInput {