fix(akquise): Anbieter wieder als Freitext mit Vorschlaegen
Das Dropdown fiel dem Feld zur Last: neue Vermittler tauchen zu oft auf, als dass das Eintragen an einer gepflegten Liste haengen sollte. Anbieter ist wieder ein Textfeld, jetzt mit Vorschlagsliste aus den bisherigen Eintraegen - der zuletzt benutzte zuerst. In den Einstellungen bleiben die drei Listen "Von", "Kanal" und "Berater". dropProviderOptions() nimmt 'provider' aus dem ENUM der Optionstabelle und loescht die dort gepflegten Werte; die Anbieter der Akquise-Eintraege bleiben unberuehrt, sie stehen als Text in crm_acquisitions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
05cc261900
commit
23087a12fb
@@ -27,6 +27,8 @@ interface AcquisitionFormProps {
|
||||
editing: Acquisition | null;
|
||||
/** Inhalte der Dropdowns, gepflegt unter Einstellungen -> Akquise. */
|
||||
options: AcquisitionOptions;
|
||||
/** Schon benutzte Anbieter - das Feld bleibt Freitext. */
|
||||
providerSuggestions: string[];
|
||||
onSaved: () => void;
|
||||
onCancelEdit: () => void;
|
||||
}
|
||||
@@ -80,6 +82,7 @@ function toFormState(entry: Acquisition | null): FormState {
|
||||
export const AcquisitionForm: React.FC<AcquisitionFormProps> = ({
|
||||
editing,
|
||||
options,
|
||||
providerSuggestions,
|
||||
onSaved,
|
||||
onCancelEdit,
|
||||
}) => {
|
||||
@@ -252,14 +255,27 @@ export const AcquisitionForm: React.FC<AcquisitionFormProps> = ({
|
||||
onChange={(value) => set('sender', value)}
|
||||
onOpenSettings={openSettings}
|
||||
/>
|
||||
<OptionSelect
|
||||
id="acq-provider"
|
||||
label={ACQUISITION_FIELD_LABELS.provider}
|
||||
value={form.provider}
|
||||
options={options.provider}
|
||||
onChange={(value) => set('provider', value)}
|
||||
onOpenSettings={openSettings}
|
||||
/>
|
||||
{/* Anbieter bleibt Freitext: neue Vermittler tauchen zu oft auf, als dass
|
||||
das Eintragen an einer gepflegten Liste haengen sollte. Die
|
||||
Vorschlagsliste erspart das Ausschreiben bekannter Namen. */}
|
||||
<div>
|
||||
<label className={labelClass} htmlFor="acq-provider">
|
||||
Anbieter
|
||||
</label>
|
||||
<input
|
||||
id="acq-provider"
|
||||
list="acq-provider-vorschlaege"
|
||||
value={form.provider}
|
||||
onChange={(event) => set('provider', event.target.value)}
|
||||
placeholder="z. B. Hays"
|
||||
className={fieldClass}
|
||||
/>
|
||||
<datalist id="acq-provider-vorschlaege">
|
||||
{providerSuggestions.map((option) => (
|
||||
<option key={option} value={option} />
|
||||
))}
|
||||
</datalist>
|
||||
</div>
|
||||
<OptionSelect
|
||||
id="acq-channel"
|
||||
label={ACQUISITION_FIELD_LABELS.channel}
|
||||
|
||||
@@ -175,6 +175,7 @@ export const Acquisitions: React.FC<AcquisitionsProps> = ({ view = 'eingang', re
|
||||
<AcquisitionForm
|
||||
editing={editing}
|
||||
options={data?.options ?? EMPTY_ACQUISITION_OPTIONS}
|
||||
providerSuggestions={data?.provider_suggestions ?? []}
|
||||
onSaved={() => load(true)}
|
||||
onCancelEdit={() => setEditing(null)}
|
||||
/>
|
||||
|
||||
@@ -15,10 +15,13 @@ import {
|
||||
} from '../../types';
|
||||
|
||||
/*
|
||||
* Inhalte der Akquise-Dropdowns pflegen: "Von", "Anbieter", "Kanal", "Berater".
|
||||
* Inhalte der Akquise-Dropdowns pflegen: "Von", "Kanal", "Berater".
|
||||
*
|
||||
* Vier gleich aufgebaute Listen statt vier Sonderfaelle - die Felder verhalten
|
||||
* sich gleich, also sieht ihre Pflege auch gleich aus.
|
||||
* "Anbieter" steht bewusst nicht dabei - das Feld ist Freitext mit Vorschlaegen
|
||||
* aus den bisherigen Eintraegen.
|
||||
*
|
||||
* Gleich aufgebaute Listen statt Sonderfaelle - die Felder verhalten sich
|
||||
* gleich, also sieht ihre Pflege auch gleich aus.
|
||||
*
|
||||
* Umbenennen zieht die vorhandenen Akquise-Eintraege mit, Loeschen nicht: eine
|
||||
* Liste aufzuraeumen darf keine Daten aendern. Beide Antworten sagen, wie viele
|
||||
@@ -133,7 +136,6 @@ export const AcquisitionSettings: React.FC = () => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [drafts, setDrafts] = useState<Record<AcquisitionOptionField, string>>({
|
||||
sender: '',
|
||||
provider: '',
|
||||
channel: '',
|
||||
consultant: '',
|
||||
});
|
||||
@@ -219,10 +221,11 @@ export const AcquisitionSettings: React.FC = () => {
|
||||
<section className="rounded-2xl border-l-4 border-l-brand-500 border border-ink-200 bg-surface p-5">
|
||||
<h3 className="text-base text-ink-900">Auswahllisten der Akquise</h3>
|
||||
<p className="mt-1 text-xs text-ink-400">
|
||||
Diese vier Listen füllen die Dropdowns im Formular unter <em>Akquise</em>. Feste Auswahl
|
||||
statt Freitext, damit aus „Hays", „hays" und „Hays AG" nicht drei Anbieter werden.
|
||||
Pflegen darf jeder angemeldete Benutzer - wer beim Eintragen auf einen neuen Anbieter
|
||||
stößt, soll weiterarbeiten können.
|
||||
Diese drei Listen füllen die Dropdowns <em>Von</em>, <em>Kanal</em> und <em>Berater</em> im
|
||||
Formular unter <em>Akquise</em>. Pflegen darf jeder angemeldete Benutzer - wer beim
|
||||
Eintragen einen fehlenden Wert braucht, soll weiterarbeiten können. Das Feld
|
||||
<em> Anbieter</em> steht bewusst nicht hier: dort wird frei getippt, mit Vorschlägen aus
|
||||
den bisherigen Einträgen.
|
||||
</p>
|
||||
<p className="mt-2 text-xs text-ink-400">
|
||||
<strong>Umbenennen</strong> ändert die vorhandenen Akquise-Einträge mit.
|
||||
|
||||
+7
-5
@@ -253,16 +253,18 @@ export type OpportunityViewMode = 'grid' | 'list' | 'pipeline';
|
||||
/**
|
||||
* Felder der Akquise, die aus einer Auswahlliste kommen. Die Werte stehen in der
|
||||
* Datenbank (crm_acquisition_options) und werden unter Einstellungen -> Akquise
|
||||
* gepflegt - als Freitext waeren "Hays", "hays" und "Hays AG" drei Anbieter.
|
||||
* gepflegt.
|
||||
*
|
||||
* "Anbieter" ist ausdruecklich nicht dabei: dort wird frei getippt, mit
|
||||
* Vorschlaegen aus den bisherigen Eintraegen (`AcquisitionList.provider_suggestions`).
|
||||
*/
|
||||
export const ACQUISITION_OPTION_FIELDS = ['sender', 'provider', 'channel', 'consultant'] as const;
|
||||
export const ACQUISITION_OPTION_FIELDS = ['sender', 'channel', 'consultant'] as const;
|
||||
|
||||
export type AcquisitionOptionField = (typeof ACQUISITION_OPTION_FIELDS)[number];
|
||||
|
||||
/** Beschriftung der Felder - dieselbe in der Liste, im Formular und in den Einstellungen. */
|
||||
export const ACQUISITION_FIELD_LABELS: Record<AcquisitionOptionField, string> = {
|
||||
sender: 'Von',
|
||||
provider: 'Anbieter',
|
||||
channel: 'Kanal',
|
||||
consultant: 'Berater',
|
||||
};
|
||||
@@ -270,7 +272,6 @@ export const ACQUISITION_FIELD_LABELS: Record<AcquisitionOptionField, string> =
|
||||
/** Was in der jeweiligen Liste steht - als Hilfe in den Einstellungen. */
|
||||
export const ACQUISITION_FIELD_HINTS: Record<AcquisitionOptionField, string> = {
|
||||
sender: 'Personen, von denen Projekte kommen',
|
||||
provider: 'Vermittler und Portale, z. B. Hays',
|
||||
channel: 'Auf welchem Weg das Projekt kam',
|
||||
consultant: 'Eigene Berater, für die Projekte gesucht werden',
|
||||
};
|
||||
@@ -284,7 +285,6 @@ export type AcquisitionOptions = Record<AcquisitionOptionField, AcquisitionOptio
|
||||
|
||||
export const EMPTY_ACQUISITION_OPTIONS: AcquisitionOptions = {
|
||||
sender: [],
|
||||
provider: [],
|
||||
channel: [],
|
||||
consultant: [],
|
||||
};
|
||||
@@ -337,6 +337,8 @@ export interface AcquisitionList {
|
||||
counts: { eingang: number; archiv: number };
|
||||
/** Inhalte der Dropdowns; kommen mit, damit die Eingabe sie sofort hat. */
|
||||
options: AcquisitionOptions;
|
||||
/** Schon benutzte Anbieter, der zuletzt verwendete zuerst - "Anbieter" ist Freitext. */
|
||||
provider_suggestions: string[];
|
||||
entries: Acquisition[];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user