u
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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={() => {}}
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user