no redux
This commit is contained in:
142
src/automats/posterminalAutomat.js
Normal file
142
src/automats/posterminalAutomat.js
Normal file
@@ -0,0 +1,142 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user