- 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>
- 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>
- 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>
- 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>
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>
- 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>
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>
- 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>
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>
Tab-Leiste auf Dashboard-Seite. Home zeigt bisherigen Inhalt,
restliche Tabs als Platzhalter (Inhalt folgt).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Neuer "Integrationen"-Tab in ProfilePage mit "Microsoft 365 verbinden"-
Button, OAuth-Callback-Handling (?integration=...&status=...), Trennen-Button
- EmailsTab, CalendarTab, TasksTab fuer ContactDetailPage (via MS Graph Proxy)
- useIntegrations, useDisconnectM365, useContactEmails/Calendar/Tasks Hooks
- integrationsApi + graphApi in crm/api.ts
- M365Email, M365CalendarEvent, M365Task, UserIntegration Types in crm/types.ts
- Tabs nur sichtbar wenn Kontakt eine E-Mail-Adresse hat; ohne Verbindung Connect-Button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Import ist kein eigener Nav-Eintrag mehr, sondern ein Tab
in den CRM-Einstellungen. /crm/import redirectet auf /crm/settings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lexware contact linking is not relevant for individual contacts,
only for companies. Removed LexwareSection component and the
two-column topRow grid layout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Name (Unternehmen) in Klammern in der Überschrift
- Grüner Punkt → "● Aktiv"/"● Inaktiv" Badge
- Position als Subtitle unterhalb des Namens
- Lexware-Card rechts neben Kontaktdaten (260px)
- Aktivitäten als volle Breite unterhalb der Kontaktdaten
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend (CRM expert): Custom field definitions CRUD, bulk value upsert,
7 endpoints, Prisma schema with CustomFieldDef + CustomFieldValue tables.
Frontend: Types, API, hooks, admin settings page with field management,
CustomFieldsDisplay for detail pages, CustomFieldsForm for edit modals.
Also fix Vite allowedHosts for insight.xinion.lan.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: 4 new endpoints in SettingsController (GET/POST/DELETE /settings/ssl, POST /settings/ssl/check-dns)
- Certificate validation via Node.js crypto.X509Certificate (PEM format, expiry, SAN match)
- DNS resolution check via dns.promises.resolve4
- Auto-generates Traefik dynamic config (ssl-domain.yml) with custom domain routing + HTTP->HTTPS redirect
- Frontend: AdminSslPage with DNS name input, cert/key upload, status display
- Docker: Core-service gets access to traefik-certs volume and dynamic config directory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: TradeEvent Prisma model, NestJS CRUD module with date validation
and tenant isolation. Frontend: Admin Events page with create/edit/delete
modals, dashboard countdown tiles showing upcoming/ongoing/ended events
with progress bars, and useEventCountdown hook for live timer updates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sub-rows now have an indigo left border, tinted background and stronger
indent to visually separate them from company rows. Dark mode variants
included. Expanded company row also gets a primary-colored left border.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Companies with linked contacts now show an expand arrow. Clicking it
lazy-loads and displays contacts as indented sub-rows with name,
position, email, phone, type badge and status. Backend gains companyId
filter on GET /contacts for efficient per-company querying.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When importing contact persons from Lexware, if the parent company
is already in the CRM (detected via linkedMap), the companyId is now
passed to createContact so the contact is properly associated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The backend DTO validation enforces @Max(100) on pageSize. The ImportTab
was requesting pageSize=500, causing a 400 Bad Request. This left the
linkedMap empty and showed import buttons for already-imported contacts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Import tab now loads all CRM companies/contacts and cross-references
lexwareContactId to detect already-imported entries. Linked contacts show
a green badge and "Öffnen" link instead of import buttons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: new CRUD services/controllers for Industries, AccountTypes,
RelationshipTypes, CompanyRelationships with Prisma schema migration
- Frontend: new hooks, API functions, and types for all config entities
- CompanyDetailPage redesign with ActivityFeed, RelationshipsCard
- CompanyFormModal extended with industry, account type, owner fields
- Activities service now supports companyId filter + includeContacts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace search-only ImportTab with paginated browsable list of all Lexware contacts
- Add expandable Ansprechpartner (contact persons) section per company
- Individual Ansprechpartner can be imported as CRM contacts
- Add pagination controls for navigating large contact lists
- Search filter still available (min. 3 chars, backend MinLength constraint)
- Clean up useLexwareContacts hook with proper query key
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New admin page under /crm/lexware-sync with two tabs:
- Import: Search Lexware contacts and import as CRM company or contact
- Export: List CRM companies/contacts and push to Lexware Office
Accessible via CRM Settings page (admin-only).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
React hooks must not be called after conditional returns (Rules of Hooks).
Moves all hook calls above the isModuleEnabled check in LexwareSection
and DealVouchersSection to prevent silent component crashes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>