medusa-product-helper 0.0.24 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -152,23 +152,61 @@ const useOrderMetadataConfig = () => useMetadataConfig("order");
152
152
  const CONFIG_DOCS_URL$2 = "https://docs.medusajs.com/admin/extension-points/widgets#product-category-details";
153
153
  const CategoryMetadataTableWidget = ({ data }) => {
154
154
  const { data: descriptors = [], isPending, isError } = useCategoryMetadataConfig();
155
- const metadata = (data == null ? void 0 : data.metadata) ?? {};
156
- const [baselineMetadata, setBaselineMetadata] = react.useState(metadata);
155
+ const categoryId = (data == null ? void 0 : data.id) ?? void 0;
156
+ const [baselineMetadata, setBaselineMetadata] = react.useState(
157
+ (data == null ? void 0 : data.metadata) ?? {}
158
+ );
157
159
  const queryClient = reactQuery.useQueryClient();
160
+ const previousCategoryIdRef = react.useRef(categoryId);
161
+ const isInitializedRef = react.useRef(false);
162
+ const dataRef = react.useRef(data);
163
+ const descriptorsRef = react.useRef(descriptors);
164
+ react.useEffect(() => {
165
+ dataRef.current = data;
166
+ descriptorsRef.current = descriptors;
167
+ }, [data, descriptors]);
168
+ react.useEffect(() => {
169
+ var _a;
170
+ if (previousCategoryIdRef.current === categoryId && isInitializedRef.current) {
171
+ return;
172
+ }
173
+ const categoryIdChanged = previousCategoryIdRef.current !== categoryId;
174
+ if (categoryIdChanged || !isInitializedRef.current) {
175
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? ((_a = dataRef.current) == null ? void 0 : _a.metadata) ?? {};
176
+ const currentDescriptors = descriptorsRef.current.length > 0 ? descriptorsRef.current : descriptors;
177
+ if (currentDescriptors.length === 0) {
178
+ return;
179
+ }
180
+ previousCategoryIdRef.current = categoryId;
181
+ setBaselineMetadata(currentMetadata);
182
+ const newInitialState = buildInitialFormState(currentDescriptors, currentMetadata);
183
+ setValues(newInitialState);
184
+ isInitializedRef.current = true;
185
+ }
186
+ }, [categoryId]);
187
+ const metadataStringRef = react.useRef("");
158
188
  react.useEffect(() => {
159
- setBaselineMetadata(metadata);
160
- }, [metadata]);
189
+ const hasCategoryData = !!data;
190
+ const descriptorsLoaded = descriptors.length > 0;
191
+ const sameCategory = previousCategoryIdRef.current === categoryId;
192
+ const notInitialized = !isInitializedRef.current;
193
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
194
+ const currentMetadataString = JSON.stringify(currentMetadata);
195
+ const metadataChanged = currentMetadataString !== metadataStringRef.current;
196
+ if (hasCategoryData && descriptorsLoaded && sameCategory && (notInitialized || metadataChanged)) {
197
+ const newInitialState = buildInitialFormState(descriptors, currentMetadata);
198
+ setBaselineMetadata(currentMetadata);
199
+ setValues(newInitialState);
200
+ metadataStringRef.current = currentMetadataString;
201
+ isInitializedRef.current = true;
202
+ }
203
+ }, [data, descriptors.length, categoryId]);
161
204
  const initialState = react.useMemo(
162
205
  () => buildInitialFormState(descriptors, baselineMetadata),
163
206
  [descriptors, baselineMetadata]
164
207
  );
165
- const [values, setValues] = react.useState(
166
- initialState
167
- );
208
+ const [values, setValues] = react.useState({});
168
209
  const [isSaving, setIsSaving] = react.useState(false);
169
- react.useEffect(() => {
170
- setValues(initialState);
171
- }, [initialState]);
172
210
  const errors = react.useMemo(() => {
173
211
  return descriptors.reduce((acc, descriptor) => {
174
212
  const error = validateValueForDescriptor(descriptor, values[descriptor.key]);
@@ -234,6 +272,15 @@ const CategoryMetadataTableWidget = ({ data }) => {
234
272
  await queryClient.invalidateQueries({
235
273
  queryKey: ["product-categories"]
236
274
  });
275
+ await queryClient.invalidateQueries({
276
+ queryKey: ["product-category", data.id]
277
+ });
278
+ if (data.id) {
279
+ queryClient.refetchQueries({
280
+ queryKey: ["product-category", data.id]
281
+ }).catch(() => {
282
+ });
283
+ }
237
284
  } catch (error) {
238
285
  ui.toast.error(error instanceof Error ? error.message : "Save failed");
239
286
  } finally {
@@ -248,7 +295,7 @@ const CategoryMetadataTableWidget = ({ data }) => {
248
295
  ] }),
249
296
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Structured metadata mapped to the keys you configured in the plugin options." })
250
297
  ] }),
251
- isPending ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "error", label: "Configuration unavailable", children: [
298
+ isPending || !isInitializedRef.current || Object.keys(values).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "error", label: "Configuration unavailable", children: [
252
299
  "Unable to load metadata configuration for this plugin. Confirm that the plugin is registered with options in ",
253
300
  /* @__PURE__ */ jsxRuntime.jsx("code", { children: "medusa-config.ts" }),
254
301
  "."
@@ -1017,14 +1064,14 @@ const ProductMetadataTableWidget = ({ data }) => {
1017
1064
  }, [productId]);
1018
1065
  const metadataStringRef = react.useRef("");
1019
1066
  react.useEffect(() => {
1020
- const hasMetadata = (data == null ? void 0 : data.metadata) && Object.keys(data.metadata).length > 0;
1067
+ const hasProductData = !!data;
1021
1068
  const descriptorsLoaded = descriptors.length > 0;
1022
1069
  const sameProduct = previousProductIdRef.current === productId;
1023
1070
  const notInitialized = !isInitializedRef.current;
1024
- const currentMetadataString = hasMetadata ? JSON.stringify(data.metadata) : "";
1071
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
1072
+ const currentMetadataString = JSON.stringify(currentMetadata);
1025
1073
  const metadataChanged = currentMetadataString !== metadataStringRef.current;
1026
- if (hasMetadata && descriptorsLoaded && sameProduct && (notInitialized || metadataChanged)) {
1027
- const currentMetadata = data.metadata ?? {};
1074
+ if (hasProductData && descriptorsLoaded && sameProduct && (notInitialized || metadataChanged)) {
1028
1075
  const newInitialState = buildInitialFormState(descriptors, currentMetadata);
1029
1076
  setBaselineMetadata(currentMetadata);
1030
1077
  setValues(newInitialState);
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { defineWidgetConfig } from "@medusajs/admin-sdk";
3
3
  import { Container, Heading, Badge, Text, Skeleton, InlineTip, Button, Switch, Textarea, Input, toast } from "@medusajs/ui";
4
- import { useState, useEffect, useMemo, useRef } from "react";
4
+ import { useState, useRef, useEffect, useMemo } from "react";
5
5
  import { useQuery, useQueryClient } from "@tanstack/react-query";
6
6
  const METADATA_FIELD_TYPES = ["number", "text", "file", "bool"];
7
7
  const VALID_FIELD_TYPES = new Set(METADATA_FIELD_TYPES);
@@ -151,23 +151,61 @@ const useOrderMetadataConfig = () => useMetadataConfig("order");
151
151
  const CONFIG_DOCS_URL$2 = "https://docs.medusajs.com/admin/extension-points/widgets#product-category-details";
152
152
  const CategoryMetadataTableWidget = ({ data }) => {
153
153
  const { data: descriptors = [], isPending, isError } = useCategoryMetadataConfig();
154
- const metadata = (data == null ? void 0 : data.metadata) ?? {};
155
- const [baselineMetadata, setBaselineMetadata] = useState(metadata);
154
+ const categoryId = (data == null ? void 0 : data.id) ?? void 0;
155
+ const [baselineMetadata, setBaselineMetadata] = useState(
156
+ (data == null ? void 0 : data.metadata) ?? {}
157
+ );
156
158
  const queryClient = useQueryClient();
159
+ const previousCategoryIdRef = useRef(categoryId);
160
+ const isInitializedRef = useRef(false);
161
+ const dataRef = useRef(data);
162
+ const descriptorsRef = useRef(descriptors);
163
+ useEffect(() => {
164
+ dataRef.current = data;
165
+ descriptorsRef.current = descriptors;
166
+ }, [data, descriptors]);
167
+ useEffect(() => {
168
+ var _a;
169
+ if (previousCategoryIdRef.current === categoryId && isInitializedRef.current) {
170
+ return;
171
+ }
172
+ const categoryIdChanged = previousCategoryIdRef.current !== categoryId;
173
+ if (categoryIdChanged || !isInitializedRef.current) {
174
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? ((_a = dataRef.current) == null ? void 0 : _a.metadata) ?? {};
175
+ const currentDescriptors = descriptorsRef.current.length > 0 ? descriptorsRef.current : descriptors;
176
+ if (currentDescriptors.length === 0) {
177
+ return;
178
+ }
179
+ previousCategoryIdRef.current = categoryId;
180
+ setBaselineMetadata(currentMetadata);
181
+ const newInitialState = buildInitialFormState(currentDescriptors, currentMetadata);
182
+ setValues(newInitialState);
183
+ isInitializedRef.current = true;
184
+ }
185
+ }, [categoryId]);
186
+ const metadataStringRef = useRef("");
157
187
  useEffect(() => {
158
- setBaselineMetadata(metadata);
159
- }, [metadata]);
188
+ const hasCategoryData = !!data;
189
+ const descriptorsLoaded = descriptors.length > 0;
190
+ const sameCategory = previousCategoryIdRef.current === categoryId;
191
+ const notInitialized = !isInitializedRef.current;
192
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
193
+ const currentMetadataString = JSON.stringify(currentMetadata);
194
+ const metadataChanged = currentMetadataString !== metadataStringRef.current;
195
+ if (hasCategoryData && descriptorsLoaded && sameCategory && (notInitialized || metadataChanged)) {
196
+ const newInitialState = buildInitialFormState(descriptors, currentMetadata);
197
+ setBaselineMetadata(currentMetadata);
198
+ setValues(newInitialState);
199
+ metadataStringRef.current = currentMetadataString;
200
+ isInitializedRef.current = true;
201
+ }
202
+ }, [data, descriptors.length, categoryId]);
160
203
  const initialState = useMemo(
161
204
  () => buildInitialFormState(descriptors, baselineMetadata),
162
205
  [descriptors, baselineMetadata]
163
206
  );
164
- const [values, setValues] = useState(
165
- initialState
166
- );
207
+ const [values, setValues] = useState({});
167
208
  const [isSaving, setIsSaving] = useState(false);
168
- useEffect(() => {
169
- setValues(initialState);
170
- }, [initialState]);
171
209
  const errors = useMemo(() => {
172
210
  return descriptors.reduce((acc, descriptor) => {
173
211
  const error = validateValueForDescriptor(descriptor, values[descriptor.key]);
@@ -233,6 +271,15 @@ const CategoryMetadataTableWidget = ({ data }) => {
233
271
  await queryClient.invalidateQueries({
234
272
  queryKey: ["product-categories"]
235
273
  });
274
+ await queryClient.invalidateQueries({
275
+ queryKey: ["product-category", data.id]
276
+ });
277
+ if (data.id) {
278
+ queryClient.refetchQueries({
279
+ queryKey: ["product-category", data.id]
280
+ }).catch(() => {
281
+ });
282
+ }
236
283
  } catch (error) {
237
284
  toast.error(error instanceof Error ? error.message : "Save failed");
238
285
  } finally {
@@ -247,7 +294,7 @@ const CategoryMetadataTableWidget = ({ data }) => {
247
294
  ] }),
248
295
  /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: "Structured metadata mapped to the keys you configured in the plugin options." })
249
296
  ] }),
250
- isPending ? /* @__PURE__ */ jsx(Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxs(InlineTip, { variant: "error", label: "Configuration unavailable", children: [
297
+ isPending || !isInitializedRef.current || Object.keys(values).length === 0 ? /* @__PURE__ */ jsx(Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxs(InlineTip, { variant: "error", label: "Configuration unavailable", children: [
251
298
  "Unable to load metadata configuration for this plugin. Confirm that the plugin is registered with options in ",
252
299
  /* @__PURE__ */ jsx("code", { children: "medusa-config.ts" }),
253
300
  "."
@@ -1016,14 +1063,14 @@ const ProductMetadataTableWidget = ({ data }) => {
1016
1063
  }, [productId]);
1017
1064
  const metadataStringRef = useRef("");
1018
1065
  useEffect(() => {
1019
- const hasMetadata = (data == null ? void 0 : data.metadata) && Object.keys(data.metadata).length > 0;
1066
+ const hasProductData = !!data;
1020
1067
  const descriptorsLoaded = descriptors.length > 0;
1021
1068
  const sameProduct = previousProductIdRef.current === productId;
1022
1069
  const notInitialized = !isInitializedRef.current;
1023
- const currentMetadataString = hasMetadata ? JSON.stringify(data.metadata) : "";
1070
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
1071
+ const currentMetadataString = JSON.stringify(currentMetadata);
1024
1072
  const metadataChanged = currentMetadataString !== metadataStringRef.current;
1025
- if (hasMetadata && descriptorsLoaded && sameProduct && (notInitialized || metadataChanged)) {
1026
- const currentMetadata = data.metadata ?? {};
1073
+ if (hasProductData && descriptorsLoaded && sameProduct && (notInitialized || metadataChanged)) {
1027
1074
  const newInitialState = buildInitialFormState(descriptors, currentMetadata);
1028
1075
  setBaselineMetadata(currentMetadata);
1029
1076
  setValues(newInitialState);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medusa-product-helper",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "A starter for Medusa plugins.",
5
5
  "author": "Medusa (https://medusajs.com)",
6
6
  "license": "MIT",