Commit graph

180 commits

Author SHA1 Message Date
Thomas Reitz
c8b25321e7 feat(core+frontend): Profilzugriff-Gruppen für Admin mit delegierten Berechtigungen
- Neue Prisma-Modelle ProfileAccessGroup + ProfileAccessGroupMember mit canView/canExport/canEdit
- Manuelle Migration 20260314_profile_access_groups
- ProfileAccessModule: CRUD-Endpoints für Gruppen und Mitglieder (nur PLATFORM_ADMIN)
- Neue Admin-Endpoints in ExpertProfileService/-Controller für alle Profil-Mutationen
- verifyOwnership mit skipCheck-Parameter für Admin-Bypass
- ExpertProfileTab + alle Section-Komponenten erhalten apiBase-Prop für Wiederverwendung
- AdminProfileAccessPage: Gruppen-Tab (CRUD) + Profile-Tab (alle User mit Aktionen)
- AdminProfileDetailPage: Profil eines beliebigen Users im Admin-Kontext bearbeiten
- Route /admin/profile-access + /admin/profiles/:userId + Nav-Tab Profilzugriff

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 10:47:36 +01:00
Thomas Reitz
f7736a6fca fix(core): Word-Export — Abstand zwischen linker und rechter Spalte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 10:16:45 +01:00
Thomas Reitz
1a222edb46 fix(core): Word-Export — Logo-Seitenverhältnis korrekt (tatsächliche Pixel-Dimensionen)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 10:12:09 +01:00
Thomas Reitz
8fc894c74c fix(core): Word-Export — jobTitle, Logo, Akzentfarbe und Firmenfußzeile
- Jobtitel aus Profil statt experiences[0].area unter dem Namen
- Platform-Logo aus Redis über Avatar einfügen
- Dominante Akzentfarbe dynamisch aus Logo extrahieren
- Firmen-Fußzeile aus Redis-Settings als DOCX-Footer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:43:29 +01:00
Thomas Reitz
196515daa8 fix(core): PDF-Export — Titel aus jobTitle-Feld statt erster Erfahrung
- getExportData(): jobTitle zu den selektierten User-Feldern hinzugefuegt
- ExportData-Interface: jobTitle: string | null ergaenzt
- PDF: Unter dem Namen wird jetzt data.jobTitle angezeigt statt
  profile.experiences[0].area

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:35:45 +01:00
Thomas Reitz
382beab9c3 feat(core): PDF-Export — Akzentfarbe dynamisch aus Branding-Logo extrahiert
- extractDominantColor(): 20x20 Resize via sharp, Alpha gegen Weiss flatten,
  alle gesaettigten Pixel (nicht weiss/schwarz/grau, range > 35) mitteln
- Ergebnis wird als accentColor fuer Timeline-Linien, Ueberschriften,
  Skill-Chips usw. verwendet
- Fallback auf #009688 wenn kein Logo hinterlegt oder keine Farbe extrahierbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:27:41 +01:00
Thomas Reitz
f5d83dc1c3 fix(core): PDF-Export — Footer-Leerseite behoben und Logo ueber Profilfoto
- Footer: doc.page.margins.bottom temporaer auf 0 gesetzt beim Footer-Zeichnen
  verhindert PDFKit Auto-Pagination (footerTextY > maxY wuerde sonst
  eine leere zweite Seite erzeugen)
- Logo: Platform-Branding-Logo (aus Redis platform_branding_logo) wird oben
  in der linken Spalte ueber dem Profilfoto gerendert (fit 180x50px)
- Firmendaten + Branding parallel via Promise.all aus Redis geladen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:20:25 +01:00
Thomas Reitz
46ced98bf4 feat(core+frontend): Firmendaten im Admin + PDF-Fusszeile
Backend:
- GET/POST /settings/company (Redis-Key platform_company_settings)
  Felder: name, street, postalCode, city, phone, email, website
- ProfileExportService: RedisService injiziert, laedt Firmendaten vor PDF-Erzeugung
- PDF-Footer: Trennlinie + kompakte Zeile mit allen Firmendaten auf jeder Seite
  (bufferPages=true, switchToPage-Loop vor doc.end())

Frontend:
- AdminCompanyPage: Formular mit Vorschau der Fusszeile
- AdminLayout: neuer Tab 'Firmendaten'
- App.tsx: Route /admin/company

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:07:42 +01:00
Thomas Reitz
1d4894b637 fix(core): PDF-Export — Zertifizierungen in linke Spalte verschoben
- ZERTIFIZIERUNGEN von rechter Spalte in linke Spalte verschoben
  (nach ERFAHRUNG, vor FÄHIGKEITEN)
- Textbreite auf leftColWidth (certContentWidth = leftColWidth - 14) angepasst
- Timeline-Linie dynamisch (certEntryStartY gespeichert, Linie nach Content)
- Alte rechte-Spalte-Sektion entfernt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 08:49:25 +01:00
Thomas Reitz
f8aed00645 fix(core): PDF-Export — Abschnittslinien bis zum Spaltenende und Titel angepasst
- pdfSectionTitle: Linie zieht sich jetzt ueber die volle Spaltenbreite (width-Parameter)
  statt nur bis zum Textende
- Titel 'BERUFSERFAHRUNG' umbenannt in 'BERUFSERFAHRUNG / PROJEKTE'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 08:46:19 +01:00
Thomas Reitz
ed24c061c4 fix(core): PDF-Export — Timeline-Linien korrekt und Faehigkeiten in linke Spalte
- BERUFSERFAHRUNG: Timeline-Linie wird jetzt NACH dem Content gezeichnet
  (entryStartY gespeichert, Linie von entryStartY+8 bis yRight-4)
  Damit stimmt die Laenge exakt mit der tatsaechlichen Eintraghoehe ueberein
- Seitenumbruch-Flag (pageBreakOccurred): Linie wird nicht gezeichnet wenn
  der Content ueber eine Seite hinausgeht
- FAEHIGKEITEN: aus dem full-width Bereich am Seitenende entfernt und in die
  linke Spalte nach ERFAHRUNG verschoben (kleinere Chips: 7pt, 16px, 5px Pad)
- Alte full-width FAEHIGKEITEN-Sektion entfernt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 22:08:18 +01:00
Thomas Reitz
41d944312c fix(core): PDF-Export Icons kleiner (12->9px) und besser positioniert
- iconSize 12 -> 9px
- iconTextOffset 20 -> 14px (kompakter)
- Alle Icons gleichmaessig bei y+1 positioniert (sauberes vertikales Alignment mit 8pt Text)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 21:39:33 +01:00
Thomas Reitz
927de0a809 fix(core): PDF-Export Zeitraum groesser und fetter (8pt -> 10pt)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 21:35:38 +01:00
Thomas Reitz
3d486e0541 fix(core): PDF-Export — Bullets, Zertifizierungen, Bild-Anhaenge
- Tasks: Bullet-Praefix nur fuer Zeilen mit echtem Aufzaehlungszeichen (kein spurious Bullet bei Plaintext)
- Zertifizierungen: Schriftgroesse reduziert (Titel 10->9pt, Aussteller 9->8pt) und Timeline-Linie gekuerzt
- Anhaenge: Bild-Anhaenge werden als zusaetzliche Seiten ans PDF angehaengt
- ExportData-Interface + getExportData() um attachments[] erweitert
- Gleiche Bullet-Fix-Logik im DOCX-Export

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 21:33:01 +01:00
Thomas Reitz
a37942b37d fix: PDF-Export — Dateiname, Fettschrift, Zeichen, Abstaende, Zertifizierungen rechts
5 Korrekturen am Experten-Profil PDF-Export:
1. Dateiname: Vorname_Nachname_CV.pdf/.docx (RFC 5987 Umlaut-sicher)
2. Fettschrift: Zeitraum, Firmenname und Branche in Berufserfahrung
3. Zeichen-Darstellung: Markdown-Marker (**bold**/*italic*/__u__)
   werden aus Tasks-Text entfernt, doppelte Bullet-Praefix-Normalisierung
4. Abstaende: Sprachen 14->11px, Erfahrung 14->11px, Gap 8->4px
5. Zertifizierungen in rechte Spalte verschoben (nach Berufserfahrung)
   statt als Vollbreite-Sektion am Ende

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 21:20:43 +01:00
Thomas Reitz
c333cbfa4b feat: Login-Screen-Branding im Global Admin (Hintergrund + Logo)
Im Bereich Anpassungen (AdminCustomizePage) kann der Platform-Admin
nun den Login-Screen individuell gestalten:
- Hintergrundtyp: Farbverlauf, Einfarbig oder Hintergrundbild
- Farbverlauf: zwei Farbpicker (Von/Bis) mit Hex-Eingabe
- Hintergrundbild: Datei-Upload max. 2MB, Live-Vorschau
- Logo auf Login-Screen: wird automatisch aus dem Sidebar-Logo uebernommen

Backend: settings.controller.ts GET/POST /settings/branding um
loginBgType, loginBgColor1, loginBgColor2, loginBgImage erweitert.
LoginPage laedt Branding per oeffentlichem Endpoint (kein Auth), leitet
containerStyle per useMemo ab und zeigt Logo-Bild statt Hardcode-Text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 21:09:32 +01:00
Thomas Reitz
b872b7e708 feat(frontend): bullet-editor B/I/U-Formatierung + Aufgaben-Anzeige in Projektliste
BulletEditor (ProjectModal.tsx):
- blWrapFormat(): wrap/unwrap Selektion mit Marker-Paar (**/*/__),
  leere Selektion → leeres Marker-Paar mit Cursor dazwischen
- Buttons: B (Fett **), I (Kursiv *), U (Unterstrichen __)
- Shortcuts: Strg/Cmd + B/I/U in handleKeyDown

ProjectsSection.tsx:
- renderInline(): regex-basierter Inline-Markdown-Renderer ohne
  dangerouslySetInnerHTML — wandelt **bold**, *italic*, __underline__ um
- RichText-Komponente: rendert Aufgaben-Text mit Bullets, Nummernlisten,
  Einrueckung und Inline-Formatierung
- Projektliste zeigt Aufgaben unterhalb der Taetigkeitszeile an
  (nur wenn vorhanden, mit border-top als optischem Trenner)
- Layout-Anpassung: entryItemExpanded + entryItemRow fuer vertikales Layout

CSS: bulletBtnBold/Italic/Underline, entryItemExpanded/Row,
entryTasks, richText/Line/Bullet/Num/Blank

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 20:47:07 +01:00
Thomas Reitz
4f141b94e5 feat(frontend): bullet-editor – nummerierte Liste + Tab/Shift+Tab Einrueckung
- Neue Funktion blLineAt() auf Modul-Ebene: parst Zeile an Cursor-Position
  (Einrueckung, Bullet/Nummeriert, Zahl, Zeileninhalt) ohne Closure-Probleme
- Neuer Toolbar-Button "1. Liste": toggled nummerierte Liste (1./2./3.);
  wandelt Bullet→Nummeriert und Nummeriert→Bullet automatisch um
- Tab-Taste: fuegt 2 Leerzeichen am Zeilenanfang ein (Einrueckung)
- Shift+Tab: entfernt bis zu 2 Leerzeichen (Ausrueckung)
- Enter in nummerierter Liste: setzt naechste Zeile mit N+1 fort
- Enter auf leerem Listenelement: beendet die Liste (Bullet + Nummeriert)
- Enter beruecksichtigt Einrueckung bei Bullets
- CSS: bulletToolbarSep (Trennlinie) + bulletToolbarHint (Keyboard-Hinweis)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 20:40:50 +01:00
Thomas Reitz
a4013d4356 feat(frontend): bullet-editor fuer Projektaufgaben + Popup-Backdrop deaktiviert
- Modal.tsx + Drawer.tsx: onClick={onClose} vom Backdrop entfernt — alle
  Popups schliessen sich jetzt nur noch ueber Speichern/Abbrechen-Buttons
- ProjectModal.tsx: Textarea "Aufgaben" durch BulletEditor-Komponente
  ersetzt (Toolbar-Button toggled Aufzaehlungspunkt, Enter setzt Bullet
  auf naechster Zeile fort, leere Bullet-Zeile + Enter beendet die Liste)
- ExpertProfileTab.module.css: CSS fuer bulletEditor, bulletToolbar,
  bulletBtn, bulletEditorTextarea hinzugefuegt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 20:32:00 +01:00
Thomas Reitz
2078a90fba fix(expert-profile): Sprachniveau-Validierung mit Frontend-Werten synchronisieren
Backend @IsIn erlaubte nur CEFR-Codes (C1/C2/B2…), Frontend schickte
aber deutsche Bezeichnungen (Verhandlungssicher/Fließend/Gut).
Alle 4 Frontend-Level + CEFR-Codes für Rückwärtskompatibilität aufgenommen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 20:02:10 +01:00
Thomas Reitz
6c51eb5e83 feat(crm): Kontakt-Detailseite – Breite, Outlook Daten, Outlook-Push
- max-width 960px auf Kontakt-Detailseite
- M365-Sektion umbenannt zu "Outlook Daten", default eingeklappt
- Aufgaben-Tab entfernt (nur noch E-Mails + Kalender)
- "In Outlook speichern"-Button: pusht/aktualisiert Kontakt in Outlook-Kontakte via MS Graph POST/PATCH /me/contacts
- Kontaktdaten: Typ, Status immer sichtbar, Bundesland (state) in Adresse
- Backend: GraphService exportiert, pushContactToOutlook-Methode, POST /crm/contacts/:id/push-to-outlook

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 19:57:07 +01:00
Thomas Reitz
b197660ac8 feat(crm): Dediziertes Projektanfrage-Formular + Button in Vorgänge-Liste
- ProjectRequestFormModal: Eigenständiges Formular mit Projektdetails oben
  (Beschreibung, Auslastung/Start, Laufzeit/Vorort-Anteil, Stundensätze)
  und Standard-Vorgangsdaten darunter (Titel, Pipeline/Stage, Kontakt, etc.)
  Auto-Select bei genau einem isProjectType-Typ; Warnung wenn nicht konfiguriert
- DealsPage: Neuer outlined Button "Neue Projektanfrage" neben "Neuer Vorgang"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 18:33:33 +01:00
Thomas Reitz
4c739945f0 feat(crm): Projektanfrage-Vorgangstyp – isProjectType + ProjectRequestDetails
Backend:
- DealType.isProjectType Boolean-Flag (Admin-konfigurierbar in CRM Settings)
- Neue 1:1-Tabelle project_request_details (ON DELETE CASCADE):
  notes, workload, startDate, duration, onsitePercent, rateRemote, rateOnsite
- Migration 20260313_project_request
- ProjectRequestDto mit Validierung (0-100% fuer Auslastung/Vorort-Anteil)
- Deals-Service: nested create + upsert fuer projectRequest

Frontend:
- DealFormModal: Vorgangsart-Dropdown an Anfang verschoben;
  Projektanfrage-Sektion erscheint conditional bei isProjectType=true
  (Beschreibung, Auslastung/Start, Laufzeit/Vorort-Anteil, Stundensaetze)
- CrmSettingsPage: DealTypesConfig mit Projektanfrage-Checkbox + Tabellenspalte
- types.ts: ProjectRequestDetails, CreateProjectRequestPayload, Deal.projectRequest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 17:17:40 +01:00
Thomas Reitz
6bfce4af97 feat(crm): Vorgangsart (DealType) konfigurierbares Dropdown + Pipeline-Leerstate
- crm-service: Neues DealType-Model (deal_types Tabelle) mit name, color, sortOrder
  und Relation zu Deal.dealTypeId; Migration 20260313_deal_type
- crm-service: Vollstaendiger CRUD REST-Endpoint /crm/deal-types (TenantGuard)
- crm-service: CreateDealDto um optionales dealTypeId erweitert
- frontend: DealType Interface, API (dealTypesApi), Hooks (useDealTypes/...)
- frontend: CrmSettingsPage > Weitere Einstellungen > DealTypesConfig mit Farbpicker
- frontend: DealFormModal: Vorgangsart-Dropdown + Hinweis bei leerer Pipeline-Liste

Deployment: prisma migrate deploy && prisma generate im crm-service ausfuehren.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 16:15:02 +01:00
Thomas Reitz
f72ac6cb90 fix(frontend): Kalender-Eintragsfarben vereinheitlichen (einheitliches Primary-Blau statt Hash-Farben)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 15:56:14 +01:00
Thomas Reitz
8b4a71edb2 fix(frontend): Topbar auf Dashboard ausblenden – Profil nur in Tab-Leiste
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 15:53:26 +01:00
Thomas Reitz
2af54246c8 feat(frontend): E-Mail-Popup, Aktivitaeten-Zeitstrahl + Profil in Tab-Leiste
- EmailsTab: Outlook-aehnlicher Detail-Popup beim Klick auf E-Mail (Von/An/Datum/Anhang-Meta, Body-Vorschau, In Kontakt speichern als EMAIL-Aktivitaet)
- Neues EmailsTab.module.css fuer kompakte Liste und Modal
- ContactDetailPage: Aktivitaeten-Filterleiste (Typ + Zeitraum Von/Bis)
- ContactDetailPage: Zeitstrahl mit vertikaler Verbindungslinie, farbigen Typ-Badges (Note/Call/Email/Meeting/Task/FollowUp)
- DashboardPage: Profil-Bereich (Theme-Schalter, Avatar, Name, Logout) in Tab-Leiste integriert und leicht farblich abgesetzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 15:51:10 +01:00
Thomas Reitz
17a81c97ef feat(frontend): Kalender-Modal – Teilnehmer-Chips + Auto-Vorauswahl
- Suche startet mit Organisator-Name vorbelegt → CRM zeigt sofort
  passende Kontakte
- Klickbare Teilnehmer-Chips ermöglichen schnellen Wechsel zwischen
  den Event-Attendees als Suchbegriff
- Aktiver Chip wird farblich hervorgehoben

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 14:34:56 +01:00
Thomas Reitz
2d56ab6b3d feat(frontend): Kalender-Event-Modal + Zeitzonen-Fix
- Neues CalendarEventModal: Klick auf Termin in Agenda-/Wochenansicht
  öffnet Popup mit Betreff, Datum/Uhrzeit, Ort, Organisator, Teilnehmern
  und Online-Meeting-Link
- CRM-Aktivität: Kontaktsuche direkt im Modal; Termin als MEETING-
  Aktivität beim gewählten CRM-Kontakt speichern
- "Im Outlook öffnen"-Link im Modal-Footer
- Zeitzonen-Fix: MS Graph liefert UTC-Zeiten ohne 'Z'-Suffix →
  toDate() hängt 'Z' an → alle Termine jetzt in korrekter Ortszeit
- DayAgenda + AgendaView + WeekView: <a>-Tags durch klickbare <div>
  (role=button) ersetzt; onEventClick-Prop weitergereicht

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 14:30:56 +01:00
Thomas Reitz
3d75a7f9de feat(frontend+core): Dashboard Kontakte-Tab (O365) + Admin Logo-/Sidebar-Breite
Dashboard Kontakte-Tab:
- DashboardContactsTab.tsx + CSS: O365-Kontakte als Visitenkarten oder Liste
- Kachelansicht (auto-fill Grid) + Listenansicht (6-spaltig) umschaltbar
- Suchfeld (Name, E-Mail, Firma) mit Live-Filter
- Klick öffnet Detail-Modal mit allen Kontaktdaten (E-Mail/Telefon als Links)
- CRM-Import-Button: mappt M365Contact → CreateContactPayload, importiert direkt
- Nicht verbunden / Laden / Fehler States
- DashboardPage: ComingSoonTab entfernt, DashboardContactsTab eingebunden

Admin Branding — Logo-Breite + Sidebar-Breite:
- settings.controller.ts: logoWidth + sidebarWidth in GET/POST Branding
- AdminCustomizePage: Slider Logo-Breite (40–240px) + Sidebar-Breite (200–360px)
  mit Live-Vorschau (skalierte Mini-Sidebar)
- AppLayout: Logo-maxWidth aus branding.logoWidth; Sidebar width + main marginLeft
  dynamisch aus branding.sidebarWidth

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 14:03:45 +01:00
Thomas Reitz
d9c6240a3e fix(frontend): Anwendungen-Gruppe bei Start eingeklappt, Dashboard-Klick resettet auf Home-Tab
- AppLayout: appsOpen initial false (Anwendungen immer eingeklappt beim Laden)
- DashboardPage: useLocation + useEffect auf location.key → setzt activeTab
  auf 'home' bei jedem Navigations-Klick auf Dashboard in der Sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 13:51:04 +01:00
Thomas Reitz
5f50ba1315 feat(frontend): Profil-Topbar — Avatar, Theme-Schalter und Logout nach oben rechts
Sidebar-Bottom-Bereich (Profil, Abmelden, Theme-Toggle) vollstaendig entfernt
und durch eine sticky Topbar im Hauptinhaltsbereich ersetzt:
- Theme-Schalter: kompakte Icon-Button-Gruppe (☀ hell / ☾ dunkel / ⚙ system)
- Benutzer-Avatar + Name klickbar → /profile
- Logout-Icon-Button (SVG, Tooltip "Abmelden")
Sidebar zeigt nur noch Logo, Navigation und Admin-Link.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 13:46:33 +01:00
Thomas Reitz
0f63c28110 fix: WeatherWidget Ort mittig darunter; +30 Sprüche des Tages (65 gesamt) 2026-03-13 13:38:45 +01:00
Thomas Reitz
b34370345f fix: Analoguhr größer, digitale Zeit entfernt, Datum ausgeschrieben (long) 2026-03-13 13:35:17 +01:00
Thomas Reitz
baa0cafd40 fix: WeatherWidget auf volle Spaltenbreite (gleich wie Forecast-Karte) 2026-03-13 13:34:16 +01:00
Thomas Reitz
f1c2ba3163 docs: Summarize.md aktualisiert — Dashboard Home-Tab Redesign + O365-Profilfelder 2026-03-13 13:32:06 +01:00
Thomas Reitz
ceea82a2ac feat: Dashboard Home-Tab mit Analoguhr, 3-Tage-Prognose, Spruch des Tages + kompakte Widgets
- Analoge SVG-Uhr (AnalogClock.tsx) aktualisiert jede Sekunde via setInterval
- useWeather: 3-Tage-Prognose via Open-Meteo daily-Parameter (weather_code, tempMax, tempMin)
- Dashboard Home-Tab: 3-Spalten-Layout (Uhr+Wetter links | Aufgaben+Mails mitte | Messe+Agenda rechts)
- Spruch des Tages rechts im Header (deterministisch nach Tagesdatum, 35 dt. Zitate)
- WeatherWidget aus dem Header in die linke Spalte verschoben
- Kompaktes Aufgaben-Widget: Top 8 offene Aufgaben (CRM + O365), direkt erledigbar
- Kompaktes E-Mail-Widget: Posteingang der letzten 3 Tage, direkter Öffnen-Link
- „Alle →" Buttons schalten auf den jeweiligen Tab um

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 13:30:45 +01:00
Thomas Reitz
2348602fb0 feat: Erweiterte Profilfelder (analog O365) + Profilbild-Sync aus Microsoft 365
Neue Felder im Benutzerprofil (analog Microsoft 365 /me):
- Stellenbezeichnung (jobTitle), Abteilung (department)
- Firma (companyName), Standort (officeLocation)

Changes:
- Core: Prisma-Migration + neue Felder in User-Model, UpdateUserDto,
  findById/update/updateProfile
- CRM: M365UserProfile-Interface + getM365Profile um neue Felder erweitert;
  neue Methode getM365Photo() lädt 96x96 JPEG als Base64 Data-URL;
  neuer Endpoint GET /crm/office365/photo
- Frontend: AuthContext User-Interface, M365UserProfile-Typ, office365Api.getM365Photo()
  ProfilePage: Neues Formular-Fieldset "Organisation" mit 4 Feldern;
  manueller Sync-Button übernimmt auch Profilbild (immer überschreiben);
  useO365ProfileSync: Auto-Sync lädt Foto nur wenn noch kein INSIGHT-Avatar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 13:08:56 +01:00
Thomas Reitz
138742d385 feat: O365-Profil automatisch beim Login synchronisieren
- Neuer Hook useO365ProfileSync: läuft einmalig pro Browser-Session,
  überschreibt INSIGHT-Profil-Felder mit O365-Daten (firstName, lastName,
  phone, mobile, city, street, postalCode) — kein UI-Feedback, kein Fehler
  bricht die UX auf.
- AppLayout ruft useO365ProfileSync() auf, sodass die Synchronisation
  beim Laden der App (nach Login) automatisch startet.
- ProfilePage: "↓ O365 übernehmen"-Button überschreibt jetzt alle Felder
  wo O365 Daten hat (nicht mehr nur leere Felder) — konsistent mit dem
  Auto-Sync-Verhalten.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:50:25 +01:00
Thomas Reitz
347a6ca418 feat: Profil mit Microsoft 365 Daten anreichern
- GraphService: getM365Profile() lädt givenName, surname, mobilePhone,
  businessPhones, city, streetAddress, postalCode, jobTitle via /me
- Office365Controller: GET /crm/office365/profile Endpunkt
- Frontend types: M365UserProfile Interface
- Frontend api: office365Api.getM365Profile()
- ProfilePage: O365 uebernehmen Button (nur wenn M365 verbunden)
  fuellt leere Felder: Vorname, Nachname, Telefon, Mobil, Ort, Strasse, PLZ
  Bestehende Werte werden NICHT ueberschrieben; Feedback zeigt welche
  Felder uebernommen wurden; User muss Speichern klicken

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:38:43 +01:00
Thomas Reitz
403c581e57 fix: Agenda-Breite im Home-Sidebar füllt volle 300px
- DayAgenda: fullWidth-Prop ergänzt (setzt .agendaFull → width: 100%)
- Im Kalender-Tab bleibt die Agenda bei 260px (flex-shrink: 0)
- HomeSidebar übergibt fullWidth, sodass die Agenda den Sidebar
  lückenlos ausfüllt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:32:38 +01:00
Thomas Reitz
653464c89b feat: Kompakter Messe-Ticker im Home-Sidebar mit Detail-Popup
- EventCountdownTiles aus homeMain entfernt
- Neuer CompactMesseTicker im Sidebar: kleine klickbare Zeilen
  mit farbiger linker Linie (blau=bevorstehend, grün=läuft)
- Klick öffnet MesseDetailModal: Name, Status-Chip, Countdown,
  Fortschrittsbalken (bei laufenden Messen), Datum, Ort/Stand,
  Beschreibung, Website-Link
- HomeDayAgendaWidget → HomeSidebar: zeigt Ticker + Tages-Agenda
  in einer Spalte; Sidebar auf 300px verbreitert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:27:07 +01:00
Thomas Reitz
3b15c8ab9b feat: Aufgaben-Tab im Dashboard (O365 + CRM bidirektional)
- GraphService: graphPost/graphPatch Helfer; getAllTasksFlat (inkl.
  Body für CRM-Sync-Marker), createM365Task, completeM365Task
- Office365Controller: GET tasks/flat, POST tasks, PATCH tasks/:listId/:taskId/complete
- ActivitiesService/Controller: GET /crm/activities/open-tasks
  (TASK + FOLLOWUP, nicht erledigt)
- Frontend types: M365TaskFlat + CrmOpenTask Interfaces
- Frontend api/hooks: getTasksFlat, createTask, completeTask,
  getOpenTasks; neue Hooks useOffice365TasksFlat, useCrmOpenTasks,
  usePushTaskToO365, useCompleteO365Task, useCompleteCrmTask
- DashboardTasksTab: vereinheitlichte Aufgabenliste mit Farbcodierung
  (O365 blau, CRM orange, Synced grün), Push-Button, Erledigen-Button
- Bidirektionaler Sync via [INSIGHT_CRM:{activityId}] Marker im O365
  Task Body; Erledigen eines Synced-Tasks aktualisiert beide Systeme
- DashboardPage: Tasks-Tab auf DashboardTasksTab umgestellt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:01:04 +01:00
Thomas Reitz
fbf0b33a1f feat(dashboard): E-Mail Lesefenster + Kalender Umbau
E-Mail Tab:
- Klick auf E-Mail öffnet Detail-Modal (Lesefenster wie Outlook)
- Modal zeigt: Betreff, Absender, Datum, Anhang-Info, Body-Vorschau
- CRM-Bereich: gefundener Kontakt mit "Im CRM öffnen" + "Als Aktivität"
  speichern; kein Kontakt → "Kontakt anlegen" navigiert zu /crm/contacts
- "In Outlook öffnen" Link im Footer des Modals

Kalender Tab:
- WeekView: nur Arbeitstage Mo–Fr (5-Spalten-Grid statt 7)
- Neue Ansicht "Agenda": 14-Tage-Listenansicht (eigener Toggle-Button)
- Tages-Agenda nur bei Monat- und Wochenansicht sichtbar (nicht Agenda-View)
- Home-Tab: Tages-Agenda des heutigen Tages als Widget rechts
  (nur sichtbar wenn M365 verbunden)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 11:36:30 +01:00
Thomas Reitz
f2ed8d0a93 fix(dashboard): Kalender-Toggle immer sichtbar, E-Mail Breite auf 70% angepasst 2026-03-13 11:20:01 +01:00
Thomas Reitz
53666122d0 fix(dashboard): E-Mail Bereich auf 50% Breite begrenzen, Textumbruch aktivieren 2026-03-13 11:16:28 +01:00
Thomas Reitz
f007765872 docs: Summarize.md mit Dashboard Kalender-Tab Aenderungen aktualisieren 2026-03-13 10:55:02 +01:00
Thomas Reitz
76e8dff577 feat(dashboard): Kalender-Tab mit Monats-/Wochenansicht und Tages-Agenda
- Graph API: getCalendarEventsForRange() für beliebigen Datumsbereich,
  GET /crm/office365/calendar/range?startDate=&endDate= Endpoint
  (vor bestehenden calendar-Route definiert um Routing-Konflikt zu vermeiden)
- Graph API: wellKnownName aus mailFolders $select entfernt (400-Fehler auf
  Exchange-Tenants die das OData-Property nicht unterstützen)
- Frontend: DashboardCalendarTab mit MonthView (6×7 Grid), WeekView (7 Spalten)
  und DayAgenda (rechts 1/3), Navigation vor/zurück + Heute-Button,
  deterministisches Event-Coloring, Klick öffnet Termin in Outlook Online
- Frontend: DashboardEmailTab Ordner-Sortierung auf Display-Name-Basis
  (wellKnownName optional, isInboxFolder() erkennt Posteingang/Inbox)
- Frontend: M365MailFolder.wellKnownName als optional markiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 10:54:32 +01:00
Thomas Reitz
b6b182a349 fix(dashboard): E-Mail Tab lädt sofort mit well-known Inbox-ID als Fallback
Vorher: activeFolderId war null bis Ordnerliste geladen → E-Mail-Query nie gestartet
Jetzt: Default-Ordner-ID = 'inbox' (Graph API Well-Known-Name) → sofortiger Abruf
Zusätzlich: Fehler-/Leer-Zustand in der Ordner-Sidebar anzeigen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 10:32:04 +01:00
Thomas Reitz
0ed48557c4 docs: Summarize.md mit Dashboard E-Mail Tab Aenderungen aktualisieren
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 10:20:26 +01:00