# INSIGHT MVP - Aenderungsprotokoll ## Stand: 2026-03-15 ### Aktueller Sprint: CRM Phase 3 + Stammdaten + Reporting + Hilfesystem + KI-Einstellungen (Feature-Branch: feature/crm-service) --- ### Aenderungen 2026-03-15 (20): KI-Einstellungen über Admin-UI konfigurierbar #### Feature: Anthropic API-Key über Admin-UI setzen **Problem**: `ANTHROPIC_API_KEY` war nur per `.env`-Datei setzbar — Admins ohne Server-Zugang konnten den KI-Chat nicht aktivieren. **Backend (Core Service)** - `src/core/settings/settings.controller.ts` — 2 neue Endpoints: - `GET /settings/ai-config` — gibt `{ configured: boolean }` zurück (Key wird niemals zurückgesendet) - `POST /settings/ai-config` — speichert Key Base64-kodiert in Redis unter `platform_ai_config`; leerer String löscht den Key (@Roles PLATFORM_ADMIN) - `src/core/help/help.service.ts` — RedisService injiziert; Key wird per `getApiKey()` dynamisch geladen (Env-Variable hat Vorrang, 60s In-Memory-Cache); Cache-Invalidierung bei 401-Fehler - `src/core/help/help.module.ts` — RedisModule importiert **Frontend** - `src/admin/AdminAiSettingsPage.tsx` (neu) — Admin-Seite mit Status-Anzeige, Password-Input, Speichern/Entfernen - `src/admin/AdminLayout.tsx` — Tab "KI-Einstellungen" ergänzt - `src/shell/App.tsx` — Route `/admin/ai-settings` + Import ergänzt - `src/components/HelpPanel/HelpPanel.tsx` — `useQuery(['settings', 'ai-config'])`: wenn nicht konfiguriert → Hinweis mit Link zu Admin-Seite statt Chat-Input **Sicherheit**: GET gibt niemals den Key zurück. Base64-Kodierung (konsistent mit Projektstil). Backward-Kompatibilität: `ANTHROPIC_API_KEY` in `.env` hat weiterhin Vorrang. --- ### Aenderungen 2026-03-15 (19): Stammdaten, CRM Reporting, Hilfesystem #### Feature 1: Stammdaten (Master Data) **Backend (Core Service)** - `prisma/core.schema.prisma` — 5 neue Modelle: `Department`, `Location`, `CostCenter`, `JobTitle`, `SkillCategory` (Tabellen: departments, locations, cost_centers, job_titles, skill_categories) - `src/core/master-data/master-data.service.ts` — CRUD-Service für alle 5 Stammdaten-Entitäten - `src/core/master-data/master-data.controller.ts` — REST-Controller mit Public-Endpunkten (Dropdowns) + Admin-Endpunkten (@Roles('PLATFORM_ADMIN')) - `src/core/master-data/master-data.module.ts` — NestJS-Modul - `src/app.module.ts` — MasterDataModule registriert **Frontend** - `src/admin/AdminMasterDataPage.tsx` — Admin-Seite mit 5 Tabs, inline Edit/Delete/Create - `src/admin/AdminLayout.tsx` — Tab "Stammdaten" ergänzt - `src/shell/App.tsx` — Route `/admin/master-data` ergänzt **Deployment-Hinweis**: `prisma migrate deploy` auf Server erforderlich + Rebuild core-service + frontend --- #### Feature 2: CRM Reporting **Backend (CRM Service)** - `src/deals/deals.service.ts` — Methode `getStats()`: Win/Loss-Rate, Umsatz, Avg-Deal-Value, LostByReason, MonthlyTrend (12 Monate) - `src/deals/dto/stats-query.dto.ts` — `StatsQueryDto` mit Period-Enum (MONTH/QUARTER/YEAR) - `src/deals/deals.controller.ts` — GET `/deals/stats` Endpunkt - `src/activities/activities.service.ts` — Methode `getStats()`: Aktivitäten nach Typ, Erledigungsrate, Upcoming Tasks - `src/activities/activities.controller.ts` — GET `/activities/stats` Endpunkt **Frontend** - `package.json` — `recharts ^2.12.0` als Dependency - `src/crm/types.ts` — Interfaces `DealStats`, `ActivityStats`, `MonthlyTrendEntry`, `LostByReasonEntry`, `ActivityStatsByType` - `src/crm/api.ts` — `dealStatsApi.get()`, `activitiesApi.getStats()` ergänzt - `src/crm/hooks.ts` — `useDealStats()`, `useActivityStats()` Hooks - `src/crm/reports/ReportsPage.tsx` — Reporting-Seite mit Period-Selector, Deal/Aktivitäts-Tabs, LineChart/BarChart/PieChart (recharts) - `src/shell/App.tsx` — Route `/crm/reports` - `src/shell/AppLayout.tsx` — Sidebar-Link "Reports" nach Kanban --- #### Feature 3: Hilfesystem (KI-Chat + Tooltips + Panel) **Backend (Core Service)** - `package.json` — `@anthropic-ai/sdk ^0.37.0` - `src/config/env.validation.ts` — `ANTHROPIC_API_KEY` (optional) - `src/core/help/help.service.ts` — Claude Haiku Integration, Chat-Methode mit System-Prompt - `src/core/help/help.controller.ts` — POST `/help/chat` - `src/core/help/help.module.ts` — NestJS-Modul - `src/app.module.ts` — HelpModule registriert **Frontend** - `src/components/HelpTooltip/HelpTooltip.tsx` + `index.ts` — Hover-Tooltip mit ❓-Icon - `src/components/HelpPanel/HelpPanel.tsx` + `index.ts` — Side-Panel mit Kontexthilfe + KI-Chat - `src/shell/AppLayout.tsx` — ❓-Button in Topbar + HelpPanel-Integration --- ### Aenderungen 2026-03-13 (18): Experten-Profil PDF-Export — 3 weitere Korrekturen #### Backend (Core Service) - `expert-profile/expert-profile.service.ts` — `getExportData()`: Anhänge jetzt inkludiert (`attachments: { orderBy: { createdAt: 'asc' } }`) - `expert-profile/profile-export.service.ts` — PDF-Export: - Neues `ExportAttachment` Interface + `attachments[]` in `ExportData` - Tasks: Bullet `•` wird nur noch hinzugefügt, wenn Original-Zeile bereits ein Aufzählungszeichen (`•`, `\u2022`) oder Nummerierung (`1.`) enthält — kein spurious Bullet für Plaintext-Zeilen - Zertifizierungen: Schriftgröße reduziert (Titel 10pt→9pt, Aussteller 9pt→8pt, Abstände angepasst) — passt jetzt zur linken Spalte - Zertifizierungen: Timeline-Linienlänge 40→32px - Anhänge: Bild-Anhänge (image/jpeg, image/png, etc.) werden als zusätzliche Seiten ans PDF angehängt (Überschrift "ANLAGE: dateiname" + Bild; PDFs + andere Formate werden übersprungen) - `expert-profile/profile-export.service.ts` — DOCX-Export: - Tasks: Gleiche Bullet-Fix-Logik (nur Bullet wenn Original-Zeile Bullet/Nummer hat) #### TypeScript - `npx tsc --noEmit` in packages/core-service: 0 Fehler #### Deployment-Hinweis (Schritt 18) - Rebuild + Restart: nur core-service --- ### Aenderungen 2026-03-13 (17): Experten-Profil PDF-Export — 5 Korrekturen #### Backend (Core Service) - `expert-profile/profile-export.service.ts` — PDF-Export verbessert: - Neue Helper-Methoden `stripMarkdown()` und `normalizeTaskLine()` - Zeitraum fett (Helvetica-Bold, #555555) - Firmenname + Branche fett (Helvetica-Bold, #333333) - Tasks: Markdown-Marker (**bold**, *italic*, __u__) werden vor Ausgabe entfernt - Sprachen/Erfahrung: Abstand 14px → 11px, Sektion-Gap 8px → 4px - Zertifizierungen in rechte Spalte verschoben (nach Berufserfahrung) - Return-Typ: `Promise<{ buffer, firstName, lastName }>` (war: `Promise`) - `expert-profile/profile-export.service.ts` — DOCX analog angepasst: - Zeitraum + Firma fett; normalizeTaskLine() fuer Tasks; Zertifizierungen in rightParagraphs - `expert-profile/expert-profile.controller.ts`: - PDF: `Vorname_Nachname_CV.pdf`, DOCX: `Vorname_Nachname_CV.docx` - RFC-5987 `filename*=UTF-8''...` fuer Umlaut-Dateinamen #### TypeScript - `npx tsc --noEmit` in packages/core-service: 0 Fehler #### Deployment-Hinweis (Schritt 17) - Rebuild + Restart: nur core-service --- ### Aenderungen 2026-03-13 (16): Global Admin — Login-Screen-Branding (Hintergrund + Logo) #### Backend (Core Service) - `settings/settings.controller.ts` — `GET /settings/branding` + `POST /settings/branding` erweitert: - 4 neue Felder: `loginBgType` ('gradient'|'solid'|'image'), `loginBgColor1`, `loginBgColor2`, `loginBgImage` - `loginBgImage` Groeßen-Validierung: max. 2MB - `loginBgType` Enum-Validierung: nur erlaubte Werte werden gespeichert - Rueckwaertskompatibel: bestehende Redis-Daten ohne neue Felder liefern `null`-Defaults #### Frontend - `admin/AdminCustomizePage.tsx` — Neuer Card-Block "Login-Hintergrund": - Typ-Toggle: Farbverlauf / Einfarbig / Hintergrundbild - Farbverlauf: Zwei Farbpicker (Von/Bis) mit Hex-Eingabe - Einfarbig: Ein Farbpicker mit Hex-Eingabe - Hintergrundbild: Datei-Upload (max. 2MB, nur Bilder), Entfernen-Button - Live-Vorschau: Mini-Login-Mockup (200x120px) mit aktuellem Hintergrund und Logo - `auth/LoginPage.tsx` — Dynamisches Branding: - `useQuery(['settings', 'branding'])` — oeffentlicher Endpoint, kein Auth noetig - `useMemo` → `containerStyle`: leitet CSS `background` aus `loginBgType` ab - Logo-Anzeige: zeigt `` mit `branding.logo` statt hardcoded "INSIGHT"-Text - `auth/LoginPage.module.css` — Neue Klasse `.logoImage` (max-width 180px, object-fit contain) #### TypeScript - `npx tsc --noEmit` in packages/frontend: 0 Fehler - `npx tsc --noEmit` in packages/core-service: 0 Fehler #### Deployment-Hinweis (Schritt 16) - Rebuild + Restart: core-service (Backend) und frontend - Kein Datenbankschema-Aenderung, keine Migration noetig (nur Redis) --- ### Aenderungen 2026-03-13 (15): Experten-Profil – BulletEditor Fett/Kursiv/Unterstrichen + Aufgaben-Anzeige #### Frontend - `profile/sections/ProjectModal.tsx` — BulletEditor: Inline-Formatierungen - Neue Hilfsfunktion `blWrapFormat()` auf Modul-Ebene: Wraps/Unwraps markierten Text mit Marker-Paar; kein Text markiert → Marker-Paar einsetzen (Cursor dazwischen); Text bereits gewrapped → aushakenlen - Toolbar: Neuer Button "B" (Fett, `**text**`), "I" (Kursiv, `*text*`), "U" (Unterstrichen, `__text__`) - Keyboard-Shortcuts: Strg+B, Strg+I, Strg+U (Mac: Cmd+B/I/U) - `profile/sections/ProjectsSection.tsx` — Aufgaben-Anzeige mit Markdown-Renderer - Neue Funktion `renderInline()`: wandelt **bold**, *italic*, __underline__ Marker in React-Elemente um (regex-basiert, kein XSS, kein dangerouslySetInnerHTML) - Neue Komponente ``: Rendert Aufgaben-Text Zeile fuer Zeile mit Bullet-Punkt-Layout, nummerierter Liste, Einrueckung und Inline-Formatierung - Projekt-Listenelement: zeigt Aufgaben-Text unterhalb von Taetikeit/Firma an (separator border-top) — nur wenn Aufgaben vorhanden - Neues Layout `entryItemExpanded + entryItemRow` (column statt row wenn Aufgaben vorhanden) - `profile/ExpertProfileTab.module.css` — Neue Klassen: `.bulletBtnBold`, `.bulletBtnItalic`, `.bulletBtnUnderline`; `.entryItemExpanded`, `.entryItemRow`, `.entryTasks`; `.richText`, `.richTextLine`, `.richTextBullet`, `.richTextNum`, `.richTextBlank` #### TypeScript - `npx tsc --noEmit` in packages/frontend: 0 Fehler #### Deployment-Hinweis (Schritt 15) - Rebuild + Restart: nur frontend --- ### Aenderungen 2026-03-13 (14): Experten-Profil – BulletEditor mit nummerierter Liste + Tab-Einrueckung #### Frontend - `profile/sections/ProjectModal.tsx` — BulletEditor erweitert: - Neuer Button "1. Liste": toggled nummerierte Liste (1. 2. 3.) ein/aus; konvertiert auch Bullet→Nummeriert und umgekehrt - Tab-Taste: rueckt aktuelle Zeile um 2 Leerzeichen ein; Shift+Tab nimmt sie wieder raus - Enter in nummerierter Liste: naechste Zeile erhaelt automatisch naechste Zahl (z.B. "3. " → "4. ") - Enter in leerer Listenelement: beendet die Liste (Bullet oder Nummeriert) - Enter beruecksichtigt Einrueckung (eingerueckte " • " → naechste Zeile ebenfalls " • ") - Modul-Level-Hilfsfunktion `blLineAt()`: parst Zeile an Cursor-Position - Toolbar-Hinweistext: "Tab = einruecken · Shift+Tab = ausruecken" - `profile/ExpertProfileTab.module.css` — `.bulletToolbarSep` (vertikale Linie), `.bulletToolbarHint` (Hinweistext) #### Deployment-Hinweis (Schritt 14) - Rebuild + Restart: nur frontend --- ### Aenderungen 2026-03-13 (13): Experten-Profil – Bullet-Editor fuer Aufgaben + Popup-Backdrop deaktiviert #### Frontend - `components/Modal.tsx` — `onClick={onClose}` vom Overlay-div entfernt: Popups schliessen sich nicht mehr durch Klick neben das Popup (betrifft alle Modal-Instanzen im Projekt) - `components/Drawer.tsx` — Gleiches: Drawer schliesst sich nicht mehr durch Klick auf den Backdrop - `profile/sections/ProjectModal.tsx` — Neue lokale `BulletEditor`-Komponente (keine externe Library): Toolbar mit "☰ Liste"-Button (toggled `• ` am Zeilenanfang ein/aus), automatische Aufzaehlungsfortsetzung beim Enter-Druck, leere Bullet-Zeile `• ` + Enter beendet die Liste; ersetzte die einfache `