This commit is contained in:
seb
2026-10-28 00:46:23 +01:00
parent 0453680c59
commit e45f35e97b
6 changed files with 90 additions and 65 deletions

View File

@@ -1,4 +1,4 @@
import { Component } from 'react';
import { PureComponent } from 'react';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import CircularProgress from '@mui/material/CircularProgress';
@@ -17,7 +17,7 @@ import { enqueueSnackbar } from 'notistack';
import BackendError from '../BackendError';
import { number as numberApi } from '../../api';
import companyAutomat from '../../automats/companyAutomat';
import { requireArray, requireDefined, requireObject } from '../../utils/apiShape';
import { requireDefined, requireObject } from '../../utils/apiShape';
import { backendErrorFrom } from '../../utils/backendError';
import { notifyError } from '../../utils/notify';
@@ -31,44 +31,76 @@ function parseNext(value) {
return Number.isInteger(n) && n >= 0 ? n : null;
}
export default class NumberSettingsPanel extends Component {
function buildDrafts(numbers, prevDrafts = {}) {
return Object.fromEntries(
(Array.isArray(numbers) ? numbers : []).map((row) => {
const existing = prevDrafts[row.id];
return [
row.id,
existing?.busy
? existing
: {
prefix: row.prefix ?? '',
padding: row.padding != null ? String(row.padding) : '',
next: row.next != null ? String(row.next) : '',
busy: false,
saveError: null,
},
];
}),
);
}
export default class NumberSettingsPanel extends PureComponent {
constructor(props) {
super(props);
const numbers = Array.isArray(companyAutomat.state.numbers)
? companyAutomat.state.numbers
: [];
const numbersStatus = companyAutomat.state.numbersStatus;
this.state = {
status: 'loading',
error: null,
numbers: [],
status:
numbersStatus === 'ready'
? 'ready'
: numbersStatus === 'failed'
? 'failed'
: 'loading',
error: companyAutomat.state.numbersError
? backendErrorFrom(companyAutomat.state.numbersError)
: null,
numbers,
// id → { prefix, padding, next, busy, saveError }
drafts: {},
drafts: buildDrafts(numbers),
};
this.handleRetry = this.handleRetry.bind(this);
this.handleSave = this.handleSave.bind(this);
}
componentDidMount() {
void this.load();
this._unmounted = false;
this.unsub = companyAutomat.subscribe(this, (state) => {
const numbers = Array.isArray(state.numbers) ? state.numbers : [];
return {
status:
state.numbersStatus === 'ready'
? 'ready'
: state.numbersStatus === 'failed'
? 'failed'
: 'loading',
error: state.numbersError ? backendErrorFrom(state.numbersError) : null,
numbers,
drafts:
numbers !== this.state.numbers
? buildDrafts(numbers, this.state.drafts)
: this.state.drafts,
};
});
}
async load() {
this.setState({ status: 'loading', error: null });
try {
const numbers = requireArray(
await companyAutomat.actions.reloadNumbers(),
'numbers',
);
const drafts = Object.fromEntries(
numbers.map((row) => [
row.id,
{
prefix: row.prefix ?? '',
padding: row.padding != null ? String(row.padding) : '',
next: row.next != null ? String(row.next) : '',
busy: false,
saveError: null,
},
]),
);
this.setState({ status: 'ready', numbers, drafts });
await companyAutomat.actions.reloadNumbers();
} catch (err) {
notifyError(err);
this.setState({ status: 'failed', error: backendErrorFrom(err) });
@@ -145,8 +177,9 @@ export default class NumberSettingsPanel extends Component {
requireObject(data.number, 'number');
const updated = requireDefined(data.number, 'number');
const numbers = this.state.numbers.map((n) => (n.id === id ? { ...n, ...body } : n));
await companyAutomat.actions.reloadNumbers();
const numbers = companyAutomat.actions.replaceNumbers(
this.state.numbers.map((n) => (n.id === id ? { ...n, ...updated } : n)),
);
this.setState({
numbers,
drafts: {
@@ -174,6 +207,7 @@ export default class NumberSettingsPanel extends Component {
componentWillUnmount() {
this._unmounted = true;
this.unsub?.();
}
render() {