import { PureComponent } from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Card from '@mui/material/Card'; import Chip from '@mui/material/Chip'; import Divider from '@mui/material/Divider'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined'; import PaymentsOutlinedIcon from '@mui/icons-material/PaymentsOutlined'; import AddIcon from '@mui/icons-material/Add'; import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import { PanelTile } from 'dashgui/panels'; import { formatDate } from './manifestConfig'; import { formatPrice } from '../../utils/price'; import { typeLabel, typeIcon } from './OrderPaymentList'; import ShipmentDetailDialog from './ShipmentDetailDialog'; import { GREEN_PANEL, YELLOW_PANEL, WHITE, } from '../../colors'; /** * Renders 1-wide associated document tiles for an order in edit mode: * 1. Lieferscheine / Auslieferungen (Shipments) * 2. Zahlungen (Payments) */ export class OrderDocumentsTiles extends PureComponent { constructor(props) { super(props); this.state = { selectedShipment: null, }; this.handleOpenShipment = this.handleOpenShipment.bind(this); this.handleCloseShipment = this.handleCloseShipment.bind(this); this.handleOpenPayments = this.handleOpenPayments.bind(this); } handleOpenShipment(sh) { this.setState({ selectedShipment: sh }); } handleCloseShipment() { this.setState({ selectedShipment: null }); } handleOpenPayments() { if (this.props.navigate) { this.props.navigate('/auftrag/zahlungen'); } } renderShipmentsTile() { const { shipments = [], shipped, delivered, navigate, deliverDisabled } = this.props; const statusLabel = delivered ? 'Geliefert' : shipped ? 'Versendet' : shipments.length > 0 ? 'Teilweise' : 'Offen'; const statusColor = delivered || shipped ? 'success' : shipments.length > 0 ? 'warning' : 'default'; return ( {shipments.length > 0 ? ( {shipments.map((sh) => { const carrier = sh.shippings?.[0]?.carrier; const tracking = sh.shippings?.[0]?.trackingCode; const posCount = sh.lineCount ?? sh.lines?.length ?? 0; return ( this.handleOpenShipment(sh)} sx={{ p: 1.25, bgcolor: WHITE, cursor: 'pointer', transition: 'all 0.15s ease', '&:hover': { boxShadow: '0 2px 8px rgba(0,0,0,0.1)', borderColor: 'primary.main', }, }} > {sh.number} {sh.date ? formatDate(sh.date) : '–'} {navigate && ( { e.stopPropagation(); navigate(`/auftrag/ausliefern?shipmentId=${sh.id}`); }} sx={{ p: 0.25, ml: 0.5, color: 'text.secondary', '&:hover': { color: 'primary.main' } }} > )} {sh.externalNumber ? ( Ref: {sh.externalNumber} ) : null} {posCount} Pos. {carrier || tracking ? ( ) : null} ); })} ) : null} ); } renderPaymentsTile() { const { payments = [], paid, paidTotal, orderTotal } = this.props; const tot = Number(orderTotal) || 0; const pd = Number(paidTotal) || 0; const openAmount = Math.max(0, tot - pd); const statusLabel = paid ? 'Bezahlt' : pd > 0 ? 'Teilzahlung' : 'Offen'; const statusColor = paid ? 'success' : pd > 0 ? 'warning' : 'error'; return ( {/* Financial KPI Card */} Summe: {formatPrice(tot)} Bezahlt: {formatPrice(pd)} Offen: 0 ? 'error.main' : 'text.secondary' }}> {formatPrice(openAmount)} {payments.length > 0 ? ( {payments.map((pay) => { const pType = pay.type || pay.paymentType || pay.payment_type; return ( {typeIcon(pType, { fontSize: 16 })} {typeLabel(pType)} {pay.date ? ( {formatDate(pay.date)} ) : null} +{formatPrice(pay.amount)} ); })} ) : null} ); } render() { return ( <> {this.renderShipmentsTile()} {this.renderPaymentsTile()} ); } } export default OrderDocumentsTiles;