This commit is contained in:
seb
2026-10-30 17:40:15 +01:00
parent 56d376c9bd
commit 9cb82745e3

View File

@@ -5,19 +5,18 @@ import Chip from '@mui/material/Chip';
import Divider from '@mui/material/Divider';
import IconButton from '@mui/material/IconButton';
import TextField from '@mui/material/TextField';
import Tooltip from '@mui/material/Tooltip';
import Typography from '@mui/material/Typography';
import AddIcon from '@mui/icons-material/Add';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import LocalPrintshopOutlinedIcon from '@mui/icons-material/LocalPrintshopOutlined';
import CheckCircleOutlinedIcon from '@mui/icons-material/CheckCircleOutlined';
import HourglassEmptyIcon from '@mui/icons-material/HourglassEmpty';
import QRCode from 'qrcode';
import { enqueueSnackbar } from 'notistack';
import BackendError from '../BackendError';
import companyAutomat from '../../automats/companyAutomat';
@@ -41,6 +40,80 @@ function formatDateTime(val) {
}
}
class AgentQrCode extends PureComponent {
constructor(props) {
super(props);
this.state = { dataUrl: null };
}
componentDidMount() {
this.generateQr();
}
componentDidUpdate(prevProps) {
if (prevProps.value !== this.props.value || prevProps.size !== this.props.size) {
this.generateQr();
}
}
async generateQr() {
const { value, size = 110 } = this.props;
if (!value) {
this.setState({ dataUrl: null });
return;
}
try {
const dataUrl = await QRCode.toDataURL(value, {
width: size,
margin: 1,
color: {
dark: '#000000',
light: '#ffffff',
},
errorCorrectionLevel: 'M',
});
this.setState({ dataUrl });
} catch (err) {
console.error('Failed to generate QR code:', err);
}
}
render() {
const { size = 110 } = this.props;
const { dataUrl } = this.state;
if (!dataUrl) {
return (
<Box
sx={{
width: size,
height: size,
bgcolor: 'action.hover',
borderRadius: 1,
}}
/>
);
}
return (
<Box
component="img"
src={dataUrl}
alt="Pairing QR Code"
sx={{
width: size,
height: size,
borderRadius: 1,
border: '1px solid',
borderColor: 'divider',
bgcolor: '#fff',
p: 0.5,
display: 'block',
flexShrink: 0,
}}
/>
);
}
}
export default class PrinterAgentSettingsPanel extends PureComponent {
constructor(props) {
super(props);
@@ -76,7 +149,7 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
error: state.printeragentsError ? backendErrorFrom(state.printeragentsError) : null,
}));
if (companyAutomat.state.printeragentsStatus === 'idle') {
void companyAutomat.actions.loadPrinterAgents().catch(() => {});
void companyAutomat.actions.loadPrinterAgents().catch(() => { });
}
}
@@ -385,7 +458,6 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
<Typography variant="subtitle1" fontWeight={600}>
{agent.name}
</Typography>
<Tooltip title="Name bearbeiten">
<IconButton
size="small"
onClick={() => this.handleStartRename(agent)}
@@ -394,7 +466,6 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
>
<EditOutlinedIcon sx={{ fontSize: 16 }} />
</IconButton>
</Tooltip>
</Box>
)}
@@ -433,33 +504,47 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
</Box>
</Box>
{/* Body: Pairing details or PIN info */}
{/* Body: Pairing details with QR code or Paired status info */}
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
flexWrap: 'wrap',
gap: 2,
flexDirection: 'column',
gap: 1.5,
pt: 0.5,
}}
>
{!isPaired ? (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, flexWrap: 'wrap' }}>
<Typography variant="body2" color="text.secondary">
(() => {
const domain = typeof window !== 'undefined' ? window.location.host : '';
const qrPayload = JSON.stringify({
domain,
pin: String(agent.pairingpin || ''),
});
return (
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: 2,
flexWrap: 'wrap',
bgcolor: 'action.hover',
p: 1.5,
borderRadius: 1.5,
border: '1px solid',
borderColor: 'warning.light',
}}
>
<Box sx={{ display: 'inline-flex' }}>
<AgentQrCode value={qrPayload} size={110} />
</Box>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1, flex: 1, minWidth: 220 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
<Typography variant="body2" color="text.secondary" sx={{ fontWeight: 500 }}>
Kopplungs-PIN:
</Typography>
<Tooltip title="PIN in die Zwischenablage kopieren">
<Chip
icon={<ContentCopyIcon sx={{ fontSize: 14 }} />}
label={agent.pairingpin || '—'}
onClick={() => {
if (agent.pairingpin) {
navigator.clipboard?.writeText(agent.pairingpin);
enqueueSnackbar('PIN in Zwischenablage kopiert.', { variant: 'info' });
}
}}
clickable
color="warning"
variant="filled"
sx={{
@@ -470,11 +555,23 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
px: 0.5,
}}
/>
</Tooltip>
<Typography variant="caption" color="text.secondary">
Geben Sie diesen PIN auf dem Drucker-Agent-Gerät ein.
</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
<Typography variant="body2" color="text.secondary" sx={{ fontWeight: 500 }}>
Domain:
</Typography>
<Chip
label={domain}
size="small"
variant="outlined"
sx={{ fontFamily: 'monospace', fontSize: '0.8rem' }}
/>
</Box>
</Box>
</Box>
);
})()
) : (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, flexWrap: 'wrap' }}>
{agent.clientserial ? (
@@ -513,12 +610,11 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
</Box>
)}
{/* Sort Order Controls */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, ml: 'auto' }}>
{/* Row with Sort Order Controls */}
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 0.5, pt: 0.5 }}>
<Typography variant="body2" color="text.secondary">
Reihenfolge:
</Typography>
<Tooltip title="Nach oben verschieben">
<span>
<IconButton
size="small"
@@ -529,8 +625,7 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
<ArrowUpwardIcon sx={{ fontSize: 16 }} />
</IconButton>
</span>
</Tooltip>
<Tooltip title="Nach unten verschieben">
<span>
<IconButton
size="small"
@@ -541,7 +636,6 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
<ArrowDownwardIcon sx={{ fontSize: 16 }} />
</IconButton>
</span>
</Tooltip>
<TextField
type="number"
size="small"