u
This commit is contained in:
107
src/components/NameDialog.jsx
Normal file
107
src/components/NameDialog.jsx
Normal file
@@ -0,0 +1,107 @@
|
||||
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 TextField from '@mui/material/TextField';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import BackendError from './BackendError';
|
||||
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}
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
required
|
||||
autoFocus
|
||||
label="Name"
|
||||
value={name}
|
||||
disabled={busy}
|
||||
onChange={(e) => this.setState({ name: e.target.value })}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</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;
|
||||
Reference in New Issue
Block a user