feat: Interviews, Mail-Papierkorb, Kontaktart

Drei Aenderungen aus dem Alltagsgebrauch:

- Der Kalender heisst jetzt "Interviews" - dafuer wird er benutzt. Der Wert in
  ViewState wandert mit, damit Menue und Kopfzeile nicht auseinanderlaufen.
  Sichtbare Reste ("Kalenderfarbe") heissen jetzt Terminfarbe.

- Mails haben einen Papierkorb, der unter dem Menuepunkt aufklappt. Loeschen
  heisst dabei ausschliesslich: im CRM. Im Postfach crm@perinco.de bleibt die
  Mail unberuehrt - Schreibrechte darauf hat die Anwendung nicht. Damit der
  Delta-Abgleich geloeschte Mails nicht wieder einliest, bleibt nach dem Leeren
  eine leere Zeile als Merker stehen (crm_purged); runMailSync() ueberspringt
  alles, was im CRM geloescht ist. Zurueckholen und Leeren darf jeder
  Angemeldete, Leeren nach einer Warnung.

- Der Kontaktstatus (Neu .. Verloren) wird zur Kontaktart: Recruiter, Partner,
  Endkunde. Die Spalte heisst jetzt kind, weil "Status" das Feld falsch
  benannte. migrateLeadKind() stellt bestehende Datenbanken um und setzt alle
  vorhandenen Kontakte auf Recruiter - welche Art jemand ist, sagt der alte
  Status nicht (so mit dem Nutzer entschieden).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sascha Wolf
2026-08-18 11:12:49 +02:00
co-authored by Claude Opus 5
parent 025390e18a
commit 8741a9ae0c
39 changed files with 719 additions and 199 deletions
+3 -3
View File
@@ -85,7 +85,7 @@ export const authApi = {
}),
me: () => request<{ user: AppUser }>('/auth/me'),
/**
* Eigene Kalenderfarbe und eigenes Foto setzen - ohne Adminrechte.
* Eigene Terminfarbe und eigenes Foto setzen - ohne Adminrechte.
* null setzt zurueck: Farbe auf die Palettenfarbe, Foto auf die Initiale.
*/
updateMe: (input: { color?: string | null; avatar?: string | null }) =>
@@ -113,7 +113,7 @@ export interface UserInput {
export const usersApi = {
list: () => request<AppUser[]>('/users'),
/**
* Aktive Benutzer - fuer jeden Angemeldeten abrufbar. Der Kalender braucht
* Aktive Benutzer - fuer jeden Angemeldeten abrufbar. Die Terminansicht braucht
* die Liste fuer @-Mentions, Teilnehmer und Farben, auch fuer Rolle "user".
*/
directory: () => request<AppUser[]>('/users/directory'),
@@ -197,7 +197,7 @@ export const opportunitiesApi = {
remove: (id: number) => request<{ ok: true }>(`/opportunities/${id}`, { method: 'DELETE' }),
};
// ---------- Kalender ----------
// ---------- Interviews (Termine) ----------
export interface EventInput {
title: string;