import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useIntegrations, useOffice365MailFolders, useOffice365MailsInFolder, useContactByEmail, } from '../crm/hooks'; import { activitiesApi } from '../crm/api'; import type { M365Email, M365MailFolder, CrmContactLookup } from '../crm/types'; import styles from './DashboardEmailTab.module.css'; // ── Helpers ─────────────────────────────────────────────────────────────────── const DAYS_OPTIONS = [ { label: '1 Tag', value: 1 }, { label: '7 Tage', value: 7 }, { label: '14 Tage', value: 14 }, { label: 'Alle', value: 0 }, ] as const; // Priorität anhand bekannter DE/EN Ordnernamen (wellKnownName nicht verlässlich) const FOLDER_NAME_PRIORITY: Record = { 'posteingang': 0, 'inbox': 0, 'gesendete elemente': 1, 'sent items': 1, 'gesendet': 1, 'entwürfe': 2, 'drafts': 2, 'archiv': 3, 'archive': 3, 'junk-e-mail': 4, 'junk email': 4, 'spam': 4, 'gelöschte elemente': 5, 'deleted items': 5, 'papierkorb': 5, 'outbox': 6, 'ausgang': 6, }; function isInboxFolder(f: M365MailFolder): boolean { const name = f.displayName.toLowerCase(); return name === 'posteingang' || name === 'inbox' || f.wellKnownName === 'inbox'; } function sortFolders(folders: M365MailFolder[]): M365MailFolder[] { return [...folders].sort((a, b) => { const pa = FOLDER_NAME_PRIORITY[a.displayName.toLowerCase()] ?? 99; const pb = FOLDER_NAME_PRIORITY[b.displayName.toLowerCase()] ?? 99; if (pa !== pb) return pa - pb; return a.displayName.localeCompare(b.displayName, 'de'); }); } function formatEmailDate(iso: string): string { const d = new Date(iso); const now = new Date(); if (d.toDateString() === now.toDateString()) { return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }); } return d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: '2-digit', }); } // ── EmailCard (Klick öffnet Detail-Modal) ──────────────────────────────────── interface EmailCardProps { email: M365Email; onClick: () => void; } function EmailCard({ email, onClick }: EmailCardProps) { const senderEmail = email.from?.emailAddress?.address ?? null; const { data: contactData } = useContactByEmail(senderEmail); const contact = contactData?.data ?? null; const displayName = email.from?.emailAddress?.name || senderEmail || '—'; return (
e.key === 'Enter' && onClick()} >
{!email.isRead && {formatEmailDate(email.receivedDateTime)}
{displayName} {contact && ( CRM )} {email.hasAttachments && ( 📎 )}
{email.bodyPreview && (

{email.bodyPreview}

)}
); } // ── EmailDetailModal ────────────────────────────────────────────────────────── interface EmailDetailModalProps { email: M365Email; onClose: () => void; onSaveActivity: (email: M365Email, contact: CrmContactLookup) => void; } function EmailDetailModal({ email, onClose, onSaveActivity }: EmailDetailModalProps) { const navigate = useNavigate(); const senderEmail = email.from?.emailAddress?.address ?? null; const senderName = email.from?.emailAddress?.name ?? ''; const { data: contactData, isLoading: contactLoading } = useContactByEmail(senderEmail); const contact = contactData?.data ?? null; const contactName = contact ? [contact.firstName, contact.lastName].filter(Boolean).join(' ') || contact.email || '—' : null; const handleOpenContact = () => { onClose(); navigate(`/crm/contacts/${contact!.id}`); }; const handleCreateContact = () => { onClose(); navigate('/crm/contacts'); }; return (
e.stopPropagation()}> {/* ── Kopfzeile ── */}

{email.subject || '(Kein Betreff)'}

{/* ── Meta ── */}
Von {senderName || senderEmail || '—'} {senderName && senderEmail && ( <{senderEmail}> )}
Datum {new Date(email.receivedDateTime).toLocaleString('de-DE', { weekday: 'short', day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', })}
{email.hasAttachments && (
Anhang 📎 Vorhanden
)}
{/* ── Body-Vorschau ── */}
{email.bodyPreview || ( Kein Vorschautext verfügbar. )}
{/* ── CRM-Bereich ── */}
CRM {contactLoading ? ( Wird geprüft… ) : contact ? (
👤
{contactName} {contact.companyName && ( · {contact.companyName} )}
) : (
{senderEmail ? `Kein CRM-Kontakt für ${senderEmail}` : 'Kein Absender bekannt'} {senderEmail && ( )}
)}
{/* ── Footer ── */}
↗ In Outlook öffnen
); } // ── ActivityModal ───────────────────────────────────────────────────────────── interface ActivityModalProps { email: M365Email; contact: CrmContactLookup; onClose: () => void; onSaved: () => void; } function ActivityModal({ email, contact, onClose, onSaved }: ActivityModalProps) { const [comment, setComment] = useState(''); const qc = useQueryClient(); const contactName = [contact.firstName, contact.lastName].filter(Boolean).join(' ') || contact.email || '—'; const { mutate, isPending, isError } = useMutation({ mutationFn: () => activitiesApi.create({ contactId: contact.id, type: 'EMAIL', subject: email.subject || '(Kein Betreff)', description: comment.trim() || undefined, completedAt: email.receivedDateTime, }), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['crm', 'activities'] }); onSaved(); }, }); return (
e.stopPropagation()}>

E-Mail als Aktivität speichern

Kontakt {contactName}
Betreff {email.subject || '(Kein Betreff)'}
Von {email.from?.emailAddress?.name || email.from?.emailAddress?.address || '—'}