diff --git a/README.md b/README.md index f8109ef..23893fe 100644 --- a/README.md +++ b/README.md @@ -576,6 +576,11 @@ Knoten ziehen fixiert ihn (grüner Punkt), Doppelklick löst die Fixierung. Über *Verbindung erstellen* zwei Kontakte anklicken, um eine Kante anzulegen; Esc bricht ab. Die Ansicht respektiert Suche und Statusfilter. +Die Art einer bestehenden Verbindung lässt sich sowohl im Kontaktdialog als auch +in der Seitenleiste der Netzwerkansicht direkt umstellen +(`PATCH /api/connections/:id`, ohne Speichern-Knopf). Vorher musste man sie +löschen und neu anlegen. + Ein Klick auf einen Knoten hebt ihn samt Nachbarn hervor und blendet den Rest auf 22 % Deckkraft ab. Ein Klick auf eine **freie Fläche** hebt die Auswahl wieder auf - der Ausgangszustand der Ansicht. Damit das Verschieben nicht diff --git a/docs/07-anleitung-benutzer.md b/docs/07-anleitung-benutzer.md index 8674396..c5c1b67 100644 --- a/docs/07-anleitung-benutzer.md +++ b/docs/07-anleitung-benutzer.md @@ -482,6 +482,12 @@ Drei Ansichten, davon eine besondere: Ein Klick auf eine Karte öffnet den Kontakt zum Bearbeiten - mit Foto, Anschrift, Art, Zuständigkeit, Tags, Notizen und den Verbindungen zu anderen Kontakten. +Bei den **Verbindungen** steht die Art (Kollege, Vorgesetzter, Kunde, …) als +Auswahlfeld neben dem Namen. Umstellen genügt: Die Änderung wird sofort +gespeichert, unabhängig vom Knopf *Speichern* darunter - eine Verbindung ist ein +eigener Eintrag und nicht Teil des Kontaktformulars. Zum Löschen bleibt das +Kreuz rechts. + Die **Art** sagt, mit wem man es zu tun hat: **Recruiter**, **Partner** oder **Endkunde**. Früher stand an dieser Stelle ein Vertriebsstatus (Neu, Kontaktiert, …); der sagte über den Kontakt selbst nichts. Bei der Umstellung am @@ -522,6 +528,10 @@ setzt ihn fest (grüner Punkt), Doppelklick löst ihn wieder. Über *Verbindung erstellen* zwei Kontakte anklicken, um eine Verbindung anzulegen; `Esc` bricht ab. Suche und Artfilter wirken auch hier. +Im Feld rechts, das nach dem Klick auf einen Kontakt erscheint, steht unter +jeder Verbindung deren **Art** als Auswahlfeld - umstellen genügt, gespeichert +wird sofort. + Ein Klick auf einen Knoten hebt ihn und seine Nachbarn hervor, alles andere wird blass. **Ein Klick auf eine freie Stelle nimmt die Hervorhebung wieder zurück** - das Bild sieht danach aus wie beim Wechsel in die Netzwerkansicht. Verschieben diff --git a/docs/09-quellcode.md b/docs/09-quellcode.md index 9ca2d33..6f449ae 100644 --- a/docs/09-quellcode.md +++ b/docs/09-quellcode.md @@ -318,8 +318,8 @@ Warum genau diese Konstanten festgelegt sind, steht in | `components/acquisition/acquisitionUi.tsx` | `fieldClass` (abgesetzte Felder) und `OptionSelect` - zeigt einen Wert, der nicht mehr in der Liste steht, als solchen; `alwaysOffer` hält den eigenen Namen für *Von* immer wählbar. *Anbieter* nutzt es nicht: Freitext mit ``. Dazu `ConsultantSelect` (mehrere Berater: Auswahlfeld hängt an, Plaketten nehmen weg) und `ConsultantList` für die Anzeige in der Liste | | `components/settings/AcquisitionSettings.tsx` | Reiter *Einstellungen → Akquise*: die vier Auswahllisten pflegen | | `components/leads/leadUi.tsx` | `inputClass`, `labelClass` (Beschriftung als eigene Zeile), `labelTextClass` + `labelRowClass` (Zeile mit Knopf rechts, z. B. Diktat - `min-h-7` haelt sie so hoch wie den Knopf, damit Felder in Nachbarspalten auf einer Linie beginnen), `KindBadge`, `Avatar`, Farben der Kontaktart | -| `components/leads/LeadModal.tsx` | Kontaktformular. Beim Neuanlegen ist der angemeldete Benutzer *Zuständig* (`useAuth()`, Rückfallebene `users[0]`) - beim Bearbeiten bleibt die gespeicherte Zuständigkeit stehen. Neben dem LinkedIn-Feld holt *Foto* das Profilbild; beim Verlassen des Feldes geschieht das einmal je Adresse von selbst, aber nur solange noch kein Bild gesetzt ist (`triedProfiles`) - ein hochgeladenes Foto wird nie überschrieben. Fehler des automatischen Versuchs stehen als Hinweis unter dem Feld, nur der Klick auf *Foto* meldet sich als Toast | -| `components/leads/LeadNetwork.tsx` | Netzwerkdiagramm (d3-force). Ein Klick auf leere Fläche hebt die Auswahl auf, das Diagramm ist danach wieder so hell wie beim Wechsel in die Ansicht; ein Ziehen des Hintergrunds (mehr als 4 px) verschiebt nur und lässt die Auswahl stehen. Knoten stoppen das `pointerdown`, ihre Klicks erreichen den Hintergrund also nicht | +| `components/leads/LeadModal.tsx` | Kontaktformular. Beim Neuanlegen ist der angemeldete Benutzer *Zuständig* (`useAuth()`, Rückfallebene `users[0]`) - beim Bearbeiten bleibt die gespeicherte Zuständigkeit stehen. Neben dem LinkedIn-Feld holt *Foto* das Profilbild; beim Verlassen des Feldes geschieht das einmal je Adresse von selbst, aber nur solange noch kein Bild gesetzt ist (`triedProfiles`) - ein hochgeladenes Foto wird nie überschrieben. Fehler des automatischen Versuchs stehen als Hinweis unter dem Feld, nur der Klick auf *Foto* meldet sich als Toast. In der Liste der Verbindungen ist die **Art** ein Auswahlfeld: die Änderung geht als `PATCH /api/connections/:id` sofort raus, ohne den Speichern-Knopf - eine Verbindung ist ein eigener Datensatz und hängt nicht am Formular | +| `components/leads/LeadNetwork.tsx` | Netzwerkdiagramm (d3-force). Ein Klick auf leere Fläche hebt die Auswahl auf, das Diagramm ist danach wieder so hell wie beim Wechsel in die Ansicht; ein Ziehen des Hintergrunds (mehr als 4 px) verschiebt nur und lässt die Auswahl stehen. Knoten stoppen das `pointerdown`, ihre Klicks erreichen den Hintergrund also nicht. In der Seitenleiste des gewählten Kontakts ist die Art jeder Verbindung umstellbar, genau wie im Kontaktdialog | | `components/leads/mailPool.ts` | `findMailPoolMatch()`, `diffFields()`, `isConflict()`, `MAIL_POOL_FIELDS` - Dublettenabgleich des Vorbereichs | | `components/leads/MailPoolLeads.tsx` | Ansicht „Aus Mails": Goldmarkierung, Abweichungen, Übernehmen, Sammelübernahme | | `components/leads/MailPoolMergeDialog.tsx` | Feldauswahl beim Ergänzen eines vorhandenen Kontakts | diff --git a/src/components/leads/LeadModal.tsx b/src/components/leads/LeadModal.tsx index fc5346e..3c7da55 100644 --- a/src/components/leads/LeadModal.tsx +++ b/src/components/leads/LeadModal.tsx @@ -119,6 +119,8 @@ export const LeadModal: React.FC = ({ const [newConnectionId, setNewConnectionId] = useState(''); const [newConnectionType, setNewConnectionType] = useState('Netzwerk'); const [isLinking, setIsLinking] = useState(false); + /** Verbindung, deren Art gerade gespeichert wird - sperrt nur diese Zeile. */ + const [changingConnectionId, setChangingConnectionId] = useState(null); const leadById = useMemo(() => new Map(leads.map((l) => [l.id, l])), [leads]); @@ -246,6 +248,24 @@ export const LeadModal: React.FC = ({ } }; + /* + * Die Art einer bestehenden Verbindung aendern. Das geht ohne Speichern-Knopf: + * die Verbindung haengt nicht am Formular, sondern ist ein eigener Datensatz - + * genau wie das Anlegen und das Entfernen daneben. + */ + const handleChangeConnectionType = async (id: number, type: ConnectionType) => { + setChangingConnectionId(id); + try { + await connectionsApi.update(id, { type }); + addToast('Verbindung geändert.', 'success'); + onSaved(); + } catch (err) { + addToast(err instanceof Error ? err.message : 'Ändern fehlgeschlagen.', 'error'); + } finally { + setChangingConnectionId(null); + } + }; + const handleRemoveConnection = async (id: number) => { try { await connectionsApi.remove(id); @@ -572,10 +592,31 @@ export const LeadModal: React.FC = ({

{leadFullName(other!)}

-

- {connection.type} - {other!.company ? ` · ${other!.company}` : ''} -

+
+ {/* + * Die Art ist hier direkt umstellbar - vorher musste man die + * Verbindung loeschen und neu anlegen, nur um "Kollege" in + * "Vorgesetzter" zu aendern. + */} + + {other!.company && ( + {other!.company} + )} +
+
+ + {/* Art direkt umstellbar - ohne den Umweg ueber Loeschen und neu Anlegen. */} + +