import { useState, useEffect } from 'react'; import { Reply, Star, Paperclip, Link2, X, Download, ExternalLink, Trash2, Undo2, Save, FileDown } from 'lucide-react'; import { CachedEmail, cachedEmailApi } from '../../services/api'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import Button from '../ui/Button'; import { Link } from 'react-router-dom'; import { useAuth } from '../../context/AuthContext'; import toast from 'react-hot-toast'; import SaveAttachmentModal from './SaveAttachmentModal'; import SaveEmailAsPdfModal from './SaveEmailAsPdfModal'; interface EmailDetailProps { email: CachedEmail; onReply: () => void; onAssignContract: () => void; onDeleted?: () => void; // Callback nach Löschen isSentFolder?: boolean; isContractView?: boolean; // True wenn aus der Vertragsansicht aufgerufen isTrashView?: boolean; // True wenn aus dem Papierkorb onRestored?: () => void; // Callback nach Wiederherstellen accountId?: number; // Für folder-counts Invalidierung } export default function EmailDetail({ email, onReply, onAssignContract, onDeleted, isSentFolder: _isSentFolder = false, isContractView = false, isTrashView = false, onRestored, accountId, }: EmailDetailProps) { const [showHtml, setShowHtml] = useState(true); const [localStarred, setLocalStarred] = useState(email.isStarred); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [showRestoreConfirm, setShowRestoreConfirm] = useState(false); const [showPermanentDeleteConfirm, setShowPermanentDeleteConfirm] = useState(false); const [saveAttachmentFilename, setSaveAttachmentFilename] = useState(null); const [showSaveAsPdfModal, setShowSaveAsPdfModal] = useState(false); const queryClient = useQueryClient(); const { hasPermission } = useAuth(); // Sync localStarred wenn sich die Email ändert useEffect(() => { setLocalStarred(email.isStarred); }, [email.id, email.isStarred]); const toggleStarMutation = useMutation({ mutationFn: () => cachedEmailApi.toggleStar(email.id), onMutate: () => { // Optimistisches Update setLocalStarred((prev) => !prev); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['emails'] }); queryClient.invalidateQueries({ queryKey: ['email', email.id] }); }, onError: () => { // Bei Fehler zurücksetzen setLocalStarred(email.isStarred); }, }); const unassignMutation = useMutation({ mutationFn: () => cachedEmailApi.unassignFromContract(email.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['emails'] }); queryClient.invalidateQueries({ queryKey: ['email', email.id] }); if (email.contractId) { queryClient.invalidateQueries({ queryKey: ['contract-folder-counts', email.contractId] }); } toast.success('Vertragszuordnung aufgehoben'); }, onError: (error: Error) => { console.error('Unassign error:', error); toast.error(error.message || 'Fehler beim Aufheben der Zuordnung'); }, }); const deleteMutation = useMutation({ mutationFn: () => cachedEmailApi.delete(email.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['emails'] }); // Folder-Counts invalidieren if (accountId) { queryClient.invalidateQueries({ queryKey: ['folder-counts', accountId] }); } if (email.contractId) { queryClient.invalidateQueries({ queryKey: ['contract-folder-counts', email.contractId] }); } toast.success('E-Mail in Papierkorb verschoben'); setShowDeleteConfirm(false); onDeleted?.(); }, onError: (error: Error) => { console.error('Delete error:', error); toast.error(error.message || 'Fehler beim Löschen der E-Mail'); setShowDeleteConfirm(false); }, }); const restoreMutation = useMutation({ mutationFn: () => cachedEmailApi.restore(email.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['emails'] }); // Folder-Counts invalidieren if (accountId) { queryClient.invalidateQueries({ queryKey: ['folder-counts', accountId] }); } if (email.contractId) { queryClient.invalidateQueries({ queryKey: ['contract-folder-counts', email.contractId] }); } toast.success('E-Mail wiederhergestellt'); setShowRestoreConfirm(false); onRestored?.(); }, onError: (error: Error) => { console.error('Restore error:', error); toast.error(error.message || 'Fehler beim Wiederherstellen der E-Mail'); setShowRestoreConfirm(false); }, }); const permanentDeleteMutation = useMutation({ mutationFn: () => cachedEmailApi.permanentDelete(email.id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['emails'] }); // Folder-Counts invalidieren (Trash count) if (accountId) { queryClient.invalidateQueries({ queryKey: ['folder-counts', accountId] }); } toast.success('E-Mail endgültig gelöscht'); setShowPermanentDeleteConfirm(false); onDeleted?.(); }, onError: (error: Error) => { console.error('Permanent delete error:', error); toast.error(error.message || 'Fehler beim endgültigen Löschen der E-Mail'); setShowPermanentDeleteConfirm(false); }, }); const formatDate = (dateStr: string) => { return new Date(dateStr).toLocaleString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }); }; const parseAddresses = (jsonStr: string): string[] => { try { return JSON.parse(jsonStr); } catch { return []; } }; const parseAttachments = (jsonStr?: string): string[] => { if (!jsonStr) return []; try { return JSON.parse(jsonStr); } catch { return []; } }; const toAddresses = parseAddresses(email.toAddresses); const ccAddresses = email.ccAddresses ? parseAddresses(email.ccAddresses) : []; const attachments = parseAttachments(email.attachmentNames); return (
{/* Header */}
{/* Subject & Actions */}

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

{isTrashView ? ( <> {/* Papierkorb-Aktionen */} ) : ( <> {/* Normale Aktionen */} {/* E-Mail als PDF speichern */} {/* Löschen-Button nur für User mit emails:delete Permission */} {hasPermission('emails:delete') && ( )} )}
{/* From/To/Date */}
Von: {email.fromName && `${email.fromName} `} <{email.fromAddress}>
An: {toAddresses.join(', ')}
{ccAddresses.length > 0 && (
CC: {ccAddresses.join(', ')}
)}
Am: {formatDate(email.receivedAt)}
{/* Contract Assignment */}
{email.contract ? (
Zugeordnet zu:{' '} {email.contract.contractNumber} {/* X-Button nur für manuell zugeordnete E-Mails (nicht für automatisch zugeordnete aus Vertrag gesendete) */} {!email.isAutoAssigned && ( )}
) : ( /* Zuordnen-Button: In Vertragsansicht ausblenden (E-Mails dort sind bereits zugeordnet) */ !isContractView && ( ) )}
{/* Attachments */} {attachments.length > 0 && (
{attachments.length} Anhang{attachments.length > 1 ? 'e' : ''}
{attachments.map((name, i) => (
{name} {/* Speichern-Button (nicht im Papierkorb) */} {!isTrashView && ( )}
))}
)}
{/* Body Toggle */} {email.htmlBody && email.textBody && (
)} {/* Email Body */}
{showHtml && email.htmlBody ? (
) : (
            {email.textBody || 'Kein Inhalt'}
          
)}
{/* Lösch-Bestätigung Modal (in Papierkorb verschieben) */} {showDeleteConfirm && (

E-Mail löschen?

Die E-Mail wird in den Papierkorb verschoben.

)} {/* Wiederherstellen-Bestätigung Modal */} {showRestoreConfirm && (

E-Mail wiederherstellen?

Die E-Mail wird wieder in den ursprünglichen Ordner ({email.folder === 'SENT' ? 'Gesendet' : 'Posteingang'}) verschoben.

)} {/* Endgültig löschen-Bestätigung Modal */} {showPermanentDeleteConfirm && (

E-Mail endgültig löschen?

Diese Aktion kann nicht rückgängig gemacht werden. Die E-Mail wird unwiderruflich gelöscht.

)} {/* Anhang speichern Modal */} {saveAttachmentFilename && ( setSaveAttachmentFilename(null)} emailId={email.id} attachmentFilename={saveAttachmentFilename} /> )} {/* E-Mail als PDF speichern Modal */} {showSaveAsPdfModal && ( setShowSaveAsPdfModal(false)} emailId={email.id} /> )}
); }