This commit is contained in:
seb
2026-08-05 20:15:39 +02:00
parent ff79d5b92c
commit caf08a3262
3 changed files with 76 additions and 14 deletions

View File

@@ -118,11 +118,19 @@ export class ApiClient {
const nameChange = body != null && Object.hasOwn(body, 'name'); const nameChange = body != null && Object.hasOwn(body, 'name');
if (nameChange) { if (nameChange) {
this.setArticleIndexName(sku, body.name); this.setArticleIndexName(sku, body.name);
this.setArticleName(sku, body.name);
} }
try { try {
return await this.#json('PATCH', `/api/article/${enc(sku)}`, { body }); const res = await this.#json('PATCH', `/api/article/${enc(sku)}`, { body });
this.setArticle(res.article);
return res;
} catch (err) { } catch (err) {
if (nameChange) this.clearArticleIndex(); if (nameChange) {
this.clearArticleIndex();
if (this.getArticle(sku)) {
void this.loadArticle(sku).catch(() => {});
}
}
throw err; throw err;
} }
}, },

View File

@@ -245,6 +245,13 @@ export class StorageManager extends ApiClient {
); );
} }
/** Patch local article detail name if already cached; no-op otherwise. */
setArticleName(sku, name) {
const current = this.#articlesBySku.get(String(sku));
if (!current) return;
this.setArticle({ ...current, name });
}
/** Drop local articleIndex if loaded (forces reload on next read). */ /** Drop local articleIndex if loaded (forces reload on next read). */
clearArticleIndex() { clearArticleIndex() {
if (!this.#articleIndexCache.value) return; if (!this.#articleIndexCache.value) return;

View File

@@ -178,21 +178,46 @@ class NameDisplay extends Component {
} }
class NameEdit extends Component { class NameEdit extends Component {
constructor(props) {
super(props);
this.state = {
name: props.name,
categoryIds: [...(props.categoryIds ?? [])],
};
}
componentDidMount() {
const { onNameDraftChange, onCategoryIdsDraftChange } = this.props;
onNameDraftChange?.(this.state.name);
onCategoryIdsDraftChange?.(this.state.categoryIds);
}
handleNameChange = (name) => {
this.setState({ name });
this.props.onNameDraftChange?.(name);
};
handleCategoryIdsChange = (categoryIds) => {
this.setState({ categoryIds });
this.props.onCategoryIdsDraftChange?.(categoryIds);
};
render() { render() {
const { name, categoryIds } = this.props; const { name, categoryIds } = this.state;
return ( return (
<Box sx={columnSx}> <Box sx={columnSx}>
<Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}> <Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}>
<SingleLineTextEdit <SingleLineTextEdit
label="Name" label="Name"
value={name} value={name}
onChange={() => {}} onChange={this.handleNameChange}
sx={articleNameFieldSx} sx={articleNameFieldSx}
/> />
</Box> </Box>
<CategoryPills <CategoryPills
categoryIds={categoryIds} categoryIds={categoryIds}
editMode editMode
onCategoryIdsChange={this.handleCategoryIdsChange}
/> />
</Box> </Box>
); );
@@ -202,34 +227,58 @@ class NameEdit extends Component {
export default class ArticleViewName extends Component { export default class ArticleViewName extends Component {
static contextType = StorageManagerContext; static contextType = StorageManagerContext;
handleSave = async (draft) => { constructor(props) {
super(props);
this.state = {
nameDraft: null,
categoryIdsDraft: null,
};
}
handleNameDraftChange = (name) => {
this.setState({ nameDraft: name });
};
handleCategoryIdsDraftChange = (categoryIds) => {
this.setState({ categoryIdsDraft: categoryIds });
};
handleSave = async () => {
const { article: articleData, onArticleUpdated } = this.props; const { article: articleData, onArticleUpdated } = this.props;
const { nameDraft, categoryIdsDraft } = this.state;
const store = this.context; const store = this.context;
const name = draft.name.trim(); const name = nameDraft.trim();
const categoryIds = draft.categoryIds ?? []; const categoryIds = categoryIdsDraft;
const nameChanged = name !== String(articleData.name ?? '').trim(); const nameChanged = name !== String(articleData.name ?? '').trim();
const categoriesChanged = categoryIdsChanged(categoryIds, articleData.categoryIds); const categoriesChanged = categoryIdsChanged(categoryIds, articleData.categoryIds);
let article = null; let article = null;
if (nameChanged) { if (nameChanged) {
console.log('nameChanged', name, articleData.name); console.log('storing name update', name, articleData.name);
const nameRes = await store.article.update(articleData.sku, { name }); const nameRes = await store.article.update(articleData.sku, { name });
article = nameRes.article; article = nameRes.article;
} }
if (categoriesChanged) { if (categoriesChanged) {
console.log('storing categories update', categoryIds, articleData.categoryIds);
const catRes = await store.article.setCategories(articleData.sku, { categoryIds }); const catRes = await store.article.setCategories(articleData.sku, { categoryIds });
article = catRes.article; article = catRes.article;
} }
if (article) onArticleUpdated?.(article); if (article) onArticleUpdated?.(article);
this.setState({ nameDraft: null, categoryIdsDraft: null });
}; };
render() { render() {
const { article: articleData } = this.props; const { article: articleData } = this.props;
const { nameDraft, categoryIdsDraft } = this.state;
const savedCategoryIds = articleData.categoryIds ?? []; const savedCategoryIds = articleData.categoryIds ?? [];
const value = { name: articleData.name ?? '', categoryIds: [...savedCategoryIds] }; const value = { name: articleData.name ?? '', categoryIds: [...savedCategoryIds] };
const draft =
nameDraft != null && categoryIdsDraft != null
? { name: nameDraft, categoryIds: categoryIdsDraft }
: null;
return ( return (
<EditablePanelTile <EditablePanelTile
@@ -239,22 +288,20 @@ export default class ArticleViewName extends Component {
color="#ffffff" color="#ffffff"
value={value} value={value}
onSave={this.handleSave} onSave={this.handleSave}
isDirty={draftDirty} isDirty={() => draft != null && draftDirty(draft, value)}
canSave={draftValid} canSave={() => draft != null && draftValid(draft)}
display={ display={
<NameDisplay <NameDisplay
name={value.name} name={value.name}
categoryIds={value.categoryIds} categoryIds={value.categoryIds}
/> />
} }
edit={ edit={
<NameEdit <NameEdit
name={value.name} name={value.name}
categoryIds={value.categoryIds} categoryIds={value.categoryIds}
onNameChange={() => {}} onNameDraftChange={this.handleNameDraftChange}
onCategoryIdsChange={() => {}} onCategoryIdsDraftChange={this.handleCategoryIdsDraftChange}
onIsDirtyChange={() => {}}
/> />
} }
/> />