@medusajs/draft-order 2.19.0 → 2.19.1-preview-20260813160157

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.
@@ -7227,88 +7227,46 @@ const CustomItemsForm = () => {
7227
7227
  const schema$3 = zod.z.object({
7228
7228
  email: zod.z.string().email()
7229
7229
  });
7230
- const InlineTip = React.forwardRef(
7231
- ({ variant = "tip", label, className, children, ...props }, ref) => {
7232
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
7233
- return /* @__PURE__ */ jsxRuntime.jsxs(
7234
- "div",
7235
- {
7236
- ref,
7237
- className: ui.clx(
7238
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
7239
- className
7240
- ),
7241
- ...props,
7242
- children: [
7243
- /* @__PURE__ */ jsxRuntime.jsx(
7244
- "div",
7245
- {
7246
- role: "presentation",
7247
- className: ui.clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
7248
- "bg-ui-tag-orange-icon": variant === "warning"
7249
- })
7250
- }
7251
- ),
7252
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-pretty", children: [
7253
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
7254
- labelValue,
7255
- ":"
7256
- ] }),
7257
- " ",
7258
- children
7259
- ] })
7260
- ]
7261
- }
7262
- );
7263
- }
7264
- );
7265
- InlineTip.displayName = "InlineTip";
7266
- const MetadataFieldSchema = zod.z.object({
7267
- key: zod.z.string(),
7268
- disabled: zod.z.boolean().optional(),
7269
- value: zod.z.any()
7270
- });
7271
- const MetadataSchema = zod.z.object({
7272
- metadata: zod.z.array(MetadataFieldSchema)
7273
- });
7274
- const Metadata = () => {
7230
+ const SalesChannel = () => {
7275
7231
  const { id } = reactRouterDom.useParams();
7276
- const { order, isPending, isError, error } = useOrder(id, {
7277
- fields: "metadata"
7278
- });
7232
+ const { draft_order, isPending, isError, error } = useDraftOrder(
7233
+ id,
7234
+ {
7235
+ fields: "+sales_channel_id"
7236
+ },
7237
+ {
7238
+ enabled: !!id
7239
+ }
7240
+ );
7279
7241
  if (isError) {
7280
7242
  throw error;
7281
7243
  }
7282
- const isReady = !isPending && !!order;
7244
+ const ISrEADY = !!draft_order && !isPending;
7283
7245
  return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
7284
7246
  /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
7285
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Metadata" }) }),
7286
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
7247
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Sales Channel" }) }),
7248
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
7287
7249
  ] }),
7288
- !isReady ? /* @__PURE__ */ jsxRuntime.jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetadataForm, { orderId: id, metadata: order?.metadata })
7250
+ ISrEADY && /* @__PURE__ */ jsxRuntime.jsx(SalesChannelForm, { order: draft_order })
7289
7251
  ] });
7290
7252
  };
7291
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
7292
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
7293
- const MetadataForm = ({ orderId, metadata }) => {
7294
- const { handleSuccess } = useRouteModal();
7295
- const hasUneditableRows = getHasUneditableRows(metadata);
7296
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
7253
+ const SalesChannelForm = ({ order }) => {
7297
7254
  const form = reactHookForm.useForm({
7298
7255
  defaultValues: {
7299
- metadata: getDefaultValues(metadata)
7256
+ sales_channel_id: order.sales_channel_id || ""
7300
7257
  },
7301
- resolver: zod$1.zodResolver(MetadataSchema)
7258
+ resolver: zod$1.zodResolver(schema$2)
7302
7259
  });
7303
- const handleSubmit = form.handleSubmit(async (data) => {
7304
- const parsedData = parseValues(data);
7260
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
7261
+ const { handleSuccess } = useRouteModal();
7262
+ const onSubmit = form.handleSubmit(async (data) => {
7305
7263
  await mutateAsync(
7306
7264
  {
7307
- metadata: parsedData
7265
+ sales_channel_id: data.sales_channel_id
7308
7266
  },
7309
7267
  {
7310
7268
  onSuccess: () => {
7311
- ui.toast.success("Metadata updated");
7269
+ ui.toast.success("Sales channel updated");
7312
7270
  handleSuccess();
7313
7271
  },
7314
7272
  onError: (error) => {
@@ -7317,365 +7275,133 @@ const MetadataForm = ({ orderId, metadata }) => {
7317
7275
  }
7318
7276
  );
7319
7277
  });
7320
- const { fields, insert, remove } = reactHookForm.useFieldArray({
7321
- control: form.control,
7322
- name: "metadata"
7323
- });
7324
- function deleteRow(index) {
7325
- remove(index);
7326
- if (fields.length === 1) {
7327
- insert(0, {
7328
- key: "",
7329
- value: "",
7330
- disabled: false
7331
- });
7332
- }
7333
- }
7334
- function insertRow(index, position) {
7335
- insert(index + (position === "above" ? 0 : 1), {
7336
- key: "",
7337
- value: "",
7338
- disabled: false
7339
- });
7340
- }
7341
7278
  return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
7342
7279
  KeyboundForm,
7343
7280
  {
7344
- onSubmit: handleSubmit,
7345
7281
  className: "flex flex-1 flex-col overflow-hidden",
7282
+ onSubmit,
7346
7283
  children: [
7347
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
7348
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
7349
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
7350
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsxRuntime.jsx("label", { id: METADATA_KEY_LABEL_ID, children: "Key" }) }),
7351
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsxRuntime.jsx("label", { id: METADATA_VALUE_LABEL_ID, children: "Value" }) })
7352
- ] }),
7353
- fields.map((field, index) => {
7354
- const isDisabled = field.disabled || false;
7355
- let placeholder = "-";
7356
- if (typeof field.value === "object") {
7357
- placeholder = "{ ... }";
7358
- }
7359
- if (Array.isArray(field.value)) {
7360
- placeholder = "[ ... ]";
7361
- }
7362
- return /* @__PURE__ */ jsxRuntime.jsx(
7363
- ConditionalTooltip,
7364
- {
7365
- showTooltip: isDisabled,
7366
- content: "This row is disabled because it contains non-primitive data.",
7367
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/table relative", children: [
7368
- /* @__PURE__ */ jsxRuntime.jsxs(
7369
- "div",
7370
- {
7371
- className: ui.clx("grid grid-cols-2 divide-x", {
7372
- "overflow-hidden rounded-b-lg": index === fields.length - 1
7373
- }),
7374
- children: [
7375
- /* @__PURE__ */ jsxRuntime.jsx(
7376
- Form$2.Field,
7377
- {
7378
- control: form.control,
7379
- name: `metadata.${index}.key`,
7380
- render: ({ field: field2 }) => {
7381
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
7382
- GridInput,
7383
- {
7384
- "aria-labelledby": METADATA_KEY_LABEL_ID,
7385
- ...field2,
7386
- disabled: isDisabled,
7387
- placeholder: "Key"
7388
- }
7389
- ) }) });
7390
- }
7391
- }
7392
- ),
7393
- /* @__PURE__ */ jsxRuntime.jsx(
7394
- Form$2.Field,
7395
- {
7396
- control: form.control,
7397
- name: `metadata.${index}.value`,
7398
- render: ({ field: { value, ...field2 } }) => {
7399
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
7400
- GridInput,
7401
- {
7402
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
7403
- ...field2,
7404
- value: isDisabled ? placeholder : value,
7405
- disabled: isDisabled,
7406
- placeholder: "Value"
7407
- }
7408
- ) }) });
7409
- }
7410
- }
7411
- )
7412
- ]
7413
- }
7414
- ),
7415
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
7416
- /* @__PURE__ */ jsxRuntime.jsx(
7417
- ui.DropdownMenu.Trigger,
7418
- {
7419
- className: ui.clx(
7420
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
7421
- {
7422
- hidden: isDisabled
7423
- }
7424
- ),
7425
- disabled: isDisabled,
7426
- asChild: true,
7427
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisVertical, {}) })
7428
- }
7429
- ),
7430
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
7431
- /* @__PURE__ */ jsxRuntime.jsxs(
7432
- ui.DropdownMenu.Item,
7433
- {
7434
- className: "gap-x-2",
7435
- onClick: () => insertRow(index, "above"),
7436
- children: [
7437
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpMini, { className: "text-ui-fg-subtle" }),
7438
- "Insert row above"
7439
- ]
7440
- }
7441
- ),
7442
- /* @__PURE__ */ jsxRuntime.jsxs(
7443
- ui.DropdownMenu.Item,
7444
- {
7445
- className: "gap-x-2",
7446
- onClick: () => insertRow(index, "below"),
7447
- children: [
7448
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownMini, { className: "text-ui-fg-subtle" }),
7449
- "Insert row below"
7450
- ]
7451
- }
7452
- ),
7453
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
7454
- /* @__PURE__ */ jsxRuntime.jsxs(
7455
- ui.DropdownMenu.Item,
7456
- {
7457
- className: "gap-x-2",
7458
- onClick: () => deleteRow(index),
7459
- children: [
7460
- /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
7461
- "Delete row"
7462
- ]
7463
- }
7464
- )
7465
- ] })
7466
- ] })
7467
- ] })
7468
- },
7469
- field.id
7470
- );
7471
- })
7472
- ] }),
7473
- hasUneditableRows && /* @__PURE__ */ jsxRuntime.jsx(InlineTip, { variant: "warning", label: "Some rows are disabled", children: "This object contains non-primitive metadata, such as arrays or objects, that can't be edited here. To edit the disabled rows, use the API directly." })
7474
- ] }),
7475
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
7476
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
7284
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(SalesChannelField, { control: form.control, order }) }),
7285
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
7286
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
7477
7287
  /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
7478
7288
  ] }) })
7479
7289
  ]
7480
7290
  }
7481
7291
  ) });
7482
7292
  };
7483
- const GridInput = React.forwardRef(({ className, ...props }, ref) => {
7484
- return /* @__PURE__ */ jsxRuntime.jsx(
7485
- "input",
7486
- {
7487
- ref,
7488
- ...props,
7489
- autoComplete: "off",
7490
- className: ui.clx(
7491
- "txt-compact-small text-ui-fg-base placeholder:text-ui-fg-muted disabled:text-ui-fg-disabled disabled:bg-ui-bg-base bg-transparent px-2 py-1.5 outline-none",
7492
- className
7493
- )
7494
- }
7495
- );
7496
- });
7497
- GridInput.displayName = "MetadataForm.GridInput";
7498
- const PlaceholderInner = () => {
7499
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
7500
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
7501
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
7502
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" }),
7503
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" })
7504
- ] }) })
7505
- ] });
7506
- };
7507
- const EDITABLE_TYPES = ["string", "number", "boolean"];
7508
- function getDefaultValues(metadata) {
7509
- if (!metadata || !Object.keys(metadata).length) {
7510
- return [
7511
- {
7512
- key: "",
7513
- value: "",
7514
- disabled: false
7515
- }
7516
- ];
7517
- }
7518
- return Object.entries(metadata).map(([key, value]) => {
7519
- if (!EDITABLE_TYPES.includes(typeof value)) {
7520
- return {
7521
- key,
7522
- value,
7523
- disabled: true
7524
- };
7525
- }
7526
- let stringValue = value;
7527
- if (typeof value !== "string") {
7528
- stringValue = JSON.stringify(value);
7529
- }
7530
- return {
7531
- key,
7532
- value: stringValue,
7533
- original_key: key
7534
- };
7293
+ const SalesChannelField = ({ control, order }) => {
7294
+ const salesChannels = useComboboxData({
7295
+ queryFn: async (params) => {
7296
+ return await sdk.admin.salesChannel.list(params);
7297
+ },
7298
+ queryKey: ["sales-channels"],
7299
+ getOptions: (data) => {
7300
+ return data.sales_channels.map((salesChannel) => ({
7301
+ label: salesChannel.name,
7302
+ value: salesChannel.id
7303
+ }));
7304
+ },
7305
+ defaultValue: order.sales_channel_id || void 0
7535
7306
  });
7536
- }
7537
- function parseValues(values) {
7538
- const metadata = values.metadata;
7539
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
7540
- if (isEmpty) {
7541
- return null;
7542
- }
7543
- const update = {};
7544
- metadata.forEach((field) => {
7545
- let key = field.key;
7546
- let value = field.value;
7547
- const disabled = field.disabled;
7548
- if (!key || !value) {
7549
- return;
7550
- }
7551
- if (disabled) {
7552
- update[key] = value;
7553
- return;
7554
- }
7555
- key = key.trim();
7556
- value = value.trim();
7557
- if (value === "true") {
7558
- update[key] = true;
7559
- } else if (value === "false") {
7560
- update[key] = false;
7561
- } else {
7562
- const parsedNumber = parseFloat(value);
7563
- if (!isNaN(parsedNumber)) {
7564
- update[key] = parsedNumber;
7565
- } else {
7566
- update[key] = value;
7307
+ return /* @__PURE__ */ jsxRuntime.jsx(
7308
+ Form$2.Field,
7309
+ {
7310
+ control,
7311
+ name: "sales_channel_id",
7312
+ render: ({ field }) => {
7313
+ return /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
7314
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Sales Channel" }),
7315
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
7316
+ Combobox,
7317
+ {
7318
+ options: salesChannels.options,
7319
+ fetchNextPage: salesChannels.fetchNextPage,
7320
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
7321
+ searchValue: salesChannels.searchValue,
7322
+ onSearchValueChange: salesChannels.onSearchValueChange,
7323
+ placeholder: "Select sales channel",
7324
+ ...field
7325
+ }
7326
+ ) }),
7327
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
7328
+ ] });
7567
7329
  }
7568
7330
  }
7569
- });
7570
- return update;
7571
- }
7572
- function getHasUneditableRows(metadata) {
7573
- if (!metadata) {
7574
- return false;
7575
- }
7576
- return Object.values(metadata).some(
7577
- (value) => !EDITABLE_TYPES.includes(typeof value)
7578
7331
  );
7579
- }
7580
- const PROMOTION_QUERY_KEY = "promotions";
7581
- const promotionsQueryKeys = {
7582
- list: (query2) => [
7583
- PROMOTION_QUERY_KEY,
7584
- query2 ? query2 : void 0
7585
- ],
7586
- detail: (id, query2) => [
7587
- PROMOTION_QUERY_KEY,
7588
- id,
7589
- query2 ? query2 : void 0
7590
- ]
7591
- };
7592
- const usePromotions = (query2, options) => {
7593
- const { data, ...rest } = reactQuery.useQuery({
7594
- queryKey: promotionsQueryKeys.list(query2),
7595
- queryFn: async () => sdk.admin.promotion.list(query2),
7596
- ...options
7597
- });
7598
- return { ...data, ...rest };
7599
7332
  };
7600
- const Promotions = () => {
7333
+ const schema$2 = zod.z.object({
7334
+ sales_channel_id: zod.z.string().min(1)
7335
+ });
7336
+ const STACKED_FOCUS_MODAL_ID = "shipping-form";
7337
+ const Shipping = () => {
7601
7338
  const { id } = reactRouterDom.useParams();
7339
+ const { order, isPending, isError, error } = useOrder(id, {
7340
+ fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
7341
+ });
7602
7342
  const {
7603
7343
  order: preview,
7344
+ isPending: isPreviewPending,
7604
7345
  isError: isPreviewError,
7605
7346
  error: previewError
7606
- } = useOrderPreview(id, void 0);
7347
+ } = useOrderPreview(id);
7607
7348
  useInitiateOrderEdit({ preview });
7608
7349
  const { onCancel } = useCancelOrderEdit({ preview });
7350
+ if (isError) {
7351
+ throw error;
7352
+ }
7609
7353
  if (isPreviewError) {
7610
7354
  throw previewError;
7611
7355
  }
7612
- const isReady = !!preview;
7613
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { onClose: onCancel, children: [
7614
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Promotions" }) }) }),
7615
- isReady && /* @__PURE__ */ jsxRuntime.jsx(PromotionForm, { preview })
7616
- ] });
7356
+ const orderHasItems = (order?.items?.length || 0) > 0;
7357
+ const isReady = preview && !isPreviewPending && order && !isPending;
7358
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
7359
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
7360
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
7361
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
7362
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
7363
+ ] }) }) }),
7364
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
7365
+ ] }) : isReady ? /* @__PURE__ */ jsxRuntime.jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7366
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
7367
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
7368
+ ] }) });
7617
7369
  };
7618
- const PromotionForm = ({ preview }) => {
7619
- const { items, shipping_methods } = preview;
7370
+ const ShippingForm = ({ preview, order }) => {
7371
+ const { setIsOpen } = useStackedModal();
7620
7372
  const [isSubmitting, setIsSubmitting] = React.useState(false);
7621
- const [comboboxValue, setComboboxValue] = React.useState("");
7622
- const { handleSuccess } = useRouteModal();
7623
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
7624
- const promoIds = getPromotionIds(items, shipping_methods);
7625
- const { promotions, isPending, isError, error } = usePromotions(
7373
+ const [data, setData] = React.useState(null);
7374
+ const appliedShippingOptionIds = preview.shipping_methods?.map((method) => method.shipping_option_id).filter(Boolean);
7375
+ const { shipping_options } = useShippingOptions(
7626
7376
  {
7627
- id: promoIds
7377
+ id: appliedShippingOptionIds,
7378
+ fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
7628
7379
  },
7629
7380
  {
7630
- enabled: !!promoIds.length
7381
+ enabled: appliedShippingOptionIds.length > 0
7631
7382
  }
7632
7383
  );
7633
- const comboboxData = useComboboxData({
7634
- queryKey: ["promotions", "combobox", promoIds],
7635
- queryFn: async (params) => {
7636
- return await sdk.admin.promotion.list({
7637
- ...params,
7638
- id: {
7639
- $nin: promoIds
7640
- }
7641
- });
7642
- },
7643
- getOptions: (data) => {
7644
- return data.promotions.map((promotion) => ({
7645
- label: promotion.code,
7646
- value: promotion.code
7647
- }));
7648
- }
7649
- });
7650
- const add = async (value) => {
7651
- if (!value) {
7652
- return;
7653
- }
7654
- addPromotions(
7655
- {
7656
- promo_codes: [value]
7657
- },
7658
- {
7659
- onError: (e) => {
7660
- ui.toast.error(e.message);
7661
- comboboxData.onSearchValueChange("");
7662
- setComboboxValue("");
7663
- },
7664
- onSuccess: () => {
7665
- comboboxData.onSearchValueChange("");
7666
- setComboboxValue("");
7667
- }
7668
- }
7669
- );
7670
- };
7384
+ const uniqueShippingProfiles = React.useMemo(() => {
7385
+ const profiles = /* @__PURE__ */ new Map();
7386
+ getUniqueShippingProfiles(order.items).forEach((profile) => {
7387
+ profiles.set(profile.id, profile);
7388
+ });
7389
+ shipping_options?.forEach((option) => {
7390
+ profiles.set(option.shipping_profile_id, option.shipping_profile);
7391
+ });
7392
+ return Array.from(profiles.values());
7393
+ }, [order.items, shipping_options]);
7394
+ const { handleSuccess } = useRouteModal();
7671
7395
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
7672
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
7396
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
7397
+ const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
7398
+ const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
7673
7399
  const onSubmit = async () => {
7674
7400
  setIsSubmitting(true);
7675
7401
  let requestSucceeded = false;
7676
7402
  await requestOrderEdit(void 0, {
7677
7403
  onError: (e) => {
7678
- ui.toast.error(e.message);
7404
+ ui.toast.error(`Failed to request order edit: ${e.message}`);
7679
7405
  },
7680
7406
  onSuccess: () => {
7681
7407
  requestSucceeded = true;
@@ -7687,358 +7413,7 @@ const PromotionForm = ({ preview }) => {
7687
7413
  }
7688
7414
  await confirmOrderEdit(void 0, {
7689
7415
  onError: (e) => {
7690
- ui.toast.error(e.message);
7691
- },
7692
- onSuccess: () => {
7693
- handleSuccess();
7694
- },
7695
- onSettled: () => {
7696
- setIsSubmitting(false);
7697
- }
7698
- });
7699
- };
7700
- if (isError) {
7701
- throw error;
7702
- }
7703
- return /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
7704
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
7705
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
7706
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
7707
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
7708
- /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
7709
- ] }),
7710
- /* @__PURE__ */ jsxRuntime.jsx(
7711
- Combobox,
7712
- {
7713
- id: "promotion-combobox",
7714
- "aria-describedby": "promotion-combobox-hint",
7715
- isFetchingNextPage: comboboxData.isFetchingNextPage,
7716
- fetchNextPage: comboboxData.fetchNextPage,
7717
- options: comboboxData.options,
7718
- onSearchValueChange: comboboxData.onSearchValueChange,
7719
- searchValue: comboboxData.searchValue,
7720
- disabled: comboboxData.disabled || isAddingPromotions,
7721
- onChange: add,
7722
- value: comboboxValue
7723
- }
7724
- )
7725
- ] }),
7726
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
7727
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: promotions?.map((promotion) => /* @__PURE__ */ jsxRuntime.jsx(
7728
- PromotionItem,
7729
- {
7730
- promotion,
7731
- orderId: preview.id,
7732
- isLoading: isPending
7733
- },
7734
- promotion.id
7735
- )) })
7736
- ] }) }),
7737
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
7738
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
7739
- /* @__PURE__ */ jsxRuntime.jsx(
7740
- ui.Button,
7741
- {
7742
- size: "small",
7743
- type: "submit",
7744
- isLoading: isSubmitting || isAddingPromotions,
7745
- children: "Save"
7746
- }
7747
- )
7748
- ] }) })
7749
- ] });
7750
- };
7751
- const PromotionItem = ({
7752
- promotion,
7753
- orderId,
7754
- isLoading
7755
- }) => {
7756
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
7757
- const onRemove = async () => {
7758
- removePromotions(
7759
- {
7760
- promo_codes: [promotion.code]
7761
- },
7762
- {
7763
- onError: (e) => {
7764
- ui.toast.error(e.message);
7765
- }
7766
- }
7767
- );
7768
- };
7769
- const displayValue = getDisplayValue(promotion);
7770
- return /* @__PURE__ */ jsxRuntime.jsxs(
7771
- "div",
7772
- {
7773
- className: ui.clx(
7774
- "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
7775
- {
7776
- "animate-pulse": isLoading
7777
- }
7778
- ),
7779
- children: [
7780
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7781
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
7782
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
7783
- displayValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
7784
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: displayValue }),
7785
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: "·" })
7786
- ] }),
7787
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "capitalize", children: promotion.application_method?.allocation })
7788
- ] })
7789
- ] }),
7790
- /* @__PURE__ */ jsxRuntime.jsx(
7791
- ui.IconButton,
7792
- {
7793
- size: "small",
7794
- type: "button",
7795
- variant: "transparent",
7796
- onClick: onRemove,
7797
- isLoading: isPending || isLoading,
7798
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.XMark, {})
7799
- }
7800
- )
7801
- ]
7802
- },
7803
- promotion.id
7804
- );
7805
- };
7806
- function getDisplayValue(promotion) {
7807
- const value = promotion.application_method?.value;
7808
- if (!value) {
7809
- return null;
7810
- }
7811
- if (promotion.application_method?.type === "fixed") {
7812
- const currency = promotion.application_method?.currency_code;
7813
- if (!currency) {
7814
- return null;
7815
- }
7816
- return getLocaleAmount(value, currency);
7817
- } else if (promotion.application_method?.type === "percentage") {
7818
- return formatPercentage(value);
7819
- }
7820
- return null;
7821
- }
7822
- const formatter = new Intl.NumberFormat([], {
7823
- style: "percent",
7824
- minimumFractionDigits: 2
7825
- });
7826
- const formatPercentage = (value, isPercentageValue = false) => {
7827
- let val = value || 0;
7828
- if (!isPercentageValue) {
7829
- val = val / 100;
7830
- }
7831
- return formatter.format(val);
7832
- };
7833
- function getPromotionIds(items, shippingMethods) {
7834
- const promotionIds = /* @__PURE__ */ new Set();
7835
- for (const item of items) {
7836
- if (item.adjustments) {
7837
- for (const adjustment of item.adjustments) {
7838
- if (adjustment.promotion_id) {
7839
- promotionIds.add(adjustment.promotion_id);
7840
- }
7841
- }
7842
- }
7843
- }
7844
- for (const shippingMethod of shippingMethods) {
7845
- if (shippingMethod.adjustments) {
7846
- for (const adjustment of shippingMethod.adjustments) {
7847
- if (adjustment.promotion_id) {
7848
- promotionIds.add(adjustment.promotion_id);
7849
- }
7850
- }
7851
- }
7852
- }
7853
- return Array.from(promotionIds);
7854
- }
7855
- const SalesChannel = () => {
7856
- const { id } = reactRouterDom.useParams();
7857
- const { draft_order, isPending, isError, error } = useDraftOrder(
7858
- id,
7859
- {
7860
- fields: "+sales_channel_id"
7861
- },
7862
- {
7863
- enabled: !!id
7864
- }
7865
- );
7866
- if (isError) {
7867
- throw error;
7868
- }
7869
- const ISrEADY = !!draft_order && !isPending;
7870
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
7871
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
7872
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Sales Channel" }) }),
7873
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
7874
- ] }),
7875
- ISrEADY && /* @__PURE__ */ jsxRuntime.jsx(SalesChannelForm, { order: draft_order })
7876
- ] });
7877
- };
7878
- const SalesChannelForm = ({ order }) => {
7879
- const form = reactHookForm.useForm({
7880
- defaultValues: {
7881
- sales_channel_id: order.sales_channel_id || ""
7882
- },
7883
- resolver: zod$1.zodResolver(schema$2)
7884
- });
7885
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
7886
- const { handleSuccess } = useRouteModal();
7887
- const onSubmit = form.handleSubmit(async (data) => {
7888
- await mutateAsync(
7889
- {
7890
- sales_channel_id: data.sales_channel_id
7891
- },
7892
- {
7893
- onSuccess: () => {
7894
- ui.toast.success("Sales channel updated");
7895
- handleSuccess();
7896
- },
7897
- onError: (error) => {
7898
- ui.toast.error(error.message);
7899
- }
7900
- }
7901
- );
7902
- });
7903
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
7904
- KeyboundForm,
7905
- {
7906
- className: "flex flex-1 flex-col overflow-hidden",
7907
- onSubmit,
7908
- children: [
7909
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(SalesChannelField, { control: form.control, order }) }),
7910
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
7911
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
7912
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
7913
- ] }) })
7914
- ]
7915
- }
7916
- ) });
7917
- };
7918
- const SalesChannelField = ({ control, order }) => {
7919
- const salesChannels = useComboboxData({
7920
- queryFn: async (params) => {
7921
- return await sdk.admin.salesChannel.list(params);
7922
- },
7923
- queryKey: ["sales-channels"],
7924
- getOptions: (data) => {
7925
- return data.sales_channels.map((salesChannel) => ({
7926
- label: salesChannel.name,
7927
- value: salesChannel.id
7928
- }));
7929
- },
7930
- defaultValue: order.sales_channel_id || void 0
7931
- });
7932
- return /* @__PURE__ */ jsxRuntime.jsx(
7933
- Form$2.Field,
7934
- {
7935
- control,
7936
- name: "sales_channel_id",
7937
- render: ({ field }) => {
7938
- return /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
7939
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Sales Channel" }),
7940
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
7941
- Combobox,
7942
- {
7943
- options: salesChannels.options,
7944
- fetchNextPage: salesChannels.fetchNextPage,
7945
- isFetchingNextPage: salesChannels.isFetchingNextPage,
7946
- searchValue: salesChannels.searchValue,
7947
- onSearchValueChange: salesChannels.onSearchValueChange,
7948
- placeholder: "Select sales channel",
7949
- ...field
7950
- }
7951
- ) }),
7952
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
7953
- ] });
7954
- }
7955
- }
7956
- );
7957
- };
7958
- const schema$2 = zod.z.object({
7959
- sales_channel_id: zod.z.string().min(1)
7960
- });
7961
- const STACKED_FOCUS_MODAL_ID = "shipping-form";
7962
- const Shipping = () => {
7963
- const { id } = reactRouterDom.useParams();
7964
- const { order, isPending, isError, error } = useOrder(id, {
7965
- fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
7966
- });
7967
- const {
7968
- order: preview,
7969
- isPending: isPreviewPending,
7970
- isError: isPreviewError,
7971
- error: previewError
7972
- } = useOrderPreview(id);
7973
- useInitiateOrderEdit({ preview });
7974
- const { onCancel } = useCancelOrderEdit({ preview });
7975
- if (isError) {
7976
- throw error;
7977
- }
7978
- if (isPreviewError) {
7979
- throw previewError;
7980
- }
7981
- const orderHasItems = (order?.items?.length || 0) > 0;
7982
- const isReady = preview && !isPreviewPending && order && !isPending;
7983
- return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
7984
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
7985
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
7986
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
7987
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
7988
- ] }) }) }),
7989
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
7990
- ] }) : isReady ? /* @__PURE__ */ jsxRuntime.jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7991
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
7992
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
7993
- ] }) });
7994
- };
7995
- const ShippingForm = ({ preview, order }) => {
7996
- const { setIsOpen } = useStackedModal();
7997
- const [isSubmitting, setIsSubmitting] = React.useState(false);
7998
- const [data, setData] = React.useState(null);
7999
- const appliedShippingOptionIds = preview.shipping_methods?.map((method) => method.shipping_option_id).filter(Boolean);
8000
- const { shipping_options } = useShippingOptions(
8001
- {
8002
- id: appliedShippingOptionIds,
8003
- fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
8004
- },
8005
- {
8006
- enabled: appliedShippingOptionIds.length > 0
8007
- }
8008
- );
8009
- const uniqueShippingProfiles = React.useMemo(() => {
8010
- const profiles = /* @__PURE__ */ new Map();
8011
- getUniqueShippingProfiles(order.items).forEach((profile) => {
8012
- profiles.set(profile.id, profile);
8013
- });
8014
- shipping_options?.forEach((option) => {
8015
- profiles.set(option.shipping_profile_id, option.shipping_profile);
8016
- });
8017
- return Array.from(profiles.values());
8018
- }, [order.items, shipping_options]);
8019
- const { handleSuccess } = useRouteModal();
8020
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
8021
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
8022
- const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
8023
- const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
8024
- const onSubmit = async () => {
8025
- setIsSubmitting(true);
8026
- let requestSucceeded = false;
8027
- await requestOrderEdit(void 0, {
8028
- onError: (e) => {
8029
- ui.toast.error(`Failed to request order edit: ${e.message}`);
8030
- },
8031
- onSuccess: () => {
8032
- requestSucceeded = true;
8033
- }
8034
- });
8035
- if (!requestSucceeded) {
8036
- setIsSubmitting(false);
8037
- return;
8038
- }
8039
- await confirmOrderEdit(void 0, {
8040
- onError: (e) => {
8041
- ui.toast.error(`Failed to confirm order edit: ${e.message}`);
7416
+ ui.toast.error(`Failed to confirm order edit: ${e.message}`);
8042
7417
  },
8043
7418
  onSuccess: () => {
8044
7419
  handleSuccess();
@@ -9359,76 +8734,701 @@ const Illustration = () => {
9359
8734
  /* @__PURE__ */ jsxRuntime.jsx("g", { clipPath: "url(#clip5_20915_38670)", children: /* @__PURE__ */ jsxRuntime.jsx(
9360
8735
  "path",
9361
8736
  {
9362
- d: "M146.894 101.198L139.51 101.155L139.486 105.365",
9363
- stroke: "#A1A1AA",
9364
- strokeWidth: "1.5",
9365
- strokeLinecap: "round",
9366
- strokeLinejoin: "round"
8737
+ d: "M146.894 101.198L139.51 101.155L139.486 105.365",
8738
+ stroke: "#A1A1AA",
8739
+ strokeWidth: "1.5",
8740
+ strokeLinecap: "round",
8741
+ strokeLinejoin: "round"
8742
+ }
8743
+ ) }),
8744
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
8745
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
8746
+ "rect",
8747
+ {
8748
+ width: "12",
8749
+ height: "12",
8750
+ fill: "white",
8751
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
8752
+ }
8753
+ ) }),
8754
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
8755
+ "rect",
8756
+ {
8757
+ width: "12",
8758
+ height: "12",
8759
+ fill: "white",
8760
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
8761
+ }
8762
+ ) }),
8763
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
8764
+ "rect",
8765
+ {
8766
+ width: "12",
8767
+ height: "12",
8768
+ fill: "white",
8769
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
8770
+ }
8771
+ ) }),
8772
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
8773
+ "rect",
8774
+ {
8775
+ width: "12",
8776
+ height: "12",
8777
+ fill: "white",
8778
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
8779
+ }
8780
+ ) }),
8781
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
8782
+ "rect",
8783
+ {
8784
+ width: "12",
8785
+ height: "12",
8786
+ fill: "white",
8787
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
8788
+ }
8789
+ ) }),
8790
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
8791
+ "rect",
8792
+ {
8793
+ width: "12",
8794
+ height: "12",
8795
+ fill: "white",
8796
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
8797
+ }
8798
+ ) })
8799
+ ] })
8800
+ ]
8801
+ }
8802
+ );
8803
+ };
8804
+ const schema = zod.z.object({
8805
+ customer_id: zod.z.string().min(1)
8806
+ });
8807
+ const PROMOTION_QUERY_KEY = "promotions";
8808
+ const promotionsQueryKeys = {
8809
+ list: (query2) => [
8810
+ PROMOTION_QUERY_KEY,
8811
+ query2 ? query2 : void 0
8812
+ ],
8813
+ detail: (id, query2) => [
8814
+ PROMOTION_QUERY_KEY,
8815
+ id,
8816
+ query2 ? query2 : void 0
8817
+ ]
8818
+ };
8819
+ const usePromotions = (query2, options) => {
8820
+ const { data, ...rest } = reactQuery.useQuery({
8821
+ queryKey: promotionsQueryKeys.list(query2),
8822
+ queryFn: async () => sdk.admin.promotion.list(query2),
8823
+ ...options
8824
+ });
8825
+ return { ...data, ...rest };
8826
+ };
8827
+ const Promotions = () => {
8828
+ const { id } = reactRouterDom.useParams();
8829
+ const {
8830
+ order: preview,
8831
+ isError: isPreviewError,
8832
+ error: previewError
8833
+ } = useOrderPreview(id, void 0);
8834
+ useInitiateOrderEdit({ preview });
8835
+ const { onCancel } = useCancelOrderEdit({ preview });
8836
+ if (isPreviewError) {
8837
+ throw previewError;
8838
+ }
8839
+ const isReady = !!preview;
8840
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { onClose: onCancel, children: [
8841
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Promotions" }) }) }),
8842
+ isReady && /* @__PURE__ */ jsxRuntime.jsx(PromotionForm, { preview })
8843
+ ] });
8844
+ };
8845
+ const PromotionForm = ({ preview }) => {
8846
+ const { items, shipping_methods } = preview;
8847
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
8848
+ const [comboboxValue, setComboboxValue] = React.useState("");
8849
+ const { handleSuccess } = useRouteModal();
8850
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
8851
+ const promoIds = getPromotionIds(items, shipping_methods);
8852
+ const { promotions, isPending, isError, error } = usePromotions(
8853
+ {
8854
+ id: promoIds
8855
+ },
8856
+ {
8857
+ enabled: !!promoIds.length
8858
+ }
8859
+ );
8860
+ const comboboxData = useComboboxData({
8861
+ queryKey: ["promotions", "combobox", promoIds],
8862
+ queryFn: async (params) => {
8863
+ return await sdk.admin.promotion.list({
8864
+ ...params,
8865
+ id: {
8866
+ $nin: promoIds
8867
+ }
8868
+ });
8869
+ },
8870
+ getOptions: (data) => {
8871
+ return data.promotions.map((promotion) => ({
8872
+ label: promotion.code,
8873
+ value: promotion.code
8874
+ }));
8875
+ }
8876
+ });
8877
+ const add = async (value) => {
8878
+ if (!value) {
8879
+ return;
8880
+ }
8881
+ addPromotions(
8882
+ {
8883
+ promo_codes: [value]
8884
+ },
8885
+ {
8886
+ onError: (e) => {
8887
+ ui.toast.error(e.message);
8888
+ comboboxData.onSearchValueChange("");
8889
+ setComboboxValue("");
8890
+ },
8891
+ onSuccess: () => {
8892
+ comboboxData.onSearchValueChange("");
8893
+ setComboboxValue("");
8894
+ }
8895
+ }
8896
+ );
8897
+ };
8898
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
8899
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
8900
+ const onSubmit = async () => {
8901
+ setIsSubmitting(true);
8902
+ let requestSucceeded = false;
8903
+ await requestOrderEdit(void 0, {
8904
+ onError: (e) => {
8905
+ ui.toast.error(e.message);
8906
+ },
8907
+ onSuccess: () => {
8908
+ requestSucceeded = true;
8909
+ }
8910
+ });
8911
+ if (!requestSucceeded) {
8912
+ setIsSubmitting(false);
8913
+ return;
8914
+ }
8915
+ await confirmOrderEdit(void 0, {
8916
+ onError: (e) => {
8917
+ ui.toast.error(e.message);
8918
+ },
8919
+ onSuccess: () => {
8920
+ handleSuccess();
8921
+ },
8922
+ onSettled: () => {
8923
+ setIsSubmitting(false);
8924
+ }
8925
+ });
8926
+ };
8927
+ if (isError) {
8928
+ throw error;
8929
+ }
8930
+ return /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
8931
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
8932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
8933
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
8934
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
8935
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
8936
+ ] }),
8937
+ /* @__PURE__ */ jsxRuntime.jsx(
8938
+ Combobox,
8939
+ {
8940
+ id: "promotion-combobox",
8941
+ "aria-describedby": "promotion-combobox-hint",
8942
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
8943
+ fetchNextPage: comboboxData.fetchNextPage,
8944
+ options: comboboxData.options,
8945
+ onSearchValueChange: comboboxData.onSearchValueChange,
8946
+ searchValue: comboboxData.searchValue,
8947
+ disabled: comboboxData.disabled || isAddingPromotions,
8948
+ onChange: add,
8949
+ value: comboboxValue
8950
+ }
8951
+ )
8952
+ ] }),
8953
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
8954
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: promotions?.map((promotion) => /* @__PURE__ */ jsxRuntime.jsx(
8955
+ PromotionItem,
8956
+ {
8957
+ promotion,
8958
+ orderId: preview.id,
8959
+ isLoading: isPending
8960
+ },
8961
+ promotion.id
8962
+ )) })
8963
+ ] }) }),
8964
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
8965
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
8966
+ /* @__PURE__ */ jsxRuntime.jsx(
8967
+ ui.Button,
8968
+ {
8969
+ size: "small",
8970
+ type: "submit",
8971
+ isLoading: isSubmitting || isAddingPromotions,
8972
+ children: "Save"
8973
+ }
8974
+ )
8975
+ ] }) })
8976
+ ] });
8977
+ };
8978
+ const PromotionItem = ({
8979
+ promotion,
8980
+ orderId,
8981
+ isLoading
8982
+ }) => {
8983
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
8984
+ const onRemove = async () => {
8985
+ removePromotions(
8986
+ {
8987
+ promo_codes: [promotion.code]
8988
+ },
8989
+ {
8990
+ onError: (e) => {
8991
+ ui.toast.error(e.message);
8992
+ }
8993
+ }
8994
+ );
8995
+ };
8996
+ const displayValue = getDisplayValue(promotion);
8997
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8998
+ "div",
8999
+ {
9000
+ className: ui.clx(
9001
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
9002
+ {
9003
+ "animate-pulse": isLoading
9004
+ }
9005
+ ),
9006
+ children: [
9007
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9008
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
9009
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
9010
+ displayValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
9011
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: displayValue }),
9012
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: "·" })
9013
+ ] }),
9014
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "capitalize", children: promotion.application_method?.allocation })
9015
+ ] })
9016
+ ] }),
9017
+ /* @__PURE__ */ jsxRuntime.jsx(
9018
+ ui.IconButton,
9019
+ {
9020
+ size: "small",
9021
+ type: "button",
9022
+ variant: "transparent",
9023
+ onClick: onRemove,
9024
+ isLoading: isPending || isLoading,
9025
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.XMark, {})
9367
9026
  }
9368
- ) }),
9369
- /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
9370
- /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
9371
- "rect",
9372
- {
9373
- width: "12",
9374
- height: "12",
9375
- fill: "white",
9376
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
9377
- }
9378
- ) }),
9379
- /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
9380
- "rect",
9381
- {
9382
- width: "12",
9383
- height: "12",
9384
- fill: "white",
9385
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
9386
- }
9387
- ) }),
9388
- /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
9389
- "rect",
9390
- {
9391
- width: "12",
9392
- height: "12",
9393
- fill: "white",
9394
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
9395
- }
9396
- ) }),
9397
- /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
9398
- "rect",
9399
- {
9400
- width: "12",
9401
- height: "12",
9402
- fill: "white",
9403
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
9404
- }
9405
- ) }),
9406
- /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
9407
- "rect",
9408
- {
9409
- width: "12",
9410
- height: "12",
9411
- fill: "white",
9412
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
9413
- }
9414
- ) }),
9415
- /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsxRuntime.jsx(
9416
- "rect",
9027
+ )
9028
+ ]
9029
+ },
9030
+ promotion.id
9031
+ );
9032
+ };
9033
+ function getDisplayValue(promotion) {
9034
+ const value = promotion.application_method?.value;
9035
+ if (!value) {
9036
+ return null;
9037
+ }
9038
+ if (promotion.application_method?.type === "fixed") {
9039
+ const currency = promotion.application_method?.currency_code;
9040
+ if (!currency) {
9041
+ return null;
9042
+ }
9043
+ return getLocaleAmount(value, currency);
9044
+ } else if (promotion.application_method?.type === "percentage") {
9045
+ return formatPercentage(value);
9046
+ }
9047
+ return null;
9048
+ }
9049
+ const formatter = new Intl.NumberFormat([], {
9050
+ style: "percent",
9051
+ minimumFractionDigits: 2
9052
+ });
9053
+ const formatPercentage = (value, isPercentageValue = false) => {
9054
+ let val = value || 0;
9055
+ if (!isPercentageValue) {
9056
+ val = val / 100;
9057
+ }
9058
+ return formatter.format(val);
9059
+ };
9060
+ function getPromotionIds(items, shippingMethods) {
9061
+ const promotionIds = /* @__PURE__ */ new Set();
9062
+ for (const item of items) {
9063
+ if (item.adjustments) {
9064
+ for (const adjustment of item.adjustments) {
9065
+ if (adjustment.promotion_id) {
9066
+ promotionIds.add(adjustment.promotion_id);
9067
+ }
9068
+ }
9069
+ }
9070
+ }
9071
+ for (const shippingMethod of shippingMethods) {
9072
+ if (shippingMethod.adjustments) {
9073
+ for (const adjustment of shippingMethod.adjustments) {
9074
+ if (adjustment.promotion_id) {
9075
+ promotionIds.add(adjustment.promotion_id);
9076
+ }
9077
+ }
9078
+ }
9079
+ }
9080
+ return Array.from(promotionIds);
9081
+ }
9082
+ const InlineTip = React.forwardRef(
9083
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
9084
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
9085
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9086
+ "div",
9087
+ {
9088
+ ref,
9089
+ className: ui.clx(
9090
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
9091
+ className
9092
+ ),
9093
+ ...props,
9094
+ children: [
9095
+ /* @__PURE__ */ jsxRuntime.jsx(
9096
+ "div",
9417
9097
  {
9418
- width: "12",
9419
- height: "12",
9420
- fill: "white",
9421
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
9098
+ role: "presentation",
9099
+ className: ui.clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
9100
+ "bg-ui-tag-orange-icon": variant === "warning"
9101
+ })
9422
9102
  }
9423
- ) })
9424
- ] })
9103
+ ),
9104
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-pretty", children: [
9105
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
9106
+ labelValue,
9107
+ ":"
9108
+ ] }),
9109
+ " ",
9110
+ children
9111
+ ] })
9112
+ ]
9113
+ }
9114
+ );
9115
+ }
9116
+ );
9117
+ InlineTip.displayName = "InlineTip";
9118
+ const MetadataFieldSchema = zod.z.object({
9119
+ key: zod.z.string(),
9120
+ disabled: zod.z.boolean().optional(),
9121
+ value: zod.z.any()
9122
+ });
9123
+ const MetadataSchema = zod.z.object({
9124
+ metadata: zod.z.array(MetadataFieldSchema)
9125
+ });
9126
+ const Metadata = () => {
9127
+ const { id } = reactRouterDom.useParams();
9128
+ const { order, isPending, isError, error } = useOrder(id, {
9129
+ fields: "metadata"
9130
+ });
9131
+ if (isError) {
9132
+ throw error;
9133
+ }
9134
+ const isReady = !isPending && !!order;
9135
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9136
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
9137
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Metadata" }) }),
9138
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
9139
+ ] }),
9140
+ !isReady ? /* @__PURE__ */ jsxRuntime.jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetadataForm, { orderId: id, metadata: order?.metadata })
9141
+ ] });
9142
+ };
9143
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
9144
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
9145
+ const MetadataForm = ({ orderId, metadata }) => {
9146
+ const { handleSuccess } = useRouteModal();
9147
+ const hasUneditableRows = getHasUneditableRows(metadata);
9148
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
9149
+ const form = reactHookForm.useForm({
9150
+ defaultValues: {
9151
+ metadata: getDefaultValues(metadata)
9152
+ },
9153
+ resolver: zod$1.zodResolver(MetadataSchema)
9154
+ });
9155
+ const handleSubmit = form.handleSubmit(async (data) => {
9156
+ const parsedData = parseValues(data);
9157
+ await mutateAsync(
9158
+ {
9159
+ metadata: parsedData
9160
+ },
9161
+ {
9162
+ onSuccess: () => {
9163
+ ui.toast.success("Metadata updated");
9164
+ handleSuccess();
9165
+ },
9166
+ onError: (error) => {
9167
+ ui.toast.error(error.message);
9168
+ }
9169
+ }
9170
+ );
9171
+ });
9172
+ const { fields, insert, remove } = reactHookForm.useFieldArray({
9173
+ control: form.control,
9174
+ name: "metadata"
9175
+ });
9176
+ function deleteRow(index) {
9177
+ remove(index);
9178
+ if (fields.length === 1) {
9179
+ insert(0, {
9180
+ key: "",
9181
+ value: "",
9182
+ disabled: false
9183
+ });
9184
+ }
9185
+ }
9186
+ function insertRow(index, position) {
9187
+ insert(index + (position === "above" ? 0 : 1), {
9188
+ key: "",
9189
+ value: "",
9190
+ disabled: false
9191
+ });
9192
+ }
9193
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
9194
+ KeyboundForm,
9195
+ {
9196
+ onSubmit: handleSubmit,
9197
+ className: "flex flex-1 flex-col overflow-hidden",
9198
+ children: [
9199
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
9200
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
9201
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
9202
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsxRuntime.jsx("label", { id: METADATA_KEY_LABEL_ID, children: "Key" }) }),
9203
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsxRuntime.jsx("label", { id: METADATA_VALUE_LABEL_ID, children: "Value" }) })
9204
+ ] }),
9205
+ fields.map((field, index) => {
9206
+ const isDisabled = field.disabled || false;
9207
+ let placeholder = "-";
9208
+ if (typeof field.value === "object") {
9209
+ placeholder = "{ ... }";
9210
+ }
9211
+ if (Array.isArray(field.value)) {
9212
+ placeholder = "[ ... ]";
9213
+ }
9214
+ return /* @__PURE__ */ jsxRuntime.jsx(
9215
+ ConditionalTooltip,
9216
+ {
9217
+ showTooltip: isDisabled,
9218
+ content: "This row is disabled because it contains non-primitive data.",
9219
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/table relative", children: [
9220
+ /* @__PURE__ */ jsxRuntime.jsxs(
9221
+ "div",
9222
+ {
9223
+ className: ui.clx("grid grid-cols-2 divide-x", {
9224
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
9225
+ }),
9226
+ children: [
9227
+ /* @__PURE__ */ jsxRuntime.jsx(
9228
+ Form$2.Field,
9229
+ {
9230
+ control: form.control,
9231
+ name: `metadata.${index}.key`,
9232
+ render: ({ field: field2 }) => {
9233
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
9234
+ GridInput,
9235
+ {
9236
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
9237
+ ...field2,
9238
+ disabled: isDisabled,
9239
+ placeholder: "Key"
9240
+ }
9241
+ ) }) });
9242
+ }
9243
+ }
9244
+ ),
9245
+ /* @__PURE__ */ jsxRuntime.jsx(
9246
+ Form$2.Field,
9247
+ {
9248
+ control: form.control,
9249
+ name: `metadata.${index}.value`,
9250
+ render: ({ field: { value, ...field2 } }) => {
9251
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
9252
+ GridInput,
9253
+ {
9254
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
9255
+ ...field2,
9256
+ value: isDisabled ? placeholder : value,
9257
+ disabled: isDisabled,
9258
+ placeholder: "Value"
9259
+ }
9260
+ ) }) });
9261
+ }
9262
+ }
9263
+ )
9264
+ ]
9265
+ }
9266
+ ),
9267
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
9268
+ /* @__PURE__ */ jsxRuntime.jsx(
9269
+ ui.DropdownMenu.Trigger,
9270
+ {
9271
+ className: ui.clx(
9272
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
9273
+ {
9274
+ hidden: isDisabled
9275
+ }
9276
+ ),
9277
+ disabled: isDisabled,
9278
+ asChild: true,
9279
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisVertical, {}) })
9280
+ }
9281
+ ),
9282
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
9283
+ /* @__PURE__ */ jsxRuntime.jsxs(
9284
+ ui.DropdownMenu.Item,
9285
+ {
9286
+ className: "gap-x-2",
9287
+ onClick: () => insertRow(index, "above"),
9288
+ children: [
9289
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpMini, { className: "text-ui-fg-subtle" }),
9290
+ "Insert row above"
9291
+ ]
9292
+ }
9293
+ ),
9294
+ /* @__PURE__ */ jsxRuntime.jsxs(
9295
+ ui.DropdownMenu.Item,
9296
+ {
9297
+ className: "gap-x-2",
9298
+ onClick: () => insertRow(index, "below"),
9299
+ children: [
9300
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownMini, { className: "text-ui-fg-subtle" }),
9301
+ "Insert row below"
9302
+ ]
9303
+ }
9304
+ ),
9305
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
9306
+ /* @__PURE__ */ jsxRuntime.jsxs(
9307
+ ui.DropdownMenu.Item,
9308
+ {
9309
+ className: "gap-x-2",
9310
+ onClick: () => deleteRow(index),
9311
+ children: [
9312
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
9313
+ "Delete row"
9314
+ ]
9315
+ }
9316
+ )
9317
+ ] })
9318
+ ] })
9319
+ ] })
9320
+ },
9321
+ field.id
9322
+ );
9323
+ })
9324
+ ] }),
9325
+ hasUneditableRows && /* @__PURE__ */ jsxRuntime.jsx(InlineTip, { variant: "warning", label: "Some rows are disabled", children: "This object contains non-primitive metadata, such as arrays or objects, that can't be edited here. To edit the disabled rows, use the API directly." })
9326
+ ] }),
9327
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
9328
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
9329
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9330
+ ] }) })
9425
9331
  ]
9426
9332
  }
9427
- );
9333
+ ) });
9428
9334
  };
9429
- const schema = zod.z.object({
9430
- customer_id: zod.z.string().min(1)
9335
+ const GridInput = React.forwardRef(({ className, ...props }, ref) => {
9336
+ return /* @__PURE__ */ jsxRuntime.jsx(
9337
+ "input",
9338
+ {
9339
+ ref,
9340
+ ...props,
9341
+ autoComplete: "off",
9342
+ className: ui.clx(
9343
+ "txt-compact-small text-ui-fg-base placeholder:text-ui-fg-muted disabled:text-ui-fg-disabled disabled:bg-ui-bg-base bg-transparent px-2 py-1.5 outline-none",
9344
+ className
9345
+ )
9346
+ }
9347
+ );
9431
9348
  });
9349
+ GridInput.displayName = "MetadataForm.GridInput";
9350
+ const PlaceholderInner = () => {
9351
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
9352
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
9353
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
9354
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" }),
9355
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" })
9356
+ ] }) })
9357
+ ] });
9358
+ };
9359
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
9360
+ function getDefaultValues(metadata) {
9361
+ if (!metadata || !Object.keys(metadata).length) {
9362
+ return [
9363
+ {
9364
+ key: "",
9365
+ value: "",
9366
+ disabled: false
9367
+ }
9368
+ ];
9369
+ }
9370
+ return Object.entries(metadata).map(([key, value]) => {
9371
+ if (!EDITABLE_TYPES.includes(typeof value)) {
9372
+ return {
9373
+ key,
9374
+ value,
9375
+ disabled: true
9376
+ };
9377
+ }
9378
+ let stringValue = value;
9379
+ if (typeof value !== "string") {
9380
+ stringValue = JSON.stringify(value);
9381
+ }
9382
+ return {
9383
+ key,
9384
+ value: stringValue,
9385
+ original_key: key
9386
+ };
9387
+ });
9388
+ }
9389
+ function parseValues(values) {
9390
+ const metadata = values.metadata;
9391
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
9392
+ if (isEmpty) {
9393
+ return null;
9394
+ }
9395
+ const update = {};
9396
+ metadata.forEach((field) => {
9397
+ let key = field.key;
9398
+ let value = field.value;
9399
+ const disabled = field.disabled;
9400
+ if (!key || !value) {
9401
+ return;
9402
+ }
9403
+ if (disabled) {
9404
+ update[key] = value;
9405
+ return;
9406
+ }
9407
+ key = key.trim();
9408
+ value = value.trim();
9409
+ if (value === "true") {
9410
+ update[key] = true;
9411
+ } else if (value === "false") {
9412
+ update[key] = false;
9413
+ } else {
9414
+ const parsedNumber = parseFloat(value);
9415
+ if (!isNaN(parsedNumber)) {
9416
+ update[key] = parsedNumber;
9417
+ } else {
9418
+ update[key] = value;
9419
+ }
9420
+ }
9421
+ });
9422
+ return update;
9423
+ }
9424
+ function getHasUneditableRows(metadata) {
9425
+ if (!metadata) {
9426
+ return false;
9427
+ }
9428
+ return Object.values(metadata).some(
9429
+ (value) => !EDITABLE_TYPES.includes(typeof value)
9430
+ );
9431
+ }
9432
9432
  const widgetModule = { widgets: [] };
9433
9433
  const routeModule = {
9434
9434
  routes: [
@@ -9465,14 +9465,6 @@ const routeModule = {
9465
9465
  Component: CustomItems,
9466
9466
  path: "/draft-orders/:id/custom-items"
9467
9467
  },
9468
- {
9469
- Component: Metadata,
9470
- path: "/draft-orders/:id/metadata"
9471
- },
9472
- {
9473
- Component: Promotions,
9474
- path: "/draft-orders/:id/promotions"
9475
- },
9476
9468
  {
9477
9469
  Component: SalesChannel,
9478
9470
  path: "/draft-orders/:id/sales-channel"
@@ -9488,6 +9480,14 @@ const routeModule = {
9488
9480
  {
9489
9481
  Component: TransferOwnership,
9490
9482
  path: "/draft-orders/:id/transfer-ownership"
9483
+ },
9484
+ {
9485
+ Component: Promotions,
9486
+ path: "/draft-orders/:id/promotions"
9487
+ },
9488
+ {
9489
+ Component: Metadata,
9490
+ path: "/draft-orders/:id/metadata"
9491
9491
  }
9492
9492
  ]
9493
9493
  }
@@ -9512,6 +9512,7 @@ const displayModule = {
9512
9512
  const i18nModule = { resources: {} };
9513
9513
  const cellRendererModule = {};
9514
9514
  const layoutModule = { layouts: [] };
9515
+ const searchEntityModule = {};
9515
9516
  const plugin = {
9516
9517
  widgetModule,
9517
9518
  routeModule,
@@ -9520,6 +9521,7 @@ const plugin = {
9520
9521
  displayModule,
9521
9522
  i18nModule,
9522
9523
  cellRendererModule,
9523
- layoutModule
9524
+ layoutModule,
9525
+ searchEntityModule
9524
9526
  };
9525
9527
  module.exports = plugin;