4.6 KiB
brandAutomat
Source File:
src/automats/brandAutomat.js
Registration Key:'brand'(Automat.get('brand')/window.__AUTOMATS__.get('brand'))
1. Overview & Purpose
brandAutomat manages the active company's catalog brands (manufacturers). Brands are referenced by articles for catalog organization, filtering, and GPSR (General Product Safety Regulation) manufacturer compliance info.
Core Responsibilities
- Company Scoping: Caches all brands for the currently selected company.
- Alphabetical Sorting: Automatically sorts brands by name using German (
'de') collation. - Autonomous Bootstrap: Automatically triggers
load()whenauthAutomatenters'authed'with a selected company, and callsreset()when the session ends. - Upsert Mutation: Handles creating or updating a brand with immediate in-memory cache synchronization.
2. State Structure
interface Brand {
id: number | string;
name: string;
gsprpinfo?: string | null;
[key: string]: any;
}
interface BrandState {
/** Alphabetically sorted list of company brands. */
brands: Array<Brand>;
/** Async lifecycle status. */
status: 'idle' | 'loading' | 'succeeded' | 'failed';
/** Error message if loading failed. */
error: string | null;
}
Initial State
const initialState = {
brands: [],
status: 'idle',
error: null,
};
3. Configuration & Options
new Automat(initialState, actions, { name: 'brand' });
name:'brand'persist:false
4. Actions & Methods
Access actions via brandAutomat.actions.<method>().
load(): Promise<Array<Brand>>
Fetches all brands for the current company via GET /api/brand. Sorts them by name, updates status to 'succeeded', and returns the array. If the request fails, sets status to 'failed' and records error.
upsert(body: { name: string, gsprpinfo?: string }): Promise<Brand>
Creates or updates a brand via POST /api/brand/upsert. Merges the updated brand into state.brands, re-sorts the list, updates state, and returns the modified brand object.
reset(): void
Resets the state back to initialState (brands: [], status: 'idle', error: null).
5. Cross-Automat Subscriptions
brandAutomat subscribes to authAutomat at module initialization:
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();
}
});
6. Usage Examples
A. React PureComponent Brand Selector Dropdown
import { PureComponent } from 'react';
import PropTypes from 'prop-types';
import brandAutomat from '../automats/brandAutomat';
export class BrandSelect extends PureComponent {
static propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
onChange: PropTypes.func.isRequired,
};
constructor(props) {
super(props);
this.state = {
brands: brandAutomat.state.brands,
status: brandAutomat.state.status,
};
}
componentDidMount() {
this.unsub = brandAutomat.subscribe(this, ['brands', 'status']);
if (this.state.status === 'idle') {
brandAutomat.actions.load().catch(console.error);
}
}
componentWillUnmount() {
this.unsub?.();
}
render() {
const { brands, status } = this.state;
const { value, onChange } = this.props;
if (status === 'loading') {
return <select disabled><option>Marken laden...</option></select>;
}
return (
<select value={value ?? ''} onChange={(e) => onChange(e.target.value)}>
<option value="">-- Keine Marke --</option>
{brands.map((b) => (
<option key={b.id} value={b.id}>{b.name}</option>
))}
</select>
);
}
}
B. Creating or Updating a Brand
import brandAutomat from '../automats/brandAutomat';
async function handleSaveBrand(name, gsprpinfo) {
try {
const brand = await brandAutomat.actions.upsert({ name, gsprpinfo });
console.log('Saved brand:', brand);
} catch (err) {
console.error('Failed to save brand:', err);
}
}
7. Best Practices & Gotchas
- Automatic Loading: In normal usage, you rarely need to invoke
load()manually;authAutomattriggers it as soon as the user logs in or switches company. - Alphabetical Guarantee: The
brandsarray in state is guaranteed to be sorted alphabetically (localeComparewith German rules).