no redux
This commit is contained in:
96
src/automats/companyAutomat.js
Normal file
96
src/automats/companyAutomat.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import { Automat } from 'react-automat';
|
||||
import { company as companyApi } from '../api';
|
||||
import authAutomat from './authAutomat';
|
||||
import { normalizeCompany } from '../utils/companyForm';
|
||||
|
||||
/**
|
||||
* @typedef {Object} CompanyState
|
||||
* @property {object|null} current Normalized company object for the selected company.
|
||||
* @property {'idle'|'loading'|'succeeded'|'failed'} status
|
||||
* @property {string|null} error
|
||||
*/
|
||||
|
||||
/** @type {CompanyState} */
|
||||
const initialState = {
|
||||
current: null,
|
||||
status: 'idle',
|
||||
error: null,
|
||||
};
|
||||
|
||||
let companyAutomat;
|
||||
|
||||
const actions = {
|
||||
/**
|
||||
* Load the company data for the currently selected company.
|
||||
* @returns {Promise<object|null>}
|
||||
*/
|
||||
async load() {
|
||||
const companyId = authAutomat.state.user?.selectedCompanyId;
|
||||
if (!companyId) return null;
|
||||
companyAutomat.setState({ status: 'loading', error: null });
|
||||
try {
|
||||
const data = await companyApi.getById(companyId);
|
||||
const normalized = normalizeCompany(data.company);
|
||||
companyAutomat.setState({ current: normalized, status: 'succeeded' });
|
||||
return normalized;
|
||||
} catch (err) {
|
||||
companyAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update company details and refresh cached data.
|
||||
* @param {object} payload
|
||||
*/
|
||||
async update(payload) {
|
||||
const companyId = authAutomat.state.user?.selectedCompanyId;
|
||||
if (!companyId) throw new Error('Kein Unternehmen ausgewählt.');
|
||||
companyAutomat.setState({ status: 'loading', error: null });
|
||||
try {
|
||||
await companyApi.update(companyId, payload);
|
||||
const data = await companyApi.getById(companyId);
|
||||
const normalized = normalizeCompany(data.company, payload);
|
||||
companyAutomat.setState({ current: normalized, status: 'succeeded' });
|
||||
return normalized;
|
||||
} catch (err) {
|
||||
companyAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
/** Reset to idle (called on logout / company switch). */
|
||||
reset() {
|
||||
companyAutomat.setState(initialState);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Global company state container.
|
||||
* Loads automatically when authAutomat reaches 'authed' with a selectedCompanyId.
|
||||
*
|
||||
* @type {Automat<CompanyState>}
|
||||
*/
|
||||
companyAutomat = new Automat(initialState, actions, { name: 'company' });
|
||||
|
||||
// Subscribe to auth changes — load when authed, reset when logged out / anon
|
||||
authAutomat.subscribe((auth) => {
|
||||
const companyId = auth.user?.selectedCompanyId;
|
||||
if (auth.status === 'authed' && companyId) {
|
||||
void companyAutomat.actions.load();
|
||||
} else if (auth.status === 'anon') {
|
||||
companyAutomat.actions.reset();
|
||||
}
|
||||
});
|
||||
|
||||
// Selectors (plain functions for use outside React)
|
||||
export const selectCurrentCompany = () => companyAutomat.state.current;
|
||||
export const selectCompanyId = () => companyAutomat.state.current?.id ?? null;
|
||||
export const selectCompanyStatus = () => companyAutomat.state.status;
|
||||
export const selectCompanyName = () => companyAutomat.state.current?.name;
|
||||
export const selectCompanyIso639 = () => companyAutomat.state.current?.iso639;
|
||||
export const selectCompanyTaxrate = () => companyAutomat.state.current?.taxrate ?? null;
|
||||
export const selectCompanyReducedTaxrate = () => companyAutomat.state.current?.reducedtaxrate ?? null;
|
||||
export const selectCompanyRootCategoryId = () => companyAutomat.state.current?.rootCategoryId ?? null;
|
||||
|
||||
export default companyAutomat;
|
||||
Reference in New Issue
Block a user