@zaamx/netme-bundle 0.0.4 → 0.0.6

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.
@@ -16,514 +16,481 @@ const sdk = new Medusa__default.default({
16
16
  type: "session"
17
17
  }
18
18
  });
19
- const limit = 15;
19
+ const ProductSearchSelect = ({
20
+ value,
21
+ valueLabel,
22
+ onChange,
23
+ disabled,
24
+ placeholder = "Search products…"
25
+ }) => {
26
+ const [search, setSearch] = react.useState("");
27
+ const [open, setOpen] = react.useState(false);
28
+ const [results, setResults] = react.useState([]);
29
+ const [loading, setLoading] = react.useState(false);
30
+ const containerRef = react.useRef(null);
31
+ react.useEffect(() => {
32
+ const handler = (e) => {
33
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
34
+ setOpen(false);
35
+ }
36
+ };
37
+ document.addEventListener("mousedown", handler);
38
+ return () => document.removeEventListener("mousedown", handler);
39
+ }, []);
40
+ react.useEffect(() => {
41
+ if (!open) return;
42
+ const delay = search.trim() ? 300 : 0;
43
+ const timer = setTimeout(async () => {
44
+ setLoading(true);
45
+ try {
46
+ const { products } = await sdk.admin.product.list({
47
+ q: search.trim() || void 0,
48
+ limit: 15
49
+ });
50
+ setResults(products.map((p) => ({ id: p.id, title: p.title ?? "" })));
51
+ } catch {
52
+ setResults([]);
53
+ } finally {
54
+ setLoading(false);
55
+ }
56
+ }, delay);
57
+ return () => clearTimeout(timer);
58
+ }, [search, open]);
59
+ if (disabled) {
60
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-gray-200 rounded-md px-3 py-2 bg-gray-50 text-sm text-gray-700 min-h-[38px]", children: valueLabel || value || /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400", children: "—" }) });
61
+ }
62
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
63
+ value && valueLabel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex items-center gap-2", children: [
64
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { className: "bg-blue-50 text-blue-700 text-xs", children: valueLabel }),
65
+ /* @__PURE__ */ jsxRuntime.jsx(
66
+ "button",
67
+ {
68
+ type: "button",
69
+ className: "text-xs text-gray-400 hover:text-gray-600",
70
+ onClick: () => onChange("", ""),
71
+ children: "✕ clear"
72
+ }
73
+ )
74
+ ] }),
75
+ /* @__PURE__ */ jsxRuntime.jsx(
76
+ ui.Input,
77
+ {
78
+ placeholder: value ? "Search to change…" : placeholder,
79
+ value: search,
80
+ onChange: (e) => {
81
+ setSearch(e.target.value);
82
+ setOpen(true);
83
+ },
84
+ onFocus: () => setOpen(true)
85
+ }
86
+ ),
87
+ open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-md shadow-lg max-h-60 overflow-y-auto", children: [
88
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-sm text-gray-400", children: "Searching…" }),
89
+ !loading && results.length === 0 && search.trim() && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-sm text-gray-400", children: "No products found." }),
90
+ results.map((product) => /* @__PURE__ */ jsxRuntime.jsx(
91
+ "button",
92
+ {
93
+ type: "button",
94
+ className: "w-full text-left px-3 py-2 hover:bg-gray-50 text-sm border-b border-gray-100 last:border-0",
95
+ onMouseDown: (e) => {
96
+ e.preventDefault();
97
+ onChange(product.id, product.title);
98
+ setSearch("");
99
+ setOpen(false);
100
+ },
101
+ children: product.title
102
+ },
103
+ product.id
104
+ ))
105
+ ] })
106
+ ] });
107
+ };
108
+ const VariantPicker = ({
109
+ productId,
110
+ selectedIds,
111
+ onChange
112
+ }) => {
113
+ const [variants, setVariants] = react.useState([]);
114
+ const [loading, setLoading] = react.useState(false);
115
+ react.useEffect(() => {
116
+ if (!productId) {
117
+ setVariants([]);
118
+ return;
119
+ }
120
+ setLoading(true);
121
+ sdk.admin.product.retrieve(productId).then(
122
+ ({ product }) => setVariants(
123
+ (product.variants || []).map((v) => ({ id: v.id, title: v.title ?? v.id, sku: v.sku ?? void 0 }))
124
+ )
125
+ ).catch(() => setVariants([])).finally(() => setLoading(false));
126
+ }, [productId]);
127
+ const toggle = (id) => onChange(
128
+ selectedIds.includes(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]
129
+ );
130
+ if (loading) return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-400", children: "Loading variants…" });
131
+ if (!loading && variants.length === 0)
132
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-400", children: "No variants found." });
133
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2 max-h-52 overflow-y-auto pr-1", children: variants.map((v) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 cursor-pointer select-none", children: [
134
+ /* @__PURE__ */ jsxRuntime.jsx(
135
+ "input",
136
+ {
137
+ type: "checkbox",
138
+ checked: selectedIds.includes(v.id),
139
+ onChange: () => toggle(v.id),
140
+ className: "h-4 w-4 rounded border-gray-300"
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: v.title }),
144
+ v.sku && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-400 font-mono", children: v.sku })
145
+ ] }, v.id)) });
146
+ };
147
+ const emptyBundleItem = () => ({
148
+ product_id: void 0,
149
+ product_title: "",
150
+ variant_mode: "all",
151
+ variant_ids: [],
152
+ min_quantity: 1,
153
+ max_quantity: 1,
154
+ default_quantity: 1,
155
+ optional: false,
156
+ separate_shipping: false,
157
+ individual_price: false
158
+ });
159
+ const LIMIT = 15;
20
160
  const BundledProductsPage = () => {
21
161
  const [page, setPage] = react.useState(0);
22
- const [openCreateModal, setOpenCreateModal] = react.useState(false);
162
+ const [openModal, setOpenModal] = react.useState(false);
23
163
  const [isEditing, setIsEditing] = react.useState(false);
24
164
  const [selectedProductId, setSelectedProductId] = react.useState();
165
+ const [selectedProductTitle, setSelectedProductTitle] = react.useState("");
25
166
  const [bundleItems, setBundleItems] = react.useState([]);
26
167
  const [bundleMeta, setBundleMeta] = react.useState([]);
27
- const [products, setProducts] = react.useState([]);
28
- const productsLimit = 15;
29
- const [currentProductPage, setCurrentProductPage] = react.useState(0);
30
- const [productsCount, setProductsCount] = react.useState(0);
31
- const hasNextPage = react.useMemo(
32
- () => productsCount ? productsCount > productsLimit : true,
33
- [productsCount, productsLimit]
34
- );
35
168
  const queryClient = reactQuery.useQueryClient();
36
- const offset = page * limit;
169
+ const offset = page * LIMIT;
170
+ const closeModal = () => {
171
+ setOpenModal(false);
172
+ setIsEditing(false);
173
+ setSelectedProductId(void 0);
174
+ setSelectedProductTitle("");
175
+ setBundleItems([]);
176
+ setBundleMeta([]);
177
+ };
37
178
  const { data, isLoading } = reactQuery.useQuery({
38
- queryKey: ["bundled-products", offset, limit],
179
+ queryKey: ["bundled-products", offset, LIMIT],
39
180
  queryFn: () => sdk.client.fetch("/admin/bundled-products", {
40
181
  method: "GET",
41
- query: {
42
- limit,
43
- offset
44
- }
182
+ query: { limit: LIMIT, offset }
45
183
  })
46
184
  });
47
- reactQuery.useQuery({
48
- queryKey: ["products"],
49
- queryFn: async () => {
50
- const { products: products2, count } = await sdk.admin.product.list({
51
- limit: productsLimit,
52
- offset: currentProductPage * productsLimit
53
- });
54
- setProductsCount(count);
55
- setProducts((prev) => [...prev, ...products2]);
56
- return products2;
57
- },
58
- enabled: hasNextPage
59
- });
60
- const fetchMoreProducts = () => {
61
- if (!hasNextPage) {
62
- return;
63
- }
64
- setCurrentProductPage(currentProductPage + 1);
65
- };
66
- const { mutateAsync: createBundle, isPending: isCreating } = reactQuery.useMutation({
67
- mutationFn: async (data2) => {
185
+ const { mutateAsync: saveBundle, isPending: isSaving } = reactQuery.useMutation({
186
+ mutationFn: async () => {
68
187
  if (!selectedProductId) throw new Error("No product selected");
188
+ const validItems = bundleItems.filter((i) => i.product_id);
69
189
  await sdk.client.fetch(`/admin/products/${selectedProductId}/bundle`, {
70
190
  method: "POST",
71
- body: data2
191
+ body: {
192
+ child_product_ids: validItems.map((item) => ({
193
+ id: item.product_id,
194
+ variant_ids: item.variant_mode === "specific" ? item.variant_ids : [],
195
+ min_quantity: item.min_quantity,
196
+ max_quantity: item.max_quantity,
197
+ default_quantity: item.default_quantity,
198
+ optional: item.optional,
199
+ separate_shipping: item.separate_shipping,
200
+ individual_price: item.individual_price
201
+ })),
202
+ bundle_meta: bundleMeta,
203
+ is_bundle: true
204
+ }
72
205
  });
73
206
  }
74
207
  });
75
- const { mutateAsync: deleteBundle, isPending: isDeleting } = reactQuery.useMutation({
76
- mutationFn: async (productId) => {
77
- await sdk.client.fetch(`/admin/products/${productId}/bundle`, {
78
- method: "DELETE"
79
- });
80
- }
208
+ const { mutateAsync: deleteBundle } = reactQuery.useMutation({
209
+ mutationFn: (productId) => sdk.client.fetch(`/admin/products/${productId}/bundle`, { method: "DELETE" })
81
210
  });
82
- const handleDeleteBundle = async (productId) => {
83
- try {
84
- await deleteBundle(productId);
85
- ui.toast.success("Bundle deleted successfully");
86
- queryClient.invalidateQueries({
87
- queryKey: ["bundled-products"]
88
- });
89
- } catch (error) {
90
- console.error("Error deleting bundle:", error);
91
- ui.toast.error("Failed to delete bundle");
92
- }
93
- };
94
211
  const handleEditBundle = (bundle) => {
95
212
  setIsEditing(true);
96
213
  setSelectedProductId(bundle.product.id);
97
- setBundleItems(bundle.items.map((item) => ({
98
- product_id: item.product.id,
99
- min_quantity: item.min_quantity || 1,
100
- max_quantity: item.max_quantity || 1,
101
- default_quantity: item.quantity,
102
- optional: item.optional || false,
103
- separate_shipping: item.separate_shipping || false,
104
- individual_price: item.individual_price || false
105
- })));
106
- setBundleMeta(bundle.bundle_meta || []);
107
- setOpenCreateModal(true);
108
- };
109
- const handleCreateBundle = async () => {
110
- try {
111
- if (!selectedProductId) {
112
- ui.toast.error("Please select a product");
113
- return;
114
- }
115
- const validItems = bundleItems.filter((item) => item.product_id);
116
- if (validItems.length === 0) {
117
- ui.toast.error("Please add at least one product to the bundle");
118
- return;
119
- }
120
- await createBundle({
121
- child_product_ids: validItems.map((item) => ({
122
- id: item.product_id,
214
+ setSelectedProductTitle(bundle.title);
215
+ setBundleItems(
216
+ bundle.items.map((item) => {
217
+ var _a;
218
+ return {
219
+ product_id: item.product.id,
220
+ product_title: item.product.title,
221
+ variant_mode: ((_a = item.variant_ids) == null ? void 0 : _a.length) ? "specific" : "all",
222
+ variant_ids: item.variant_ids ?? [],
123
223
  min_quantity: item.min_quantity,
124
224
  max_quantity: item.max_quantity,
125
225
  default_quantity: item.default_quantity,
126
226
  optional: item.optional,
127
227
  separate_shipping: item.separate_shipping,
128
228
  individual_price: item.individual_price
129
- })),
130
- bundle_meta: bundleMeta,
131
- is_bundle: true
132
- });
133
- setOpenCreateModal(false);
134
- ui.toast.success(isEditing ? "Bundle updated successfully" : "Bundle created successfully");
135
- queryClient.invalidateQueries({
136
- queryKey: ["bundled-products"]
137
- });
138
- setIsEditing(false);
139
- setSelectedProductId(void 0);
140
- setBundleItems([]);
141
- setBundleMeta([]);
142
- } catch (error) {
143
- console.error("Error creating bundle:", error);
144
- ui.toast.error("Failed to create bundle");
145
- }
146
- };
147
- const addBundleItem = () => {
148
- setBundleItems([
149
- ...bundleItems,
150
- {
151
- product_id: void 0,
152
- min_quantity: 1,
153
- max_quantity: 1,
154
- default_quantity: 1,
155
- optional: false,
156
- separate_shipping: false,
157
- individual_price: false
158
- }
159
- ]);
160
- };
161
- const removeBundleItem = (index) => {
162
- setBundleItems(bundleItems.filter((_, i) => i !== index));
163
- };
164
- const updateBundleItem = (index, field, value) => {
165
- setBundleItems(bundleItems.map(
166
- (item, i) => i === index ? { ...item, [field]: value } : item
167
- ));
168
- };
169
- const addBundleMeta = () => {
170
- setBundleMeta([...bundleMeta, { key: "", value: "" }]);
229
+ };
230
+ })
231
+ );
232
+ setBundleMeta(bundle.bundle_meta || []);
233
+ setOpenModal(true);
171
234
  };
172
- const removeBundleMeta = (index) => {
173
- setBundleMeta(bundleMeta.filter((_, i) => i !== index));
235
+ const handleDeleteBundle = async (productId) => {
236
+ try {
237
+ await deleteBundle(productId);
238
+ ui.toast.success("Bundle deleted");
239
+ queryClient.invalidateQueries({ queryKey: ["bundled-products"] });
240
+ } catch {
241
+ ui.toast.error("Failed to delete bundle");
242
+ }
174
243
  };
175
- const updateBundleMeta = (index, field, value) => {
176
- setBundleMeta(bundleMeta.map(
177
- (item, i) => i === index ? { ...item, [field]: value } : item
178
- ));
244
+ const handleSave = async () => {
245
+ if (!selectedProductId) {
246
+ ui.toast.error("Please select a product");
247
+ return;
248
+ }
249
+ if (!bundleItems.some((i) => i.product_id)) {
250
+ ui.toast.error("Please add at least one product to the bundle");
251
+ return;
252
+ }
253
+ try {
254
+ await saveBundle();
255
+ ui.toast.success(isEditing ? "Bundle updated" : "Bundle created");
256
+ queryClient.invalidateQueries({ queryKey: ["bundled-products"] });
257
+ closeModal();
258
+ } catch {
259
+ ui.toast.error(isEditing ? "Failed to update bundle" : "Failed to create bundle");
260
+ }
179
261
  };
180
- const totalPages = Math.ceil(((data == null ? void 0 : data.count) || 0) / limit);
262
+ const updateItem = (index, field, value) => setBundleItems((prev) => prev.map((item, i) => i === index ? { ...item, [field]: value } : item));
263
+ const totalPages = Math.ceil(((data == null ? void 0 : data.count) || 0) / LIMIT);
181
264
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
182
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2 md:flex-row md:items-center p-6", children: [
265
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-6", children: [
183
266
  /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Bundled Products" }),
184
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => setOpenCreateModal(true), children: "Create Bundle" })
267
+ /* @__PURE__ */ jsxRuntime.jsx(
268
+ ui.Button,
269
+ {
270
+ variant: "primary",
271
+ onClick: () => {
272
+ closeModal();
273
+ setOpenModal(true);
274
+ },
275
+ children: "Create Bundle"
276
+ }
277
+ )
185
278
  ] }),
186
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading..." }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
279
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
187
280
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse border border-gray-200", children: [
188
281
  /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "bg-gray-50", children: [
189
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "ID" }),
190
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Title" }),
191
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Items" }),
192
282
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Product" }),
193
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Status" })
283
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Status" }),
284
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Items" }),
285
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "border border-gray-200 px-4 py-2 text-left", children: "Actions" })
194
286
  ] }) }),
195
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: data == null ? void 0 : data.bundled_products.map((bundle) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "hover:bg-gray-50", children: [
196
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-sm", children: bundle.id }) }),
197
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-2", children: bundle.title }),
198
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: bundle.items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm", children: [
199
- /* @__PURE__ */ jsxRuntime.jsx(
200
- reactRouterDom.Link,
201
- {
202
- to: `/products/${item.product.id}`,
203
- className: "text-blue-600 hover:underline",
204
- children: item.product.title
205
- }
206
- ),
207
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-500", children: [
208
- " x ",
209
- item.quantity
287
+ /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
288
+ ((data == null ? void 0 : data.bundled_products.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 4, className: "border border-gray-200 px-4 py-6 text-center text-gray-400", children: "No bundled products found." }) }),
289
+ data == null ? void 0 : data.bundled_products.map((bundle) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "hover:bg-gray-50", children: [
290
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "border border-gray-200 px-4 py-3", children: [
291
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: `/products/${bundle.product.id}`, className: "font-medium text-blue-600 hover:underline", children: bundle.title }),
292
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-400 mt-0.5", children: bundle.id })
210
293
  ] }),
211
- item.optional && /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { className: "ml-2 bg-gray-100 text-gray-700", children: "Optional" })
212
- ] }, item.id)) }) }),
213
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
214
- reactRouterDom.Link,
215
- {
216
- to: `/products/${bundle.product.id}`,
217
- className: "text-blue-600 hover:underline",
218
- children: "View Product"
219
- }
220
- ) }),
221
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
222
- /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { className: bundle.is_bundle ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-700", children: bundle.is_bundle ? "Active" : "Inactive" }),
223
- /* @__PURE__ */ jsxRuntime.jsx(
224
- ui.Button,
225
- {
226
- variant: "secondary",
227
- size: "small",
228
- onClick: () => handleEditBundle(bundle),
229
- children: "Edit"
230
- }
231
- ),
232
- /* @__PURE__ */ jsxRuntime.jsx(
233
- ui.Button,
234
- {
235
- variant: "secondary",
236
- size: "small",
237
- onClick: () => handleDeleteBundle(bundle.id),
238
- className: "text-red-600 hover:text-red-700",
239
- children: "Delete"
240
- }
241
- )
242
- ] }) })
243
- ] }, bundle.id)) })
294
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { className: bundle.status === "published" ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-600", children: bundle.status ?? "" }) }),
295
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
296
+ bundle.items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-400", children: "No items" }),
297
+ bundle.items.map((item) => {
298
+ var _a;
299
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm", children: [
300
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
301
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: `/products/${item.product.id}`, className: "text-blue-600 hover:underline", children: item.product.title }),
302
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400", children: [
303
+ ",
304
+ item.default_quantity
305
+ ] }),
306
+ item.optional && /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { className: "bg-gray-100 text-gray-500 text-xs", children: "Optional" })
307
+ ] }),
308
+ ((_a = item.variant_ids) == null ? void 0 : _a.length) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-gray-400 ml-1", children: [
309
+ item.variant_ids.length,
310
+ " specific variant",
311
+ item.variant_ids.length > 1 ? "s" : ""
312
+ ] })
313
+ ] }, item.id);
314
+ })
315
+ ] }) }),
316
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "border border-gray-200 px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
317
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => handleEditBundle(bundle), children: "Edit" }),
318
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => handleDeleteBundle(bundle.id), className: "text-red-600 hover:text-red-700", children: "Delete" })
319
+ ] }) })
320
+ ] }, bundle.id))
321
+ ] })
244
322
  ] }) }),
245
323
  totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-center gap-2 mt-6", children: [
246
- /* @__PURE__ */ jsxRuntime.jsx(
247
- ui.Button,
248
- {
249
- variant: "secondary",
250
- onClick: () => setPage(Math.max(0, page - 1)),
251
- disabled: page === 0,
252
- children: "Previous"
253
- }
254
- ),
324
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => setPage(Math.max(0, page - 1)), disabled: page === 0, children: "Previous" }),
255
325
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center px-4", children: [
256
326
  "Page ",
257
327
  page + 1,
258
328
  " of ",
259
329
  totalPages
260
330
  ] }),
261
- /* @__PURE__ */ jsxRuntime.jsx(
262
- ui.Button,
263
- {
264
- variant: "secondary",
265
- onClick: () => setPage(Math.min(totalPages - 1, page + 1)),
266
- disabled: page === totalPages - 1,
267
- children: "Next"
268
- }
269
- )
331
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => setPage(Math.min(totalPages - 1, page + 1)), disabled: page === totalPages - 1, children: "Next" })
270
332
  ] })
271
333
  ] }),
272
- /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open: openCreateModal, onOpenChange: setOpenCreateModal, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.FocusModal.Content, { children: [
334
+ /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open: openModal, onOpenChange: (open) => {
335
+ if (!open) closeModal();
336
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.FocusModal.Content, { children: [
273
337
  /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: isEditing ? "Edit Bundle" : "Create Bundle" }) }),
274
338
  /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col items-center h-[80vh] overflow-y-auto px-2 py-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-3xl flex flex-col gap-y-8", children: [
275
339
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
276
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Select Product to Bundle" }),
277
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600 mb-4", children: "Choose a product that will become a bundle" }),
278
- /* @__PURE__ */ jsxRuntime.jsxs(
279
- ui.Select,
340
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Bundle Product" }),
341
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-500 mb-2", children: isEditing ? "The product this bundle is attached to" : "Choose the product that becomes the bundle" }),
342
+ /* @__PURE__ */ jsxRuntime.jsx(
343
+ ProductSearchSelect,
280
344
  {
281
345
  value: selectedProductId,
282
- onValueChange: setSelectedProductId,
346
+ valueLabel: selectedProductTitle,
347
+ onChange: (id, title) => {
348
+ setSelectedProductId(id || void 0);
349
+ setSelectedProductTitle(title);
350
+ },
283
351
  disabled: isEditing,
284
- children: [
285
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select a product to bundle" }) }),
286
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: products == null ? void 0 : products.map((product) => /* @__PURE__ */ jsxRuntime.jsx(
287
- ui.Select.Item,
288
- {
289
- value: product.id,
290
- children: product.title
291
- },
292
- product.id
293
- )) })
294
- ]
352
+ placeholder: "Search for a product to bundle…"
295
353
  }
296
354
  )
297
355
  ] }),
298
356
  selectedProductId && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
299
357
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
300
358
  /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Bundle Items" }),
301
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600 mb-4", children: "Select products to include in this bundle" }),
359
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-500 mb-4", children: "Products included in this bundle" }),
302
360
  bundleItems.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
303
361
  BundleItemForm,
304
362
  {
305
363
  item,
306
364
  index,
307
- products,
308
- onUpdate: (field, value) => updateBundleItem(index, field, value),
309
- onRemove: () => removeBundleItem(index),
310
- fetchMoreProducts,
311
- hasNextPage
365
+ onUpdate: (field, value) => updateItem(index, field, value),
366
+ onRemove: () => setBundleItems((prev) => prev.filter((_, i) => i !== index))
312
367
  },
313
368
  index
314
369
  )),
315
- /* @__PURE__ */ jsxRuntime.jsx(
316
- ui.Button,
317
- {
318
- variant: "secondary",
319
- onClick: addBundleItem,
320
- className: "mt-4",
321
- children: "Add Item"
322
- }
323
- )
370
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => setBundleItems((prev) => [...prev, emptyBundleItem()]), className: "mt-2", children: "Add Item" })
324
371
  ] }),
325
372
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
326
373
  /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Bundle Metadata" }),
327
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600 mb-4", children: "Add custom metadata for this bundle" }),
374
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-500 mb-4", children: "Custom key-value pairs" }),
328
375
  bundleMeta.map((meta, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 mb-2", children: [
329
- /* @__PURE__ */ jsxRuntime.jsx(
330
- ui.Input,
331
- {
332
- placeholder: "Key",
333
- value: meta.key,
334
- onChange: (e) => updateBundleMeta(index, "key", e.target.value)
335
- }
336
- ),
337
- /* @__PURE__ */ jsxRuntime.jsx(
338
- ui.Input,
339
- {
340
- placeholder: "Value",
341
- value: meta.value,
342
- onChange: (e) => updateBundleMeta(index, "value", e.target.value)
343
- }
344
- ),
345
- /* @__PURE__ */ jsxRuntime.jsx(
346
- ui.Button,
347
- {
348
- variant: "secondary",
349
- onClick: () => removeBundleMeta(index),
350
- children: "Remove"
351
- }
352
- )
376
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { placeholder: "Key", value: meta.key, onChange: (e) => setBundleMeta((prev) => prev.map((m, i) => i === index ? { ...m, key: e.target.value } : m)) }),
377
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { placeholder: "Value", value: meta.value, onChange: (e) => setBundleMeta((prev) => prev.map((m, i) => i === index ? { ...m, value: e.target.value } : m)) }),
378
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => setBundleMeta((prev) => prev.filter((_, i) => i !== index)), children: "Remove" })
353
379
  ] }, index)),
354
- /* @__PURE__ */ jsxRuntime.jsx(
355
- ui.Button,
356
- {
357
- variant: "secondary",
358
- onClick: addBundleMeta,
359
- className: "mt-4",
360
- children: "Add Metadata"
361
- }
362
- )
380
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => setBundleMeta((prev) => [...prev, { key: "", value: "" }]), className: "mt-2", children: "Add Metadata" })
363
381
  ] })
364
382
  ] })
365
383
  ] }) }) }),
366
384
  /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
367
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: () => {
368
- setOpenCreateModal(false);
369
- setIsEditing(false);
370
- setSelectedProductId(void 0);
371
- setBundleItems([]);
372
- setBundleMeta([]);
373
- }, children: "Cancel" }),
374
- /* @__PURE__ */ jsxRuntime.jsx(
375
- ui.Button,
376
- {
377
- variant: "primary",
378
- onClick: handleCreateBundle,
379
- isLoading: isCreating,
380
- disabled: !selectedProductId,
381
- children: isEditing ? "Update Bundle" : "Create Bundle"
382
- }
383
- )
385
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: closeModal, children: "Cancel" }),
386
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: handleSave, isLoading: isSaving, disabled: !selectedProductId, children: isEditing ? "Update Bundle" : "Create Bundle" })
384
387
  ] }) })
385
388
  ] }) })
386
389
  ] });
387
390
  };
388
- const BundleItemForm = ({
389
- item,
390
- index,
391
- products,
392
- onUpdate,
393
- onRemove,
394
- fetchMoreProducts,
395
- hasNextPage
396
- }) => {
397
- const observer = react.useRef(
398
- new IntersectionObserver(
399
- (entries) => {
400
- if (!hasNextPage) {
401
- return;
402
- }
403
- const first = entries[0];
404
- if (first.isIntersecting) {
405
- fetchMoreProducts();
406
- }
407
- },
408
- { threshold: 1 }
409
- )
410
- );
411
- const lastOptionRef = react.useCallback(
412
- (node) => {
413
- if (!hasNextPage) {
414
- return;
415
- }
416
- if (observer.current) {
417
- observer.current.disconnect();
418
- }
419
- if (node) {
420
- observer.current.observe(node);
421
- }
422
- },
423
- [hasNextPage]
424
- );
425
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border rounded-lg p-4 space-y-4", children: [
426
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
427
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h3", children: [
428
- "Item ",
429
- index + 1
430
- ] }),
431
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: onRemove, children: "Remove" })
432
- ] }),
433
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
434
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Product" }),
435
- /* @__PURE__ */ jsxRuntime.jsxs(
436
- ui.Select,
437
- {
438
- value: item.product_id,
439
- onValueChange: (value) => onUpdate("product_id", value),
440
- children: [
441
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select Product" }) }),
442
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: products == null ? void 0 : products.map((product, productIndex) => /* @__PURE__ */ jsxRuntime.jsx(
443
- ui.Select.Item,
444
- {
445
- value: product.id,
446
- ref: productIndex === products.length - 1 ? lastOptionRef : null,
447
- children: product.title
448
- },
449
- product.id
450
- )) })
451
- ]
452
- }
453
- )
454
- ] }),
455
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-4", children: [
456
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
457
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Min Quantity" }),
458
- /* @__PURE__ */ jsxRuntime.jsx(
459
- ui.Input,
460
- {
461
- type: "number",
462
- min: 0,
463
- value: item.min_quantity,
464
- onChange: (e) => onUpdate("min_quantity", parseInt(e.target.value) || 0)
465
- }
466
- )
467
- ] }),
468
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
469
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Max Quantity" }),
470
- /* @__PURE__ */ jsxRuntime.jsx(
471
- ui.Input,
472
- {
473
- type: "number",
474
- min: 0,
475
- value: item.max_quantity,
476
- onChange: (e) => onUpdate("max_quantity", parseInt(e.target.value) || 0)
477
- }
478
- )
479
- ] }),
480
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
481
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Default Quantity" }),
482
- /* @__PURE__ */ jsxRuntime.jsx(
483
- ui.Input,
484
- {
485
- type: "number",
486
- min: 0,
487
- value: item.default_quantity,
488
- onChange: (e) => onUpdate("default_quantity", parseInt(e.target.value) || 0)
489
- }
490
- )
491
- ] })
391
+ const BundleItemForm = ({ item, index, onUpdate, onRemove }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border rounded-lg p-4 space-y-4 mb-4", children: [
392
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
393
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Heading, { level: "h3", children: [
394
+ "Item ",
395
+ index + 1
492
396
  ] }),
493
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
494
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
495
- /* @__PURE__ */ jsxRuntime.jsx(
496
- ui.Switch,
497
- {
498
- checked: item.optional,
499
- onCheckedChange: (checked) => onUpdate("optional", checked)
500
- }
501
- ),
502
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Optional" })
503
- ] }),
504
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
397
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", onClick: onRemove, children: "Remove" })
398
+ ] }),
399
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
400
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Product" }),
401
+ /* @__PURE__ */ jsxRuntime.jsx(
402
+ ProductSearchSelect,
403
+ {
404
+ value: item.product_id,
405
+ valueLabel: item.product_title,
406
+ onChange: (id, title) => {
407
+ onUpdate("product_id", id || void 0);
408
+ onUpdate("product_title", title);
409
+ onUpdate("variant_mode", "all");
410
+ onUpdate("variant_ids", []);
411
+ },
412
+ placeholder: "Search for a product…"
413
+ }
414
+ )
415
+ ] }),
416
+ item.product_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
417
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Applies to" }),
418
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-6", children: [
419
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer select-none", children: [
505
420
  /* @__PURE__ */ jsxRuntime.jsx(
506
- ui.Switch,
421
+ "input",
507
422
  {
508
- checked: item.separate_shipping,
509
- onCheckedChange: (checked) => onUpdate("separate_shipping", checked)
423
+ type: "radio",
424
+ name: `variant-mode-${index}`,
425
+ checked: item.variant_mode === "all",
426
+ onChange: () => {
427
+ onUpdate("variant_mode", "all");
428
+ onUpdate("variant_ids", []);
429
+ }
510
430
  }
511
431
  ),
512
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Separate Shipping" })
432
+ "All variations"
513
433
  ] }),
514
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
434
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer select-none", children: [
515
435
  /* @__PURE__ */ jsxRuntime.jsx(
516
- ui.Switch,
436
+ "input",
517
437
  {
518
- checked: item.individual_price,
519
- onCheckedChange: (checked) => onUpdate("individual_price", checked)
438
+ type: "radio",
439
+ name: `variant-mode-${index}`,
440
+ checked: item.variant_mode === "specific",
441
+ onChange: () => onUpdate("variant_mode", "specific")
520
442
  }
521
443
  ),
522
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Individual Price" })
444
+ "Specific variations"
445
+ ] })
446
+ ] }),
447
+ item.variant_mode === "specific" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border border-gray-200 rounded-md p-3 bg-gray-50", children: [
448
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs text-gray-500 mb-3", children: 'Check each variation that qualifies for this bundle item. Switching back to "All variations" will clear this selection.' }),
449
+ /* @__PURE__ */ jsxRuntime.jsx(
450
+ VariantPicker,
451
+ {
452
+ productId: item.product_id,
453
+ selectedIds: item.variant_ids,
454
+ onChange: (ids) => onUpdate("variant_ids", ids)
455
+ }
456
+ ),
457
+ item.variant_ids.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-xs text-gray-400 mt-2", children: [
458
+ item.variant_ids.length,
459
+ " variation",
460
+ item.variant_ids.length > 1 ? "s" : "",
461
+ " selected"
523
462
  ] })
524
463
  ] })
525
- ] });
526
- };
464
+ ] }),
465
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-4", children: [
466
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
467
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Min Quantity" }),
468
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { type: "number", min: 0, value: item.min_quantity, onChange: (e) => onUpdate("min_quantity", parseInt(e.target.value) || 0) })
469
+ ] }),
470
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
471
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Max Quantity" }),
472
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { type: "number", min: 0, value: item.max_quantity, onChange: (e) => onUpdate("max_quantity", parseInt(e.target.value) || 0) })
473
+ ] }),
474
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
475
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Default Quantity" }),
476
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { type: "number", min: 0, value: item.default_quantity, onChange: (e) => onUpdate("default_quantity", parseInt(e.target.value) || 0) })
477
+ ] })
478
+ ] }),
479
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
480
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
481
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: item.optional, onCheckedChange: (v) => onUpdate("optional", v) }),
482
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Optional" })
483
+ ] }),
484
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
485
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: item.separate_shipping, onCheckedChange: (v) => onUpdate("separate_shipping", v) }),
486
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Separate Shipping" })
487
+ ] }),
488
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
489
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: item.individual_price, onCheckedChange: (v) => onUpdate("individual_price", v) }),
490
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Individual Price" })
491
+ ] })
492
+ ] })
493
+ ] });
527
494
  const config = adminSdk.defineRouteConfig({
528
495
  label: "Bundled Products",
529
496
  icon: icons.CubeSolid