import { Automat } from 'react-automat'; import { brand as brandApi } from '../api'; import authAutomat from './authAutomat'; /** * @typedef {Object} BrandState * @property {Array} 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; }, /** * Delete a brand by id. * @param {number} id */ async remove(id) { await brandApi.delete(id); const brands = brandAutomat.state.brands.filter((b) => b.id !== id); brandAutomat.setState({ brands }); }, /** * Add / update brand image. * @param {number} id * @param {Blob|File} file */ async addImage(id, file) { const res = await brandApi.addImage(id, file); await brandAutomat.actions.load(); return res.brand; }, /** * Delete brand image. * @param {number} id */ async deleteImage(id) { const res = await brandApi.deleteImage(id); await brandAutomat.actions.load(); return res.brand; }, /** 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} */ 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;