Gate article detail on a store-backed cache so the view paints once.
Sku page loads/caches the article before mounting ArticleView; the view reads sync from StorageManager instead of fetching again.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { requireArray, requireDefined, requireObject } from '../utils/apiShape';
|
||||
import { notifyError } from '../utils/notify';
|
||||
import { parseCategoryTreeResponse } from '../store/categorySlice';
|
||||
import { ApiClient } from './ApiClient';
|
||||
|
||||
/**
|
||||
@@ -73,6 +74,8 @@ export class StorageManager extends ApiClient {
|
||||
#events = null;
|
||||
/** @type {ReturnType<typeof createCache> | null} */
|
||||
#articleIndexCache = null;
|
||||
/** @type {Map<string, object>} sku → article detail */
|
||||
#articlesBySku = new Map();
|
||||
/** @type {Map<string, Set<() => void>>} sku → refreshers */
|
||||
#historyWatchers = new Map();
|
||||
|
||||
@@ -81,6 +84,52 @@ export class StorageManager extends ApiClient {
|
||||
this.#initCaches();
|
||||
}
|
||||
|
||||
/** Settled article detail for sku, or undefined. */
|
||||
getArticle(sku) {
|
||||
return this.#articlesBySku.get(String(sku));
|
||||
}
|
||||
|
||||
/** Keep local article detail in sync after GET/PATCH/PUT responses. */
|
||||
setArticle(article) {
|
||||
requireObject(article, 'article');
|
||||
requireDefined(article.sku, 'article.sku');
|
||||
this.#articlesBySku.set(String(article.sku), article);
|
||||
return article;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/article/{sku}, cache detail, return article.
|
||||
* @param {string} sku
|
||||
*/
|
||||
async loadArticle(sku) {
|
||||
const res = await this.article.get(sku);
|
||||
requireObject(res, 'GET /api/article/:sku');
|
||||
requireObject(res.article, 'article');
|
||||
return this.setArticle(res.article);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsed category map + root id from settled caches, or null if any piece missing.
|
||||
* @returns {{ categories: object, rootCategoryId: unknown } | null}
|
||||
*/
|
||||
getCategoryState() {
|
||||
const treeData = this.categoryTree;
|
||||
const companies = this.companies;
|
||||
const session = this.authMe;
|
||||
if (treeData == null || companies == null || session == null) return null;
|
||||
|
||||
const companyId = session.user?.selectedCompanyId;
|
||||
if (companyId == null) return null;
|
||||
const company = companies.find((c) => c.id === companyId);
|
||||
if (company == null) return null;
|
||||
|
||||
const parsed = parseCategoryTreeResponse(treeData, company.rootCategoryId);
|
||||
return {
|
||||
categories: parsed.categories,
|
||||
rootCategoryId: parsed.rootCategoryId,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch article history, then refetch whenever SSE emits `article-<sku>`.
|
||||
* @param {string} sku
|
||||
|
||||
Reference in New Issue
Block a user