diff --git a/src/routes/auftrag/lieferarten.jsx b/src/routes/auftrag/lieferarten.jsx deleted file mode 100644 index a47c726..0000000 --- a/src/routes/auftrag/lieferarten.jsx +++ /dev/null @@ -1,270 +0,0 @@ -import { PureComponent, createRef } from 'react'; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import CircularProgress from '@mui/material/CircularProgress'; -import List from '@mui/material/List'; -import Typography from '@mui/material/Typography'; -import Sortable from 'sortablejs'; -import { enqueueSnackbar } from 'notistack'; -import BackendError from '../../components/BackendError'; -import SingleLineTextEdit from 'dashgui/SingleLineTextEdit'; -import { PanelTile, PanelTileGrid } from 'dashgui/panels'; -import withNavigate from '../../components/withNavigate'; -import { backendErrorFrom } from '../../utils/backendError'; -import { notifyError } from '../../utils/notify'; -import carrierAutomat from '../../automats/carrierAutomat'; -import { CarrierItem } from '../../components/carrier'; -import { GREEN_PANEL } from '../../colors'; - -class LieferartenSearchField extends PureComponent { - constructor(props) { - super(props); - const initial = carrierAutomat.state.filter || ''; - this.state = { - input: initial, - submitting: false, - }; - this.handleSubmit = this.handleSubmit.bind(this); - } - - componentDidMount() { - this.unsub = carrierAutomat.subscribe(this, (state) => ({ - input: state.filter, - })); - } - - componentWillUnmount() { - this.unsub?.(); - } - - onInputChange(input) { - this.setState({ input }); - carrierAutomat.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 carrierAutomat.actions.create({ - name, - hasPackages: true, - isReverse: false, - }); - enqueueSnackbar(`Lieferart „${row.name || name}“ angelegt.`, { variant: 'success' }); - this.setState({ input: '', submitting: false }); - carrierAutomat.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 ( - - - - this.onInputChange(next)} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.preventDefault(); - void this.handleSubmit(); - } - }} - /> - - - - - ); - } -} - -class AuftragLieferartenPage extends PureComponent { - constructor(props) { - super(props); - const initialCarriers = - carrierAutomat.state.filteredCarriers ?? carrierAutomat.state.carriers ?? []; - this.state = { - status: carrierAutomat.state.status === 'ready' ? 'ready' : 'loading', - error: carrierAutomat.state.error ? backendErrorFrom(carrierAutomat.state.error) : null, - carriers: initialCarriers, - filter: carrierAutomat.state.filter ?? '', - }; - this.searchRef = createRef(); - this.listRef = createRef(); - this._sortable = null; - this._cancelled = false; - this.handleRetry = this.handleRetry.bind(this); - this._initSortable = this._initSortable.bind(this); - this._destroySortable = this._destroySortable.bind(this); - } - - componentDidMount() { - this._cancelled = false; - - this.unsub = carrierAutomat.subscribe(this, (state) => ({ - carriers: state.filteredCarriers ?? state.carriers, - filter: state.filter ?? '', - status: state.status, - error: state.error ? backendErrorFrom(state.error) : null, - })); - - if (carrierAutomat.state.status !== 'ready') { - void carrierAutomat.actions.load().catch((err) => notifyError(err)); - } else { - this._initSortable(); - } - } - - componentDidUpdate(prevProps, prevState) { - if ( - prevState.status !== this.state.status || - prevState.carriers !== this.state.carriers || - prevState.filter !== this.state.filter - ) { - if (this.state.status === 'ready') { - this._initSortable(); - } - } - } - - componentWillUnmount() { - this._cancelled = true; - this.unsub?.(); - this._destroySortable(); - } - - _initSortable() { - this._destroySortable(); - const el = this.listRef.current; - if (!el) return; - - const isFiltered = Boolean(this.state.filter?.trim()); - - this._sortable = Sortable.create(el, { - handle: '.drag-handle', - animation: 150, - ghostClass: 'sortable-ghost', - chosenClass: 'sortable-chosen', - disabled: isFiltered, - onEnd: (evt) => { - const { oldIndex, newIndex } = evt; - if (oldIndex === newIndex) return; - - this.setState( - (prev) => { - const next = [...prev.carriers]; - const [moved] = next.splice(oldIndex, 1); - next.splice(newIndex, 0, moved); - return { carriers: next }; - }, - () => { - const ids = this.state.carriers.map((c) => c.id); - void this._persistOrder(ids); - } - ); - }, - }); - } - - _destroySortable() { - this._sortable?.destroy(); - this._sortable = null; - } - - async _persistOrder(carrierIds) { - try { - await carrierAutomat.actions.reorder(carrierIds); - } catch (err) { - if (this._cancelled) return; - notifyError(err); - void carrierAutomat.actions.reload(); - } - } - - handleRetry() { - void carrierAutomat.actions.load().catch((err) => notifyError(err)); - } - - render() { - const { status, error, carriers, filter } = this.state; - - if (status === 'loading' || status === 'idle') { - return ( - - - - ); - } - - if (status === 'failed') { - return ; - } - - const trimmedFilter = filter?.trim() ?? ''; - - return ( - <> - - - - - {carriers.length === 0 ? ( - - {trimmedFilter - ? `Keine Treffer für „${trimmedFilter}“.` - : 'Noch keine Lieferarten angelegt.'} - - ) : ( - carriers.map((c) => ( - - )) - )} - - - - - ); - } -} - -export { CarrierItem, LieferartenSearchField }; -export default withNavigate(AuftragLieferartenPage);