feat: add mobile-responsive layout and card views across all pages
Build and Push Multi-Platform Images / build-and-push (push) Successful in 39s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 39s
- New useIsMobile hook and MobileCardList component - AppLayout: hamburger menu + Drawer navigation on mobile - All list pages (Inbox, Posteingang, Manuell, Mail, Freigabe, Zahlung, TaskLog) show card layout on mobile instead of tables - CSS: responsive modal height, horizontal table scroll, text-size-adjust - Backend: Agrarmonitor polling fixes, Zahlung service improvements, IMAP folder service extended, misc controller fixes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
0765d14d3b
commit
7076eef57b
28 files changed
+1081
-462
No files matched your search
@@ -3,14 +3,17 @@ import { Table, Popover, Button, Space, message, Tooltip, Typography } from 'ant
|
||||
import { AuthImage } from '../utils/auth-resource';
|
||||
import { ReloadOutlined } from '@ant-design/icons';
|
||||
|
||||
const { Title } = Typography;
|
||||
const { Title, Text } = Typography;
|
||||
import dayjs from 'dayjs';
|
||||
import { posteingangApi } from '../api/posteingang';
|
||||
import type { PosteingangDocument } from '../api/posteingang';
|
||||
import DocumentEditModal from '../components/DocumentEditModal';
|
||||
import { getEnv } from '../utils/env';
|
||||
import { useIsMobile } from '../hooks/useIsMobile';
|
||||
import MobileCardList from '../components/MobileCardList';
|
||||
|
||||
export default function PosteingangPage() {
|
||||
const isMobile = useIsMobile();
|
||||
const [data, setData] = useState<PosteingangDocument[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [editModalOpen, setEditModalOpen] = useState(false);
|
||||
@@ -64,6 +67,11 @@ export default function PosteingangPage() {
|
||||
/>
|
||||
);
|
||||
|
||||
const getEingangsdatum = (record: PosteingangDocument) => {
|
||||
const cf = record.customFields?.find((f) => f.field === 9);
|
||||
return cf?.value ? dayjs(cf.value).format('DD.MM.YYYY') : '-';
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Vorschau',
|
||||
@@ -88,10 +96,7 @@ export default function PosteingangPage() {
|
||||
{
|
||||
title: 'Eingangsdatum',
|
||||
key: 'eingangsdatum',
|
||||
render: (_: any, record: PosteingangDocument) => {
|
||||
const cf = record.customFields?.find((f) => f.field === 9);
|
||||
return cf?.value ? dayjs(cf.value).format('DD.MM.YYYY') : '-';
|
||||
}
|
||||
render: (_: any, record: PosteingangDocument) => getEingangsdatum(record),
|
||||
},
|
||||
{
|
||||
title: 'Importiert am',
|
||||
@@ -121,14 +126,46 @@ export default function PosteingangPage() {
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{ pageSize: 20, showSizeChanger: true, showTotal: (t) => `${t} Dokumente` }}
|
||||
locale={{ emptyText: 'Keine Einträge vorhanden' }}
|
||||
/>
|
||||
{isMobile ? (
|
||||
<MobileCardList<PosteingangDocument>
|
||||
dataSource={data}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{ pageSize: 20, showTotal: (t) => `${t} Dokumente` }}
|
||||
renderCard={(record) => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||
<div style={{ display: 'flex', gap: 12 }}>
|
||||
<AuthImage
|
||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${record.id}`}
|
||||
width={72}
|
||||
style={{ border: '1px solid #d9d9d9', objectFit: 'contain', flexShrink: 0 }}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
|
||||
<Text strong>{record.title || '—'}</Text>
|
||||
<Text type="secondary" style={{ fontSize: 13 }}>
|
||||
Eingangsdatum: {getEingangsdatum(record)}
|
||||
</Text>
|
||||
<Text type="secondary" style={{ fontSize: 13 }}>
|
||||
Importiert am: {dayjs(record.added).format('DD.MM.YYYY HH:mm')}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<Button type="primary" block onClick={() => handleEdit(record)}>
|
||||
Bearbeiten
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{ pageSize: 20, showSizeChanger: true, showTotal: (t) => `${t} Dokumente` }}
|
||||
locale={{ emptyText: 'Keine Einträge vorhanden' }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<DocumentEditModal
|
||||
documentId={selectedDoc?.id || null}
|
||||
|
||||
Reference in new issue
Block a user