import { useState } from 'react'; import { FileText, User, CreditCard, IdCard, AlertTriangle, Check, ChevronDown, ChevronRight } from 'lucide-react'; import Modal from '../ui/Modal'; import Button from '../ui/Button'; import { cachedEmailApi, AttachmentTargetSlot, AttachmentEntityWithSlots } from '../../services/api'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import toast from 'react-hot-toast'; interface SaveAttachmentModalProps { isOpen: boolean; onClose: () => void; emailId: number; attachmentFilename: string; onSuccess?: () => void; } type SelectedTarget = { entityType: 'customer' | 'identityDocument' | 'bankCard' | 'contract'; entityId?: number; targetKey: string; hasDocument: boolean; label: string; }; export default function SaveAttachmentModal({ isOpen, onClose, emailId, attachmentFilename, onSuccess, }: SaveAttachmentModalProps) { const [selectedTarget, setSelectedTarget] = useState(null); const [expandedSections, setExpandedSections] = useState>(new Set(['customer'])); const queryClient = useQueryClient(); // Ziele laden const { data: targetsData, isLoading, error } = useQuery({ queryKey: ['attachment-targets', emailId], queryFn: () => cachedEmailApi.getAttachmentTargets(emailId), enabled: isOpen, }); const targets = targetsData?.data; const saveMutation = useMutation({ mutationFn: () => { if (!selectedTarget) throw new Error('Kein Ziel ausgewählt'); return cachedEmailApi.saveAttachmentTo(emailId, attachmentFilename, { entityType: selectedTarget.entityType, entityId: selectedTarget.entityId, targetKey: selectedTarget.targetKey, }); }, onSuccess: () => { toast.success('Anhang gespeichert'); queryClient.invalidateQueries({ queryKey: ['attachment-targets', emailId] }); queryClient.invalidateQueries({ queryKey: ['customers'] }); queryClient.invalidateQueries({ queryKey: ['contracts'] }); // Spezifische Ansichten aktualisieren (IDs als String, da URL-Params Strings sind) if (targets?.customer?.id) { queryClient.invalidateQueries({ queryKey: ['customer', targets.customer.id.toString()] }); } if (targets?.contract?.id) { queryClient.invalidateQueries({ queryKey: ['contract', targets.contract.id.toString()] }); } onSuccess?.(); handleClose(); }, onError: (error: Error) => { toast.error(error.message || 'Fehler beim Speichern'); }, }); const handleClose = () => { setSelectedTarget(null); onClose(); }; const toggleSection = (section: string) => { const newExpanded = new Set(expandedSections); if (newExpanded.has(section)) { newExpanded.delete(section); } else { newExpanded.add(section); } setExpandedSections(newExpanded); }; const handleSelectSlot = ( entityType: 'customer' | 'identityDocument' | 'bankCard' | 'contract', slot: AttachmentTargetSlot, entityId?: number, parentLabel?: string ) => { setSelectedTarget({ entityType, entityId, targetKey: slot.key, hasDocument: slot.hasDocument, label: parentLabel ? `${parentLabel} → ${slot.label}` : slot.label, }); }; const renderSlots = ( slots: AttachmentTargetSlot[], entityType: 'customer' | 'identityDocument' | 'bankCard' | 'contract', entityId?: number, parentLabel?: string ) => { return slots.map((slot) => { const isSelected = selectedTarget?.entityType === entityType && selectedTarget?.entityId === entityId && selectedTarget?.targetKey === slot.key; return (
handleSelectSlot(entityType, slot, entityId, parentLabel)} className={` flex items-center gap-3 p-3 cursor-pointer transition-colors rounded-lg ml-4 ${isSelected ? 'bg-blue-100 ring-2 ring-blue-500' : 'hover:bg-gray-100'} `} >
{slot.label} {slot.hasDocument && ( Vorhanden )}
{isSelected && }
); }); }; const renderEntityWithSlots = ( entity: AttachmentEntityWithSlots, entityType: 'identityDocument' | 'bankCard' ) => { return (
{entity.label}
{renderSlots(entity.slots, entityType, entity.id, entity.label)}
); }; const renderSection = ( title: string, sectionKey: string, icon: React.ReactNode, children: React.ReactNode, isEmpty: boolean = false ) => { const isExpanded = expandedSections.has(sectionKey); return (
{isExpanded && (
{isEmpty ? (

Keine Einträge vorhanden

) : ( children )}
)}
); }; return (
{/* Attachment Info */}

Datei: {attachmentFilename}

{/* Loading */} {isLoading && (
)} {/* Error */} {error && (
Fehler beim Laden der Dokumentziele
)} {/* Targets */} {targets && (
{/* Kunde */} {renderSection( `Kunde: ${targets.customer.name}`, 'customer', , renderSlots(targets.customer.slots, 'customer'), targets.customer.slots.length === 0 )} {/* Ausweise */} {renderSection( 'Ausweisdokumente', 'identityDocuments', , targets.identityDocuments.map((doc) => renderEntityWithSlots(doc, 'identityDocument') ), targets.identityDocuments.length === 0 )} {/* Bankkarten */} {renderSection( 'Bankkarten', 'bankCards', , targets.bankCards.map((card) => renderEntityWithSlots(card, 'bankCard')), targets.bankCards.length === 0 )} {/* Vertrag */} {targets.contract && renderSection( `Vertrag: ${targets.contract.contractNumber}`, 'contract', , renderSlots(targets.contract.slots, 'contract'), targets.contract.slots.length === 0 )} {!targets.contract && (
E-Mail ist keinem Vertrag zugeordnet. Ordnen Sie die E-Mail einem Vertrag zu, um Vertragsdokumente als Ziel auswählen zu können.
)}
)} {/* Warning if replacing */} {selectedTarget?.hasDocument && (
Achtung: An diesem Feld ist bereits ein Dokument hinterlegt. Das vorhandene Dokument wird durch den neuen Anhang ersetzt.
)} {/* Actions */}
); }