176 lines
4.7 KiB
JavaScript
176 lines
4.7 KiB
JavaScript
import { PureComponent, createRef } from 'react';
|
|
import Box from '@mui/material/Box';
|
|
import Button from '@mui/material/Button';
|
|
import CircularProgress from '@mui/material/CircularProgress';
|
|
import BackendError from '../../components/BackendError';
|
|
import SingleLineTextEdit from 'dashgui/SingleLineTextEdit';
|
|
import FillSpace from 'dashgui/FillSpace';
|
|
import { PanelTile, PanelTileGrid } from 'dashgui/panels';
|
|
import { backendErrorFrom } from '../../utils/backendError';
|
|
import { notifyError } from '../../utils/notify';
|
|
import { setLastArticleSku } from '../../automats';
|
|
import brandAutomat from '../../automats/brandAutomat';
|
|
import { enqueueSnackbar } from 'notistack';
|
|
import {
|
|
ArtikelMarke,
|
|
ArtikelMarkeNew,
|
|
} from '../../components/brand';
|
|
import {
|
|
PURPLE_PANEL,
|
|
} from '../../colors';
|
|
|
|
class ArtikelMarkenSearchField extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
input: brandAutomat.state.filter ?? '',
|
|
submitting: false,
|
|
};
|
|
this.handleSubmit = this.handleSubmit.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.unsub = brandAutomat.subscribe(this, (state) => ({
|
|
input: state.filter,
|
|
}));
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.unsub?.();
|
|
}
|
|
|
|
onInputChange(input) {
|
|
this.setState({ input });
|
|
brandAutomat.actions.filter(input);
|
|
}
|
|
|
|
async handleSubmit() {
|
|
const name = this.state.input.trim();
|
|
if (!name || this.state.submitting) return;
|
|
|
|
this.setState({ submitting: true });
|
|
try {
|
|
const row = await brandAutomat.actions.create({ name });
|
|
enqueueSnackbar(`Marke „${row.name || name}“ angelegt.`, { variant: 'success' });
|
|
this.setState({ input: '', submitting: false });
|
|
brandAutomat.actions.filter('');
|
|
} catch (err) {
|
|
this.setState({ submitting: false });
|
|
notifyError(err);
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const { inputRef } = this.props;
|
|
const { input, submitting } = this.state;
|
|
const canSubmit = Boolean(input.trim()) && !submitting;
|
|
|
|
return (
|
|
<PanelTileGrid>
|
|
<Box
|
|
ref={inputRef}
|
|
sx={{
|
|
gridColumn: {
|
|
xs: '1 / -1',
|
|
sm: 'span 2',
|
|
md: 'span 2',
|
|
},
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 1,
|
|
pb: 2,
|
|
}}
|
|
>
|
|
<SingleLineTextEdit
|
|
sx={{ flex: 1 }}
|
|
size="small"
|
|
search
|
|
clear
|
|
value={input}
|
|
disabled={submitting}
|
|
onChange={(next) => this.onInputChange(next)}
|
|
/>
|
|
<Button
|
|
variant="contained"
|
|
disabled={!canSubmit}
|
|
onClick={() => void this.handleSubmit()}
|
|
>
|
|
Hinzufügen
|
|
</Button>
|
|
</Box>
|
|
</PanelTileGrid>
|
|
);
|
|
}
|
|
}
|
|
|
|
class ArtikelMarkenPage extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
status: brandAutomat.state.status,
|
|
error: brandAutomat.state.error ? backendErrorFrom({ message: brandAutomat.state.error }) : null,
|
|
brands: brandAutomat.state.filteredBrands ?? brandAutomat.state.brands,
|
|
totalCount: brandAutomat.state.brands?.length ?? 0,
|
|
};
|
|
this.searchRef = createRef();
|
|
this.handleRetry = this.handleRetry.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
setLastArticleSku(null);
|
|
|
|
this.unsub = brandAutomat.subscribe(this, (state) => ({
|
|
brands: state.filteredBrands,
|
|
totalCount: state.brands?.length ?? 0,
|
|
status: state.status,
|
|
error: state.error ? backendErrorFrom({ message: state.error }) : null,
|
|
}));
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.unsub?.();
|
|
}
|
|
|
|
handleRetry() {
|
|
void brandAutomat.actions.load().catch((err) => notifyError(err));
|
|
}
|
|
|
|
render() {
|
|
const { status, error, brands } = this.state;
|
|
|
|
if (status === 'loading' || status === 'idle') {
|
|
return (
|
|
<Box sx={{ display: 'flex', justifyContent: 'center', py: 6 }}>
|
|
<CircularProgress />
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
if (status === 'failed') {
|
|
return <BackendError error={error} onRetry={this.handleRetry} />;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<ArtikelMarkenSearchField inputRef={this.searchRef} />
|
|
<PanelTileGrid>
|
|
<PanelTile wide={2} minHeight={0} color={PURPLE_PANEL} sx={{ pb: 0 }}>
|
|
<FillSpace
|
|
aboveRef={[this.searchRef]}
|
|
reserveBottom={32}
|
|
minPageSize={8}
|
|
minHeight={0}
|
|
items={brands}
|
|
totalCount={this.state.totalCount}
|
|
renderItem={ArtikelMarke}
|
|
/>
|
|
</PanelTile>
|
|
</PanelTileGrid>
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
|
|
export { ArtikelMarke, ArtikelMarkeNew, ArtikelMarkenSearchField };
|
|
export default ArtikelMarkenPage;
|