import { useState, useEffect } from 'react'; import { Box, Tab, Tabs, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Chip, IconButton, Button, Dialog, DialogTitle, DialogContent, DialogActions, TextField, MenuItem, Select, FormControl, InputLabel, Tooltip, Autocomplete, } from '@mui/material'; import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate, useSearchParams } from 'react-router-dom'; import DashboardLayout from '../components/dashboard/DashboardLayout'; import ChatAwareFab from '../components/shared/ChatAwareFab'; import { useNotification } from '../contexts/NotificationContext'; import { usePermissionContext } from '../contexts/PermissionContext'; import { bestellungApi } from '../services/bestellung'; import { BESTELLUNG_STATUS_LABELS, BESTELLUNG_STATUS_COLORS } from '../types/bestellung.types'; import type { BestellungStatus, BestellungFormData, LieferantFormData, Lieferant } from '../types/bestellung.types'; // ── Helpers ── const formatCurrency = (value?: number) => value != null ? new Intl.NumberFormat('de-AT', { style: 'currency', currency: 'EUR' }).format(value) : '–'; const formatDate = (iso?: string) => iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) : '–'; // ── Tab Panel ── interface TabPanelProps { children: React.ReactNode; index: number; value: number } function TabPanel({ children, value, index }: TabPanelProps) { if (value !== index) return null; return {children}; } const TAB_COUNT = 2; // ── Status options for filter ── const ALL_STATUSES: BestellungStatus[] = ['entwurf', 'erstellt', 'bestellt', 'teillieferung', 'vollstaendig', 'abgeschlossen']; // ── Empty form data ── const emptyOrderForm: BestellungFormData = { bezeichnung: '', lieferant_id: undefined, besteller_id: '', budget: undefined, notizen: '' }; const emptyVendorForm: LieferantFormData = { name: '', kontakt_name: '', email: '', telefon: '', adresse: '', website: '', notizen: '' }; // ══════════════════════════════════════════════════════════════════════════════ // Component // ══════════════════════════════════════════════════════════════════════════════ export default function Bestellungen() { const navigate = useNavigate(); const [searchParams] = useSearchParams(); const queryClient = useQueryClient(); const { showSuccess, showError } = useNotification(); const { hasPermission } = usePermissionContext(); // Tab from URL const [tab, setTab] = useState(() => { const t = Number(searchParams.get('tab')); return t >= 0 && t < TAB_COUNT ? t : 0; }); useEffect(() => { const t = Number(searchParams.get('tab')); if (t >= 0 && t < TAB_COUNT) setTab(t); }, [searchParams]); // ── State ── const [statusFilter, setStatusFilter] = useState(''); const [orderDialogOpen, setOrderDialogOpen] = useState(false); const [orderForm, setOrderForm] = useState({ ...emptyOrderForm }); const [vendorDialogOpen, setVendorDialogOpen] = useState(false); const [vendorForm, setVendorForm] = useState({ ...emptyVendorForm }); const [editingVendor, setEditingVendor] = useState(null); const [deleteVendorTarget, setDeleteVendorTarget] = useState(null); // ── Queries ── const { data: orders = [], isLoading: ordersLoading } = useQuery({ queryKey: ['bestellungen', statusFilter], queryFn: () => bestellungApi.getOrders(statusFilter ? { status: statusFilter } : undefined), }); const { data: vendors = [], isLoading: vendorsLoading } = useQuery({ queryKey: ['lieferanten'], queryFn: bestellungApi.getVendors, }); // ── Mutations ── const createOrder = useMutation({ mutationFn: (data: BestellungFormData) => bestellungApi.createOrder(data), onSuccess: (created) => { queryClient.invalidateQueries({ queryKey: ['bestellungen'] }); showSuccess('Bestellung erstellt'); setOrderDialogOpen(false); setOrderForm({ ...emptyOrderForm }); navigate(`/bestellungen/${created.id}`); }, onError: () => showError('Fehler beim Erstellen der Bestellung'), }); const createVendor = useMutation({ mutationFn: (data: LieferantFormData) => bestellungApi.createVendor(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['lieferanten'] }); showSuccess('Lieferant erstellt'); closeVendorDialog(); }, onError: () => showError('Fehler beim Erstellen des Lieferanten'), }); const updateVendor = useMutation({ mutationFn: ({ id, data }: { id: number; data: LieferantFormData }) => bestellungApi.updateVendor(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['lieferanten'] }); showSuccess('Lieferant aktualisiert'); closeVendorDialog(); }, onError: () => showError('Fehler beim Aktualisieren des Lieferanten'), }); const deleteVendor = useMutation({ mutationFn: (id: number) => bestellungApi.deleteVendor(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['lieferanten'] }); showSuccess('Lieferant gelöscht'); setDeleteVendorTarget(null); }, onError: () => showError('Fehler beim Löschen des Lieferanten'), }); // ── Dialog helpers ── function openEditVendor(v: Lieferant) { setEditingVendor(v); setVendorForm({ name: v.name, kontakt_name: v.kontakt_name || '', email: v.email || '', telefon: v.telefon || '', adresse: v.adresse || '', website: v.website || '', notizen: v.notizen || '' }); setVendorDialogOpen(true); } function closeVendorDialog() { setVendorDialogOpen(false); setEditingVendor(null); setVendorForm({ ...emptyVendorForm }); } function handleVendorSave() { if (!vendorForm.name.trim()) return; if (editingVendor) { updateVendor.mutate({ id: editingVendor.id, data: vendorForm }); } else { createVendor.mutate(vendorForm); } } function handleOrderSave() { if (!orderForm.bezeichnung.trim()) return; createOrder.mutate(orderForm); } // ── Render ── return ( Bestellungen { setTab(v); navigate(`/bestellungen?tab=${v}`, { replace: true }); }}> {/* ── Tab 0: Orders ── */} Status Filter Bezeichnung Lieferant Besteller Status Positionen Gesamtpreis Erstellt am {ordersLoading ? ( Laden... ) : orders.length === 0 ? ( Keine Bestellungen vorhanden ) : ( orders.map((o) => ( navigate(`/bestellungen/${o.id}`)} > {o.bezeichnung} {o.lieferant_name || '–'} {o.besteller_name || '–'} {o.items_count ?? 0} {formatCurrency(o.total_cost)} {formatDate(o.erstellt_am)} )) )}
{hasPermission('bestellungen:create') && ( setOrderDialogOpen(true)} aria-label="Neue Bestellung"> )}
{/* ── Tab 1: Vendors ── */} {hasPermission('bestellungen:create') && ( )} Name Kontakt E-Mail Telefon Website Aktionen {vendorsLoading ? ( Laden... ) : vendors.length === 0 ? ( Keine Lieferanten vorhanden ) : ( vendors.map((v) => ( {v.name} {v.kontakt_name || '–'} {v.email ? {v.email} : '–'} {v.telefon || '–'} {v.website ? ( {v.website} ) : '–'} openEditVendor(v)}> setDeleteVendorTarget(v)}> )) )}
{/* ── Create Order Dialog ── */} setOrderDialogOpen(false)} maxWidth="sm" fullWidth> Neue Bestellung setOrderForm((f) => ({ ...f, bezeichnung: e.target.value }))} /> o.name} value={vendors.find((v) => v.id === orderForm.lieferant_id) || null} onChange={(_e, v) => setOrderForm((f) => ({ ...f, lieferant_id: v?.id }))} renderInput={(params) => } /> setOrderForm((f) => ({ ...f, besteller_id: e.target.value }))} /> setOrderForm((f) => ({ ...f, budget: e.target.value ? Number(e.target.value) : undefined }))} inputProps={{ min: 0, step: 0.01 }} /> setOrderForm((f) => ({ ...f, notizen: e.target.value }))} /> {/* ── Create/Edit Vendor Dialog ── */} {editingVendor ? 'Lieferant bearbeiten' : 'Neuer Lieferant'} setVendorForm((f) => ({ ...f, name: e.target.value }))} /> setVendorForm((f) => ({ ...f, kontakt_name: e.target.value }))} /> setVendorForm((f) => ({ ...f, email: e.target.value }))} /> setVendorForm((f) => ({ ...f, telefon: e.target.value }))} /> setVendorForm((f) => ({ ...f, adresse: e.target.value }))} /> setVendorForm((f) => ({ ...f, website: e.target.value }))} /> setVendorForm((f) => ({ ...f, notizen: e.target.value }))} /> {/* ── Delete Vendor Confirm ── */} setDeleteVendorTarget(null)}> Lieferant löschen Soll der Lieferant {deleteVendorTarget?.name} wirklich gelöscht werden?
); }