no redux
This commit is contained in:
81
src/automats/brandAutomat.js
Normal file
81
src/automats/brandAutomat.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Automat } from 'react-automat';
|
||||
import { brand as brandApi } from '../api';
|
||||
import authAutomat from './authAutomat';
|
||||
|
||||
/**
|
||||
* @typedef {Object} BrandState
|
||||
* @property {Array<object>} brands
|
||||
* @property {'idle'|'loading'|'succeeded'|'failed'} status
|
||||
* @property {string|null} error
|
||||
*/
|
||||
|
||||
/** @type {BrandState} */
|
||||
const initialState = {
|
||||
brands: [],
|
||||
status: 'idle',
|
||||
error: null,
|
||||
};
|
||||
|
||||
function sortBrands(brands) {
|
||||
return [...brands].sort((a, b) =>
|
||||
String(a.name ?? '').localeCompare(String(b.name ?? ''), 'de'),
|
||||
);
|
||||
}
|
||||
|
||||
let brandAutomat;
|
||||
|
||||
const actions = {
|
||||
/** Load all brands for the selected company. */
|
||||
async load() {
|
||||
brandAutomat.setState({ status: 'loading', error: null });
|
||||
try {
|
||||
const res = await brandApi.list();
|
||||
const brands = sortBrands(Array.isArray(res.brands) ? res.brands : []);
|
||||
brandAutomat.setState({ brands, status: 'succeeded' });
|
||||
return brands;
|
||||
} catch (err) {
|
||||
brandAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Upsert a brand (create or update by name).
|
||||
* @param {{ name: string, gsprpinfo?: string }} body
|
||||
*/
|
||||
async upsert(body) {
|
||||
const res = await brandApi.upsert(body);
|
||||
const row = res.brand;
|
||||
const brands = sortBrands([
|
||||
...brandAutomat.state.brands.filter((b) => b.id !== row.id),
|
||||
row,
|
||||
]);
|
||||
brandAutomat.setState({ brands });
|
||||
return row;
|
||||
},
|
||||
|
||||
/** Reset to idle state (called on logout / company switch). */
|
||||
reset() {
|
||||
brandAutomat.setState(initialState);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Global brand state container.
|
||||
* Loads automatically when authAutomat reaches 'authed' with a selectedCompanyId.
|
||||
*
|
||||
* @type {Automat<BrandState>}
|
||||
*/
|
||||
brandAutomat = new Automat(initialState, actions, { name: 'brand' });
|
||||
|
||||
// Subscribe to auth changes
|
||||
authAutomat.subscribe((auth) => {
|
||||
const companyId = auth.user?.selectedCompanyId;
|
||||
if (auth.status === 'authed' && companyId) {
|
||||
void brandAutomat.actions.load();
|
||||
} else if (auth.status === 'anon') {
|
||||
brandAutomat.actions.reset();
|
||||
}
|
||||
});
|
||||
|
||||
export default brandAutomat;
|
||||
Reference in New Issue
Block a user