refactor: redesign summary view in MailImportWizard to improve readability and document information layout
Build and Push Multi-Platform Images / build-and-push (push) Successful in 15s

This commit is contained in:
2026-05-09 12:15:54 +02:00
parent 3f2b3a7af4
commit e4f765fcfd
@@ -1,20 +1,19 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { import {
Modal, Steps, Button, Table, Radio, Select, Input, DatePicker, Modal, Steps, Button, Table, Radio, Select, Input, DatePicker,
Space, Row, Col, Typography, message, Spin, Result, Alert, Card, Tag Space, Row, Col, Typography, message, Spin, Result, Alert, Tag
} from 'antd'; } from 'antd';
import type { ColumnsType } from 'antd/es/table'; import type { ColumnsType } from 'antd/es/table';
import { emailImportApi, type AttachmentImportData } from '../api/email-import'; import { emailImportApi, type AttachmentImportData } from '../api/email-import';
import { paperlessApi, type PaperlessCorrespondent } from '../api/paperless'; import { paperlessApi, type PaperlessCorrespondent } from '../api/paperless';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { import {
PrinterOutlined, FileTextOutlined, PaperClipOutlined, ArrowRightOutlined, PrinterOutlined, PaperClipOutlined, ArrowRightOutlined, WarningOutlined
WarningOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import PdfSplitViewer from './PdfSplitViewer'; import PdfSplitViewer from './PdfSplitViewer';
import BarcodePositioner from './BarcodePositioner'; import BarcodePositioner from './BarcodePositioner';
const { Text, Title } = Typography; const { Text } = Typography;
interface MailImportWizardProps { interface MailImportWizardProps {
visible: boolean; visible: boolean;
@@ -664,66 +663,61 @@ export default function MailImportWizard({ visible, onClose, email, attachments
const attachmentsToImport = importData.filter(i => i.type === 'ATTACHMENT'); const attachmentsToImport = importData.filter(i => i.type === 'ATTACHMENT');
return ( return (
<div style={{ padding: '0 24px' }}> <div>
<Title level={4} style={{ marginBottom: 24 }}>Zusammenfassung des Imports</Title> {mainDocs.length === 0 && (
<Text type="secondary" style={{ display: 'block', marginBottom: 24 }}> <Alert type="warning" message="Keine Hauptdokumente zum Importieren ausgewählt." style={{ marginBottom: 16 }} />
Bitte überprüfe die folgende Struktur. Mit Klick auf "Import Ausführen" werden die Belegnummern reserviert und die Dokumente hochgeladen. )}
</Text>
{mainDocs.length === 0 && <Alert type="warning" message="Keine Hauptdokumente zum Importieren ausgewählt." />}
{mainDocs.map(main => { {mainDocs.map(main => {
const mainAttachments = attachmentsToImport.filter(a => a.parentVirtualId === main.virtualId); const mainAttachments = attachmentsToImport.filter(a => a.parentVirtualId === main.virtualId);
const mode = belegnummerMode[main.virtualId] || 'neu';
const num = belegnummern[main.virtualId] || '000000'; const num = belegnummern[main.virtualId] || '000000';
const yr = barcodes[main.virtualId]?.jahr || dayjs(email.Date).format('YYYY'); const yr = barcodes[main.virtualId]?.jahr || dayjs(email.Date).format('YYYY');
const datum = eingangsdaten[main.virtualId];
const belegnr = `${yr}-${String(num).padStart(6, '0')}`;
return ( return (
<div key={main.virtualId} style={{ marginBottom: 24 }}> <div key={main.virtualId} style={{ marginBottom: 24, padding: 16, border: '1px solid #f0f0f0', borderRadius: 8 }}>
<Card size="small" style={{ borderLeft: '4px solid #1890ff' }}> <Text strong style={{ fontSize: 16, marginBottom: 12, display: 'block' }}>{main.fileName}</Text>
<Row align="middle"> <Row gutter={24} align="middle">
<Col span={16}> <Col span={20}>
<Space> <Space size={24}>
<FileTextOutlined style={{ fontSize: 20, color: '#1890ff' }} /> <Text type="secondary">
<div> Eingangsdatum: <Text strong>{datum?.format('DD.MM.YYYY') ?? '—'}</Text>
<Text strong style={{ fontSize: 16 }}>{main.fileName}</Text> </Text>
<br /> <Text type="secondary">
<Text type="secondary" style={{ fontSize: 12 }}>Hauptdokument</Text> Belegnummer: <Tag color="blue" style={{ fontSize: 13 }}>{belegnr}</Tag>
</div> </Text>
</Space> </Space>
</Col> {mainAttachments.length > 0 && (
<Col span={8} style={{ textAlign: 'right' }}> <div style={{ marginTop: 12, paddingLeft: 16 }}>
<Tag color="blue" style={{ fontSize: 14, padding: '4px 12px' }}> {mainAttachments.map(att => (
{mode === 'neu' ? `Belegnr.: ${yr}-${num}` : `Belegnr.: ${yr}-${num}`} <div key={att.virtualId} style={{ marginBottom: 8, padding: '6px 12px', background: '#fafafa', borderRadius: 4, display: 'flex', alignItems: 'center' }}>
</Tag> <ArrowRightOutlined style={{ marginRight: 12, color: '#8c8c8c' }} />
</Col> <PaperClipOutlined style={{ marginRight: 8 }} />
</Row> <Text style={{ flex: 1 }}>{att.fileName}</Text>
<Tag>Anlage</Tag>
{mainAttachments.length > 0 && ( </div>
<div style={{ marginTop: 12, paddingLeft: 32 }}> ))}
{mainAttachments.map(att => ( </div>
<div key={att.virtualId} style={{ marginBottom: 8, padding: '8px 12px', background: '#fafafa', borderRadius: 4, display: 'flex', alignItems: 'center' }}> )}
<ArrowRightOutlined style={{ marginRight: 12, color: '#8c8c8c' }} /> </Col>
<PaperClipOutlined style={{ marginRight: 8 }} /> <Col span={4} style={{ textAlign: 'right' }}>
<Text style={{ flex: 1 }}>{att.fileName}</Text> <Button icon={<PrinterOutlined />} onClick={() => printDocument(main.virtualId, main.attachmentId)}>
<Tag>Anlage</Tag> Drucken
</div> </Button>
))} </Col>
</div> </Row>
)}
</Card>
</div> </div>
); );
})} })}
{/* Orphans (Attachments without parent or parents ignored) */}
{attachmentsToImport.filter(a => !mainDocs.find(m => m.virtualId === a.parentVirtualId)).map(orphan => ( {attachmentsToImport.filter(a => !mainDocs.find(m => m.virtualId === a.parentVirtualId)).map(orphan => (
<div key={orphan.virtualId} style={{ marginBottom: 12 }}> <div key={orphan.virtualId} style={{ marginBottom: 12 }}>
<Alert <Alert
type="error" type="error"
message={`Anlage ohne Hauptdokument: ${orphan.fileName}`} message={`Anlage ohne Hauptdokument: ${orphan.fileName}`}
description="Bitte gehe zurück und ordne diese Anlage einem Hauptdokument zu oder ignoriere sie." description="Bitte gehe zurück und ordne diese Anlage einem Hauptdokument zu oder ignoriere sie."
/> />
</div> </div>
))} ))}
</div> </div>