Files
dashfront/src/components/NameDialog.jsx
2026-07-31 19:38:52 +02:00

106 lines
3.0 KiB
JavaScript

import { Component } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import Alert from '@mui/material/Alert';
import BackendError from './BackendError';
import SingleLineTextEdit from './SingleLineTextEdit';
import { backendErrorFrom, isBackendFailure } from '../utils/backendError';
/**
* Single-field name dialog (create/edit).
* Props: open, title, submitLabel, onClose, onSubmit({ name }),
* optional initialName (form start value when opened).
*/
class NameDialog extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
busy: false,
error: null,
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleClose = this.handleClose.bind(this);
}
componentDidUpdate(prevProps) {
if (this.props.open && !prevProps.open) {
this.setState({
name: this.props.initialName ?? '',
busy: false,
error: null,
});
}
}
handleClose() {
if (this.state.busy) return;
this.props.onClose();
}
async handleSubmit(event) {
event.preventDefault();
const name = this.state.name.trim();
if (!name) {
this.setState({ error: 'Bitte Name eingeben.' });
return;
}
this.setState({ busy: true, error: null });
try {
await this.props.onSubmit({ name });
this.props.onClose();
} catch (err) {
this.setState({ error: backendErrorFrom(err), busy: false });
}
}
render() {
const { open, title, submitLabel } = this.props;
const { name, busy, error } = this.state;
const canSave = name.trim() !== '';
return (
<Dialog open={open} onClose={this.handleClose} maxWidth="xs" fullWidth>
<DialogTitle>{title}</DialogTitle>
<Box component="form" onSubmit={this.handleSubmit} noValidate>
<DialogContent>
{error ? (
isBackendFailure(error) ? (
<BackendError error={error} sx={{ mb: 2 }} />
) : (
<Alert severity="error" sx={{ mb: 2 }}>
{typeof error === 'string' ? error : error.message}
</Alert>
)
) : null}
<SingleLineTextEdit
required
autoFocus
label="Name"
value={name}
disabled={busy}
onChange={(nextName) => this.setState({ name: nextName })}
/>
</DialogContent>
<DialogActions sx={{ px: 3, pb: 2 }}>
<Button type="button" onClick={this.handleClose} disabled={busy}>
Abbrechen
</Button>
<Button type="submit" variant="contained" disabled={busy || !canSave}>
{submitLabel}
</Button>
</DialogActions>
</Box>
</Dialog>
);
}
}
export default NameDialog;