143 lines
4.2 KiB
JavaScript
143 lines
4.2 KiB
JavaScript
import { Automat } from 'react-automat';
|
|
import { posterminal as posterminalApi } from '../api';
|
|
import authAutomat from './authAutomat';
|
|
import companyAutomat from './companyAutomat';
|
|
|
|
/**
|
|
* @typedef {Object} PosterminalState
|
|
* @property {Array<object>} terminals
|
|
* @property {number|string|null} companyId
|
|
* @property {'idle'|'loading'|'succeeded'|'failed'} status
|
|
* @property {string|null} error
|
|
*/
|
|
|
|
/** @type {PosterminalState} */
|
|
const initialState = {
|
|
terminals: [],
|
|
companyId: null,
|
|
status: 'idle',
|
|
error: null,
|
|
};
|
|
|
|
let posterminalAutomat;
|
|
|
|
const actions = {
|
|
/** Load all posterminals for the selected company. */
|
|
async load() {
|
|
const companyId = companyAutomat.state.current?.id;
|
|
if (!companyId) return [];
|
|
posterminalAutomat.setState({ status: 'loading', error: null });
|
|
try {
|
|
const res = await posterminalApi.list();
|
|
const terminals = Array.isArray(res.posterminals) ? res.posterminals : [];
|
|
posterminalAutomat.setState({ terminals, companyId, status: 'succeeded' });
|
|
return terminals;
|
|
} catch (err) {
|
|
posterminalAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
|
throw err;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Create a new posterminal.
|
|
* @param {{ name: string }} param0
|
|
*/
|
|
async create({ name }) {
|
|
const res = await posterminalApi.create({ name });
|
|
const terminal = res.posterminal;
|
|
posterminalAutomat.setState({
|
|
terminals: [...posterminalAutomat.state.terminals, terminal],
|
|
});
|
|
return terminal;
|
|
},
|
|
|
|
/**
|
|
* Delete a posterminal.
|
|
* @param {number} terminalId
|
|
*/
|
|
async delete(terminalId) {
|
|
await posterminalApi.delete(terminalId);
|
|
posterminalAutomat.setState({
|
|
terminals: posterminalAutomat.state.terminals.filter((t) => t.id !== terminalId),
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Enable all categories on a terminal.
|
|
* @param {{ terminalId: number }} param0
|
|
*/
|
|
async enableAll({ terminalId }) {
|
|
const res = await posterminalApi.enableAllCategories(terminalId);
|
|
patchTerminalCategories(terminalId, res.categoryIds);
|
|
return res;
|
|
},
|
|
|
|
/**
|
|
* Disable all categories on a terminal.
|
|
* @param {{ terminalId: number }} param0
|
|
*/
|
|
async disableAll({ terminalId }) {
|
|
const res = await posterminalApi.disableAllCategories(terminalId);
|
|
patchTerminalCategories(terminalId, res.categoryIds);
|
|
return res;
|
|
},
|
|
|
|
/**
|
|
* Enable a specific category on a terminal.
|
|
* @param {{ terminalId: number, categoryId: number }} param0
|
|
*/
|
|
async enableCategory({ terminalId, categoryId }) {
|
|
const res = await posterminalApi.enableCategory(terminalId, categoryId);
|
|
patchTerminalCategories(terminalId, res.categoryIds);
|
|
return res;
|
|
},
|
|
|
|
/**
|
|
* Disable a specific category on a terminal.
|
|
* @param {{ terminalId: number, categoryId: number }} param0
|
|
*/
|
|
async disableCategory({ terminalId, categoryId }) {
|
|
const res = await posterminalApi.disableCategory(terminalId, categoryId);
|
|
patchTerminalCategories(terminalId, res.categoryIds);
|
|
return res;
|
|
},
|
|
|
|
/** Reset to idle state (called on logout / company switch). */
|
|
reset() {
|
|
posterminalAutomat.setState(initialState);
|
|
},
|
|
};
|
|
|
|
function patchTerminalCategories(terminalId, categoryIds) {
|
|
posterminalAutomat.setState({
|
|
terminals: posterminalAutomat.state.terminals.map((t) =>
|
|
t.id === terminalId ? { ...t, categoryIds } : t,
|
|
),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Global posterminal state container.
|
|
* Loads automatically when authAutomat reaches 'authed' with a selectedCompanyId.
|
|
*
|
|
* @type {Automat<PosterminalState>}
|
|
*/
|
|
posterminalAutomat = new Automat(initialState, actions, { name: 'posterminal' });
|
|
|
|
// Subscribe to auth changes
|
|
authAutomat.subscribe((auth) => {
|
|
const companyId = auth.user?.selectedCompanyId;
|
|
if (auth.status === 'authed' && companyId) {
|
|
void posterminalAutomat.actions.load();
|
|
} else if (auth.status === 'anon') {
|
|
posterminalAutomat.actions.reset();
|
|
}
|
|
});
|
|
|
|
// Selectors
|
|
export const selectPosterminals = () => posterminalAutomat.state.terminals;
|
|
export const selectPosterminalStatus = () => posterminalAutomat.state.status;
|
|
export const selectHasPosterminals = () => posterminalAutomat.state.terminals.length > 0;
|
|
|
|
export default posterminalAutomat;
|