Files
dashboard/frontend/src/components/admin/BestellungenTab.tsx
Matthias Hochmeister 5032e1593b new features
2026-03-23 13:08:19 +01:00

168 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react';
import {
Box,
Typography,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Chip,
FormControl,
InputLabel,
Select,
MenuItem,
CircularProgress,
} from '@mui/material';
import { useQuery } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { bestellungApi } from '../../services/bestellung';
import { shopApi } from '../../services/shop';
import { BESTELLUNG_STATUS_LABELS, BESTELLUNG_STATUS_COLORS } from '../../types/bestellung.types';
import { SHOP_STATUS_LABELS, SHOP_STATUS_COLORS } from '../../types/shop.types';
import type { BestellungStatus } from '../../types/bestellung.types';
import type { ShopAnfrageStatus } from '../../types/shop.types';
function BestellungenTab() {
const navigate = useNavigate();
const [statusFilter, setStatusFilter] = useState<string>('');
const { data: orders, isLoading: ordersLoading } = useQuery({
queryKey: ['admin-bestellungen', statusFilter],
queryFn: () => bestellungApi.getOrders(statusFilter ? { status: statusFilter } : undefined),
});
const { data: requests, isLoading: requestsLoading } = useQuery({
queryKey: ['admin-shop-requests'],
queryFn: () => shopApi.getRequests({ status: 'offen' }),
});
const formatCurrency = (value?: number) =>
value != null ? new Intl.NumberFormat('de-AT', { style: 'currency', currency: 'EUR' }).format(value) : '';
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
{/* Pending Shop Requests */}
{(requests?.length ?? 0) > 0 && (
<Paper sx={{ p: 2 }}>
<Typography variant="h6" gutterBottom>
Offene Shop-Anfragen ({requests?.length})
</Typography>
{requestsLoading ? (
<CircularProgress size={24} />
) : (
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>#</TableCell>
<TableCell>Anfrager</TableCell>
<TableCell>Status</TableCell>
<TableCell>Erstellt am</TableCell>
</TableRow>
</TableHead>
<TableBody>
{(requests ?? []).map((req) => (
<TableRow
key={req.id}
hover
sx={{ cursor: 'pointer' }}
onClick={() => navigate('/shop?tab=2')}
>
<TableCell>{req.id}</TableCell>
<TableCell>{req.anfrager_name || ''}</TableCell>
<TableCell>
<Chip
label={SHOP_STATUS_LABELS[req.status as ShopAnfrageStatus]}
color={SHOP_STATUS_COLORS[req.status as ShopAnfrageStatus]}
size="small"
/>
</TableCell>
<TableCell>{new Date(req.erstellt_am).toLocaleDateString('de-AT')}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)}
</Paper>
)}
{/* Orders Overview */}
<Paper sx={{ p: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
<Typography variant="h6">Bestellungen</Typography>
<FormControl size="small" sx={{ minWidth: 180 }}>
<InputLabel>Status</InputLabel>
<Select
value={statusFilter}
label="Status"
onChange={(e) => setStatusFilter(e.target.value)}
>
<MenuItem value="">Alle</MenuItem>
{Object.entries(BESTELLUNG_STATUS_LABELS).map(([key, label]) => (
<MenuItem key={key} value={key}>{label}</MenuItem>
))}
</Select>
</FormControl>
</Box>
{ordersLoading ? (
<Box sx={{ display: 'flex', justifyContent: 'center', py: 3 }}>
<CircularProgress />
</Box>
) : (
<TableContainer>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>Bezeichnung</TableCell>
<TableCell>Lieferant</TableCell>
<TableCell>Status</TableCell>
<TableCell align="right">Positionen</TableCell>
<TableCell align="right">Gesamt</TableCell>
<TableCell>Erstellt am</TableCell>
</TableRow>
</TableHead>
<TableBody>
{(orders ?? []).length === 0 ? (
<TableRow>
<TableCell colSpan={6} align="center">
<Typography variant="body2" color="text.secondary">Keine Bestellungen</Typography>
</TableCell>
</TableRow>
) : (
(orders ?? []).map((order) => (
<TableRow
key={order.id}
hover
sx={{ cursor: 'pointer' }}
onClick={() => navigate(`/bestellungen/${order.id}`)}
>
<TableCell>{order.bezeichnung}</TableCell>
<TableCell>{order.lieferant_name || ''}</TableCell>
<TableCell>
<Chip
label={BESTELLUNG_STATUS_LABELS[order.status as BestellungStatus]}
color={BESTELLUNG_STATUS_COLORS[order.status as BestellungStatus]}
size="small"
/>
</TableCell>
<TableCell align="right">{order.items_count ?? 0}</TableCell>
<TableCell align="right">{formatCurrency(order.total_cost)}</TableCell>
<TableCell>{new Date(order.erstellt_am).toLocaleDateString('de-AT')}</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
)}
</Paper>
</Box>
);
}
export default BestellungenTab;