@medusajs/draft-order 2.21.1 → 2.21.2-preview-20260925133948

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