u
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { Automat } from 'react-automat';
|
||||
import { article as articleApi } from '../api';
|
||||
import { requireDefined, requireObject } from '../utils/apiShape';
|
||||
import authAutomat from './authAutomat';
|
||||
import articleIndexAutomat, { setArticleIndexName } from './articleIndexAutomat';
|
||||
|
||||
/**
|
||||
* @typedef {Object} ArtikelState
|
||||
@@ -125,6 +127,117 @@ const actions = {
|
||||
artikelAutomat.setState({ bySku });
|
||||
},
|
||||
|
||||
/**
|
||||
* PATCH /api/article/:sku with optimistic name handling.
|
||||
*
|
||||
* A `name` in the body is applied to both caches immediately so the tile
|
||||
* does not flicker, then rolled back from the server on failure.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {object} body Patch body (`{ name?, unitamount?, unitSi?, track_stock? }`).
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async update(sku, body) {
|
||||
const key = String(sku);
|
||||
const nameChange = body != null && Object.hasOwn(body, 'name');
|
||||
if (nameChange) {
|
||||
setArticleIndexName(key, body.name);
|
||||
actions.setArticleName(key, body.name);
|
||||
}
|
||||
try {
|
||||
const res = await articleApi.update(key, body);
|
||||
actions.setArticle(res.article);
|
||||
return res;
|
||||
} catch (err) {
|
||||
if (nameChange) {
|
||||
// The optimistic patch was wrong: drop the index entry and refetch.
|
||||
articleIndexAutomat.actions.reset();
|
||||
if (hasArticle(key)) {
|
||||
void actions.loadArticle(key).catch(() => {});
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/article/:sku/eans → refreshes the cached article.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {Array<string>} eans Replacement EAN list.
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async setEans(sku, eans) {
|
||||
const res = await articleApi.setEansBySku(String(sku), eans);
|
||||
actions.setArticle(res.article);
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/article/:sku/brand → refreshes the cached article.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {{ brandId: number|null }} body Brand payload.
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async setBrand(sku, body) {
|
||||
const res = await articleApi.setBrandIdBySku(String(sku), body?.brandId);
|
||||
actions.setArticle(res.article);
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/article/:sku/categories → refreshes the cached article.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {Array<number>} categoryIds Replacement category ids.
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async setCategories(sku, categoryIds) {
|
||||
const res = await articleApi.setCategories(String(sku), categoryIds);
|
||||
actions.setArticle(res.article);
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/article/:sku/prices → refreshes the cached article.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {Array<object>} prices Net price rows.
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async setPrices(sku, prices) {
|
||||
const res = await articleApi.setPrices(String(sku), prices);
|
||||
actions.setArticle(res.article);
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/article/:sku/weight → refreshes the cached article.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {object} body Weight payload.
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async setWeight(sku, body) {
|
||||
const res = await articleApi.setWeight(String(sku), body);
|
||||
actions.setArticle(res.article);
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/article/:sku/track_stock → refreshes the cached article.
|
||||
*
|
||||
* @param {string} sku Article SKU.
|
||||
* @param {boolean|object} body Flag or full body.
|
||||
* @returns {Promise<object>} Response body containing the fresh `article`.
|
||||
*/
|
||||
async setTrackStock(sku, body) {
|
||||
const res = await articleApi.setTrackStock(String(sku), body);
|
||||
if (res?.article) actions.setArticle(res.article);
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* Forgets every cached article.
|
||||
*
|
||||
@@ -187,4 +300,12 @@ export function selectArticle(sku) {
|
||||
return artikelAutomat.select(createArticleSelector(sku));
|
||||
}
|
||||
|
||||
// Drop cached articles on logout. A company switch keeps them; the SSE hub
|
||||
// reconnects and revalidates whatever is on screen.
|
||||
authAutomat.subscribe((auth) => {
|
||||
if (auth.status === 'anon') {
|
||||
actions.clear();
|
||||
}
|
||||
});
|
||||
|
||||
export default artikelAutomat;
|
||||
|
||||
Reference in New Issue
Block a user