u
This commit is contained in:
@@ -27,6 +27,7 @@ import PointOfSaleIcon from '@mui/icons-material/PointOfSale';
|
|||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import BackendError from './BackendError';
|
import BackendError from './BackendError';
|
||||||
import SingleLineTextEdit from './SingleLineTextEdit';
|
import SingleLineTextEdit from './SingleLineTextEdit';
|
||||||
|
import { StorageManagerContext } from '../api/storageManager';
|
||||||
import {
|
import {
|
||||||
loadCurrentCompany,
|
loadCurrentCompany,
|
||||||
selectCompanyStatus,
|
selectCompanyStatus,
|
||||||
@@ -34,12 +35,9 @@ import {
|
|||||||
updateCompany as updateCompanyThunk,
|
updateCompany as updateCompanyThunk,
|
||||||
} from '../store/companySlice';
|
} from '../store/companySlice';
|
||||||
import {
|
import {
|
||||||
loadPosterminals,
|
|
||||||
createPosterminal,
|
createPosterminal,
|
||||||
deletePosterminal,
|
deletePosterminal,
|
||||||
enableAllTerminalCategories,
|
enableAllTerminalCategories,
|
||||||
selectPosterminals,
|
|
||||||
selectPosterminalStatus,
|
|
||||||
} from '../store/posterminalSlice';
|
} from '../store/posterminalSlice';
|
||||||
import { loadCategoryTree } from '../store/categorySlice';
|
import { loadCategoryTree } from '../store/categorySlice';
|
||||||
import { ISO639_OPTIONS, parseTaxRate } from '../utils/companyForm';
|
import { ISO639_OPTIONS, parseTaxRate } from '../utils/companyForm';
|
||||||
@@ -47,6 +45,8 @@ import { backendErrorFrom, isBackendFailure } from '../utils/backendError';
|
|||||||
import { notifyError } from '../utils/notify';
|
import { notifyError } from '../utils/notify';
|
||||||
|
|
||||||
class CompanySettingsDialog extends Component {
|
class CompanySettingsDialog extends Component {
|
||||||
|
static contextType = StorageManagerContext;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -59,11 +59,13 @@ class CompanySettingsDialog extends Component {
|
|||||||
newTerminalName: '',
|
newTerminalName: '',
|
||||||
creatingTerminal: false,
|
creatingTerminal: false,
|
||||||
enableAllForNew: true,
|
enableAllForNew: true,
|
||||||
|
terminals: [],
|
||||||
};
|
};
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
this.syncFormFromCompany = this.syncFormFromCompany.bind(this);
|
this.syncFormFromCompany = this.syncFormFromCompany.bind(this);
|
||||||
this.handleCreateTerminal = this.handleCreateTerminal.bind(this);
|
this.handleCreateTerminal = this.handleCreateTerminal.bind(this);
|
||||||
this.handleDeleteTerminal = this.handleDeleteTerminal.bind(this);
|
this.handleDeleteTerminal = this.handleDeleteTerminal.bind(this);
|
||||||
|
this.loadTerminals = this.loadTerminals.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
@@ -75,10 +77,7 @@ class CompanySettingsDialog extends Component {
|
|||||||
} else if (companyStatus !== 'loading') {
|
} else if (companyStatus !== 'loading') {
|
||||||
void this.props.loadCurrentCompany();
|
void this.props.loadCurrentCompany();
|
||||||
}
|
}
|
||||||
// Load posterminals when dialog opens
|
void this.loadTerminals();
|
||||||
if (this.props.posterminalStatus !== 'loading') {
|
|
||||||
void this.props.loadPosterminals();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (open && company && company !== prevProps.company) {
|
if (open && company && company !== prevProps.company) {
|
||||||
this.syncFormFromCompany(company);
|
this.syncFormFromCompany(company);
|
||||||
@@ -94,6 +93,15 @@ class CompanySettingsDialog extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async loadTerminals() {
|
||||||
|
try {
|
||||||
|
const terminals = await this.context.posterminalPromise;
|
||||||
|
this.setState({ terminals });
|
||||||
|
} catch (err) {
|
||||||
|
notifyError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async handleCreateTerminal() {
|
async handleCreateTerminal() {
|
||||||
const { newTerminalName, enableAllForNew } = this.state;
|
const { newTerminalName, enableAllForNew } = this.state;
|
||||||
const trimmed = newTerminalName.trim();
|
const trimmed = newTerminalName.trim();
|
||||||
@@ -101,7 +109,7 @@ class CompanySettingsDialog extends Component {
|
|||||||
this.setState({ creatingTerminal: true });
|
this.setState({ creatingTerminal: true });
|
||||||
try {
|
try {
|
||||||
const terminal = await this.props.createPosterminal({ name: trimmed }).unwrap();
|
const terminal = await this.props.createPosterminal({ name: trimmed }).unwrap();
|
||||||
|
|
||||||
// If "enable all" toggle is on, enable all categories for this terminal
|
// If "enable all" toggle is on, enable all categories for this terminal
|
||||||
if (enableAllForNew && terminal.id) {
|
if (enableAllForNew && terminal.id) {
|
||||||
await this.props.enableAllTerminalCategories({ terminalId: terminal.id }).unwrap();
|
await this.props.enableAllTerminalCategories({ terminalId: terminal.id }).unwrap();
|
||||||
@@ -109,7 +117,8 @@ class CompanySettingsDialog extends Component {
|
|||||||
this.props.loadCategoryTree();
|
this.props.loadCategoryTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ newTerminalName: '' });
|
const terminals = await this.context.updatePosterminal();
|
||||||
|
this.setState({ newTerminalName: '', terminals });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notifyError(err);
|
notifyError(err);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -120,6 +129,8 @@ class CompanySettingsDialog extends Component {
|
|||||||
async handleDeleteTerminal(terminal) {
|
async handleDeleteTerminal(terminal) {
|
||||||
try {
|
try {
|
||||||
await this.props.deletePosterminal({ terminalId: terminal.id }).unwrap();
|
await this.props.deletePosterminal({ terminalId: terminal.id }).unwrap();
|
||||||
|
const terminals = await this.context.updatePosterminal();
|
||||||
|
this.setState({ terminals });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notifyError(err);
|
notifyError(err);
|
||||||
}
|
}
|
||||||
@@ -262,73 +273,65 @@ class CompanySettingsDialog extends Component {
|
|||||||
<Divider sx={{ my: 1 }} />
|
<Divider sx={{ my: 1 }} />
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
{this.props.posterminalStatus === 'loading' ? (
|
<List dense sx={{ py: 0 }}>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 2 }}>
|
{this.state.terminals.map((terminal) => (
|
||||||
<CircularProgress size={24} />
|
<ListItem
|
||||||
</Box>
|
key={terminal.id}
|
||||||
) : (
|
sx={{ px: 0, py: 0.5 }}
|
||||||
<>
|
>
|
||||||
<List dense sx={{ py: 0 }}>
|
<PointOfSaleIcon sx={{ mr: 1, color: 'text.secondary', fontSize: 20 }} />
|
||||||
{this.props.terminals.map((terminal) => (
|
<ListItemText
|
||||||
<ListItem
|
primary={terminal.name}
|
||||||
key={terminal.id}
|
secondary={`PIN: ${terminal.pairingpin}`}
|
||||||
sx={{ px: 0, py: 0.5 }}
|
|
||||||
>
|
|
||||||
<PointOfSaleIcon sx={{ mr: 1, color: 'text.secondary', fontSize: 20 }} />
|
|
||||||
<ListItemText
|
|
||||||
primary={terminal.name}
|
|
||||||
secondary={`PIN: ${terminal.pairingpin}`}
|
|
||||||
/>
|
|
||||||
<ListItemSecondaryAction>
|
|
||||||
<IconButton
|
|
||||||
edge="end"
|
|
||||||
size="small"
|
|
||||||
onClick={() => this.handleDeleteTerminal(terminal)}
|
|
||||||
disabled={busy || this.state.creatingTerminal}
|
|
||||||
>
|
|
||||||
<DeleteOutlinedIcon fontSize="small" />
|
|
||||||
</IconButton>
|
|
||||||
</ListItemSecondaryAction>
|
|
||||||
</ListItem>
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
|
|
||||||
<Box sx={{ mt: 1, display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
||||||
<TextField
|
|
||||||
size="small"
|
|
||||||
placeholder="Neues Terminal..."
|
|
||||||
value={this.state.newTerminalName}
|
|
||||||
onChange={(e) => this.setState({ newTerminalName: e.target.value })}
|
|
||||||
disabled={busy || this.state.creatingTerminal}
|
|
||||||
autoComplete="off"
|
|
||||||
onKeyDown={(e) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
e.preventDefault();
|
|
||||||
this.handleCreateTerminal();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
sx={{ flex: 1 }}
|
|
||||||
/>
|
/>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
<ListItemSecondaryAction>
|
||||||
<PointOfSaleIcon sx={{ fontSize: 18, color: 'text.secondary' }} />
|
<IconButton
|
||||||
<Switch
|
edge="end"
|
||||||
size="small"
|
size="small"
|
||||||
checked={this.state.enableAllForNew}
|
onClick={() => this.handleDeleteTerminal(terminal)}
|
||||||
onChange={(e) => this.setState({ enableAllForNew: e.target.checked })}
|
|
||||||
disabled={busy || this.state.creatingTerminal}
|
disabled={busy || this.state.creatingTerminal}
|
||||||
/>
|
>
|
||||||
</Box>
|
<DeleteOutlinedIcon fontSize="small" />
|
||||||
<Button
|
</IconButton>
|
||||||
variant="contained"
|
</ListItemSecondaryAction>
|
||||||
size="small"
|
</ListItem>
|
||||||
onClick={this.handleCreateTerminal}
|
))}
|
||||||
disabled={busy || this.state.creatingTerminal || !this.state.newTerminalName.trim()}
|
</List>
|
||||||
>
|
|
||||||
Hinzufügen
|
<Box sx={{ mt: 1, display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
</Button>
|
<TextField
|
||||||
</Box>
|
size="small"
|
||||||
</>
|
placeholder="Neues Terminal..."
|
||||||
)}
|
value={this.state.newTerminalName}
|
||||||
|
onChange={(e) => this.setState({ newTerminalName: e.target.value })}
|
||||||
|
disabled={busy || this.state.creatingTerminal}
|
||||||
|
autoComplete="off"
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
this.handleCreateTerminal();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
sx={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||||
|
<PointOfSaleIcon sx={{ fontSize: 18, color: 'text.secondary' }} />
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
checked={this.state.enableAllForNew}
|
||||||
|
onChange={(e) => this.setState({ enableAllForNew: e.target.checked })}
|
||||||
|
disabled={busy || this.state.creatingTerminal}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
onClick={this.handleCreateTerminal}
|
||||||
|
disabled={busy || this.state.creatingTerminal || !this.state.newTerminalName.trim()}
|
||||||
|
>
|
||||||
|
Hinzufügen
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
@@ -350,14 +353,11 @@ class CompanySettingsDialog extends Component {
|
|||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
company: selectCurrentCompany(state),
|
company: selectCurrentCompany(state),
|
||||||
companyStatus: selectCompanyStatus(state),
|
companyStatus: selectCompanyStatus(state),
|
||||||
terminals: selectPosterminals(state),
|
|
||||||
posterminalStatus: selectPosterminalStatus(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
loadCurrentCompany: () => dispatch(loadCurrentCompany()),
|
loadCurrentCompany: () => dispatch(loadCurrentCompany()),
|
||||||
updateCompany: (payload) => dispatch(updateCompanyThunk(payload)),
|
updateCompany: (payload) => dispatch(updateCompanyThunk(payload)),
|
||||||
loadPosterminals: () => dispatch(loadPosterminals()),
|
|
||||||
createPosterminal: (payload) => dispatch(createPosterminal(payload)),
|
createPosterminal: (payload) => dispatch(createPosterminal(payload)),
|
||||||
deletePosterminal: (payload) => dispatch(deletePosterminal(payload)),
|
deletePosterminal: (payload) => dispatch(deletePosterminal(payload)),
|
||||||
enableAllTerminalCategories: (payload) => dispatch(enableAllTerminalCategories(payload)),
|
enableAllTerminalCategories: (payload) => dispatch(enableAllTerminalCategories(payload)),
|
||||||
|
|||||||
Reference in New Issue
Block a user