import { useEffect, useState, useCallback } from 'react'; import { Table, Typography, Tag, Button, Modal, Select, message, Space, Radio, Tooltip } from 'antd'; import { EuroOutlined } from '@ant-design/icons'; import type { ColumnsType } from 'antd/es/table'; import dayjs from 'dayjs'; import { zahlungApi, type ZahlungDocument, type ZahlungOption, type ZahlungFilter } from '../api/zahlung'; import { paperlessApi, type PaperlessDocType, type PaperlessCorrespondent } from '../api/paperless'; import { useIsMobile } from '../hooks/useIsMobile'; import MobileCardList from '../components/MobileCardList'; const { Title, Text } = Typography; const FREIGABE_FIELD_ID = 15; const ZAHLUNG_FIELD_ID = 16; const FREIGABE_WERT_FREIGEGEBEN = 'freigegeben'; const FILTER_OPTIONS: { value: ZahlungFilter; label: string }[] = [ { value: 'ausstehend', label: 'Freigegeben, noch nicht bezahlt' }, { value: 'freigegeben', label: 'Alle freigegebenen' }, { value: 'alle', label: 'Alle' }, ]; export default function ZahlungPage() { const isMobile = useIsMobile(); const [data, setData] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(25); const [filter, setFilter] = useState('ausstehend'); const [docTypes, setDocTypes] = useState([]); const [correspondents, setCorrespondents] = useState([]); const [zahlungOptions, setZahlungOptions] = useState([]); const [selectedDoc, setSelectedDoc] = useState(null); const [modalOpen, setModalOpen] = useState(false); const [selectedValue, setSelectedValue] = useState(null); const [saving, setSaving] = useState(false); useEffect(() => { Promise.all([ paperlessApi.getDocumentTypes(), paperlessApi.getCorrespondents(), zahlungApi.getOptions(), ]).then(([dts, corrs, opts]) => { setDocTypes(dts); setCorrespondents(corrs); setZahlungOptions(opts); }); }, []); const fetchData = useCallback(async () => { setLoading(true); try { const result = await zahlungApi.getDocuments(page, pageSize, filter); setData(result.results ?? []); setTotal(result.count ?? 0); } catch { message.error('Fehler beim Laden der Belege'); } finally { setLoading(false); } }, [page, pageSize, filter]); useEffect(() => { fetchData(); }, [fetchData]); const getDocTypeName = (id: number | null) => { if (!id) return '—'; return docTypes.find((d) => d.id === id)?.name ?? String(id); }; const getCorrespondentName = (id: number | null) => { if (!id) return '—'; return correspondents.find((c) => c.id === id)?.name ?? String(id); }; const toCfString = (value: any): string | null => { if (value === null || value === undefined || value === '') return null; if (typeof value === 'object') return String(value?.id ?? value?.value ?? value?.label ?? '') || null; return String(value); }; const getCfValue = (doc: ZahlungDocument, fieldId: number) => { const cf = doc.custom_fields?.find((f) => f.field === fieldId); return toCfString(cf?.value); }; const renderFreigabeTag = (doc: ZahlungDocument) => { const val = getCfValue(doc, FREIGABE_FIELD_ID); if (!val) return Nicht gesetzt; if (val === FREIGABE_WERT_FREIGEGEBEN) return Freigegeben; return {val}; }; const renderZahlungTag = (doc: ZahlungDocument) => { const val = getCfValue(doc, ZAHLUNG_FIELD_ID); if (!val) return Nicht gesetzt; const opt = zahlungOptions.find((o) => o.id === val); return {opt?.label ?? val}; }; const istFreigegeben = (doc: ZahlungDocument) => getCfValue(doc, FREIGABE_FIELD_ID) === FREIGABE_WERT_FREIGEGEBEN; const openModal = (doc: ZahlungDocument) => { setSelectedDoc(doc); setSelectedValue(getCfValue(doc, ZAHLUNG_FIELD_ID)); setModalOpen(true); }; const handleZahlung = async () => { if (!selectedDoc) return; setSaving(true); try { await zahlungApi.setZahlung(selectedDoc.id, selectedValue); message.success('Zahlung gesetzt'); setModalOpen(false); setSelectedDoc(null); fetchData(); } catch { message.error('Fehler beim Speichern der Zahlung'); } finally { setSaving(false); } }; const columns: ColumnsType = [ { title: 'Dokumenttyp', dataIndex: 'document_type', key: 'doctype', render: getDocTypeName, }, { title: 'Titel', dataIndex: 'title', key: 'title', ellipsis: true, }, { title: 'Erstellt', dataIndex: 'created', key: 'created', width: 110, render: (v: string) => v ? dayjs(v).format('DD.MM.YYYY') : '—', }, { title: 'Absender', dataIndex: 'correspondent', key: 'correspondent', render: getCorrespondentName, }, { title: 'Freigabe', key: 'freigabe', width: 130, render: (_, doc) => renderFreigabeTag(doc), }, { title: 'Zahlung', key: 'zahlung', width: 130, render: (_, doc) => renderZahlungTag(doc), }, { title: '', key: 'action', width: 150, render: (_, doc) => { const freigegeben = istFreigegeben(doc); return ( ); }, }, ]; const paginationConfig = { current: page, pageSize, total, showSizeChanger: true, pageSizeOptions: ['25', '50', '100'], onChange: (p: number, ps: number) => { setPage(p); setPageSize(ps); }, showTotal: (t: number) => `${t} Belege`, }; return ( <> Zahlung {isMobile ? ( setSelectedValue(v ?? null)} options={zahlungOptions.map((o) => ({ value: o.id, label: o.label }))} /> ); }