@medusajs/draft-order 2.10.1-snapshot-20250828200335 → 2.10.1-snapshot-20250828204656

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.
@@ -9560,95 +9560,6 @@ const ID = () => {
9560
9560
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Outlet, {})
9561
9561
  ] });
9562
9562
  };
9563
- const Email = () => {
9564
- const { id } = reactRouterDom.useParams();
9565
- const { order, isPending, isError, error } = useOrder(id, {
9566
- fields: "+email"
9567
- });
9568
- if (isError) {
9569
- throw error;
9570
- }
9571
- const isReady = !isPending && !!order;
9572
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9573
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
9574
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Email" }) }),
9575
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
9576
- ] }),
9577
- isReady && /* @__PURE__ */ jsxRuntime.jsx(EmailForm, { order })
9578
- ] });
9579
- };
9580
- const EmailForm = ({ order }) => {
9581
- const form = reactHookForm.useForm({
9582
- defaultValues: {
9583
- email: order.email ?? ""
9584
- },
9585
- resolver: zod.zodResolver(schema$5)
9586
- });
9587
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9588
- const { handleSuccess } = useRouteModal();
9589
- const onSubmit = form.handleSubmit(async (data) => {
9590
- await mutateAsync(
9591
- { email: data.email },
9592
- {
9593
- onSuccess: () => {
9594
- handleSuccess();
9595
- },
9596
- onError: (error) => {
9597
- ui.toast.error(error.message);
9598
- }
9599
- }
9600
- );
9601
- });
9602
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
9603
- KeyboundForm,
9604
- {
9605
- className: "flex flex-1 flex-col overflow-hidden",
9606
- onSubmit,
9607
- children: [
9608
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
9609
- Form$2.Field,
9610
- {
9611
- control: form.control,
9612
- name: "email",
9613
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
9614
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Email" }),
9615
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
9616
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
9617
- ] })
9618
- }
9619
- ) }),
9620
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9621
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9622
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9623
- ] }) })
9624
- ]
9625
- }
9626
- ) });
9627
- };
9628
- const schema$5 = objectType({
9629
- email: stringType().email()
9630
- });
9631
- const CustomItems = () => {
9632
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9633
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Custom Items" }) }) }),
9634
- /* @__PURE__ */ jsxRuntime.jsx(CustomItemsForm, {})
9635
- ] });
9636
- };
9637
- const CustomItemsForm = () => {
9638
- const form = reactHookForm.useForm({
9639
- resolver: zod.zodResolver(schema$4)
9640
- });
9641
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9642
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, {}),
9643
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9644
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9645
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", children: "Save" })
9646
- ] }) })
9647
- ] }) });
9648
- };
9649
- const schema$4 = objectType({
9650
- email: stringType().email()
9651
- });
9652
9563
  const BillingAddress = () => {
9653
9564
  const { id } = reactRouterDom.useParams();
9654
9565
  const { order, isPending, isError, error } = useOrder(id, {
@@ -9681,7 +9592,7 @@ const BillingAddressForm = ({ order }) => {
9681
9592
  postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
9682
9593
  phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
9683
9594
  },
9684
- resolver: zod.zodResolver(schema$3)
9595
+ resolver: zod.zodResolver(schema$5)
9685
9596
  });
9686
9597
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9687
9598
  const { handleSuccess } = useRouteModal();
@@ -9838,55 +9749,32 @@ const BillingAddressForm = ({ order }) => {
9838
9749
  }
9839
9750
  ) });
9840
9751
  };
9841
- const schema$3 = addressSchema;
9842
- const InlineTip = React.forwardRef(
9843
- ({ variant = "tip", label, className, children, ...props }, ref) => {
9844
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
9845
- return /* @__PURE__ */ jsxRuntime.jsxs(
9846
- "div",
9847
- {
9848
- ref,
9849
- className: ui.clx(
9850
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
9851
- className
9852
- ),
9853
- ...props,
9854
- children: [
9855
- /* @__PURE__ */ jsxRuntime.jsx(
9856
- "div",
9857
- {
9858
- role: "presentation",
9859
- className: ui.clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
9860
- "bg-ui-tag-orange-icon": variant === "warning"
9861
- })
9862
- }
9863
- ),
9864
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-pretty", children: [
9865
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
9866
- labelValue,
9867
- ":"
9868
- ] }),
9869
- " ",
9870
- children
9871
- ] })
9872
- ]
9873
- }
9874
- );
9875
- }
9876
- );
9877
- InlineTip.displayName = "InlineTip";
9878
- const MetadataFieldSchema = objectType({
9879
- key: stringType(),
9880
- disabled: booleanType().optional(),
9881
- value: anyType()
9882
- });
9883
- const MetadataSchema = objectType({
9884
- metadata: arrayType(MetadataFieldSchema)
9752
+ const schema$5 = addressSchema;
9753
+ const CustomItems = () => {
9754
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9755
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Custom Items" }) }) }),
9756
+ /* @__PURE__ */ jsxRuntime.jsx(CustomItemsForm, {})
9757
+ ] });
9758
+ };
9759
+ const CustomItemsForm = () => {
9760
+ const form = reactHookForm.useForm({
9761
+ resolver: zod.zodResolver(schema$4)
9762
+ });
9763
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9764
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, {}),
9765
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9766
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9767
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", children: "Save" })
9768
+ ] }) })
9769
+ ] }) });
9770
+ };
9771
+ const schema$4 = objectType({
9772
+ email: stringType().email()
9885
9773
  });
9886
- const Metadata = () => {
9774
+ const Email = () => {
9887
9775
  const { id } = reactRouterDom.useParams();
9888
9776
  const { order, isPending, isError, error } = useOrder(id, {
9889
- fields: "metadata"
9777
+ fields: "+email"
9890
9778
  });
9891
9779
  if (isError) {
9892
9780
  throw error;
@@ -9894,33 +9782,26 @@ const Metadata = () => {
9894
9782
  const isReady = !isPending && !!order;
9895
9783
  return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9896
9784
  /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
9897
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Metadata" }) }),
9898
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
9785
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Email" }) }),
9786
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
9899
9787
  ] }),
9900
- !isReady ? /* @__PURE__ */ jsxRuntime.jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
9788
+ isReady && /* @__PURE__ */ jsxRuntime.jsx(EmailForm, { order })
9901
9789
  ] });
9902
9790
  };
9903
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
9904
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
9905
- const MetadataForm = ({ orderId, metadata }) => {
9906
- const { handleSuccess } = useRouteModal();
9907
- const hasUneditableRows = getHasUneditableRows(metadata);
9908
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
9791
+ const EmailForm = ({ order }) => {
9909
9792
  const form = reactHookForm.useForm({
9910
9793
  defaultValues: {
9911
- metadata: getDefaultValues(metadata)
9794
+ email: order.email ?? ""
9912
9795
  },
9913
- resolver: zod.zodResolver(MetadataSchema)
9796
+ resolver: zod.zodResolver(schema$3)
9914
9797
  });
9915
- const handleSubmit = form.handleSubmit(async (data) => {
9916
- const parsedData = parseValues(data);
9798
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9799
+ const { handleSuccess } = useRouteModal();
9800
+ const onSubmit = form.handleSubmit(async (data) => {
9917
9801
  await mutateAsync(
9918
- {
9919
- metadata: parsedData
9920
- },
9802
+ { email: data.email },
9921
9803
  {
9922
9804
  onSuccess: () => {
9923
- ui.toast.success("Metadata updated");
9924
9805
  handleSuccess();
9925
9806
  },
9926
9807
  onError: (error) => {
@@ -9929,282 +9810,156 @@ const MetadataForm = ({ orderId, metadata }) => {
9929
9810
  }
9930
9811
  );
9931
9812
  });
9932
- const { fields, insert, remove } = reactHookForm.useFieldArray({
9933
- control: form.control,
9934
- name: "metadata"
9935
- });
9936
- function deleteRow(index) {
9937
- remove(index);
9938
- if (fields.length === 1) {
9939
- insert(0, {
9940
- key: "",
9941
- value: "",
9942
- disabled: false
9943
- });
9944
- }
9945
- }
9946
- function insertRow(index, position) {
9947
- insert(index + (position === "above" ? 0 : 1), {
9948
- key: "",
9949
- value: "",
9950
- disabled: false
9951
- });
9952
- }
9953
9813
  return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
9954
9814
  KeyboundForm,
9955
9815
  {
9956
- onSubmit: handleSubmit,
9957
9816
  className: "flex flex-1 flex-col overflow-hidden",
9817
+ onSubmit,
9958
9818
  children: [
9959
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
9960
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
9961
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
9962
- /* @__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" }) }),
9963
- /* @__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" }) })
9964
- ] }),
9965
- fields.map((field, index) => {
9966
- const isDisabled = field.disabled || false;
9967
- let placeholder = "-";
9968
- if (typeof field.value === "object") {
9969
- placeholder = "{ ... }";
9970
- }
9971
- if (Array.isArray(field.value)) {
9972
- placeholder = "[ ... ]";
9973
- }
9974
- return /* @__PURE__ */ jsxRuntime.jsx(
9975
- ConditionalTooltip,
9976
- {
9977
- showTooltip: isDisabled,
9978
- content: "This row is disabled because it contains non-primitive data.",
9979
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/table relative", children: [
9980
- /* @__PURE__ */ jsxRuntime.jsxs(
9981
- "div",
9982
- {
9983
- className: ui.clx("grid grid-cols-2 divide-x", {
9984
- "overflow-hidden rounded-b-lg": index === fields.length - 1
9985
- }),
9986
- children: [
9987
- /* @__PURE__ */ jsxRuntime.jsx(
9988
- Form$2.Field,
9989
- {
9990
- control: form.control,
9991
- name: `metadata.${index}.key`,
9992
- render: ({ field: field2 }) => {
9993
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
9994
- GridInput,
9995
- {
9996
- "aria-labelledby": METADATA_KEY_LABEL_ID,
9997
- ...field2,
9998
- disabled: isDisabled,
9999
- placeholder: "Key"
10000
- }
10001
- ) }) });
10002
- }
10003
- }
10004
- ),
10005
- /* @__PURE__ */ jsxRuntime.jsx(
10006
- Form$2.Field,
10007
- {
10008
- control: form.control,
10009
- name: `metadata.${index}.value`,
10010
- render: ({ field: { value, ...field2 } }) => {
10011
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10012
- GridInput,
10013
- {
10014
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10015
- ...field2,
10016
- value: isDisabled ? placeholder : value,
10017
- disabled: isDisabled,
10018
- placeholder: "Value"
10019
- }
10020
- ) }) });
10021
- }
10022
- }
10023
- )
10024
- ]
10025
- }
10026
- ),
10027
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
10028
- /* @__PURE__ */ jsxRuntime.jsx(
10029
- ui.DropdownMenu.Trigger,
10030
- {
10031
- className: ui.clx(
10032
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10033
- {
10034
- hidden: isDisabled
10035
- }
10036
- ),
10037
- disabled: isDisabled,
10038
- asChild: true,
10039
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisVertical, {}) })
10040
- }
10041
- ),
10042
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
10043
- /* @__PURE__ */ jsxRuntime.jsxs(
10044
- ui.DropdownMenu.Item,
10045
- {
10046
- className: "gap-x-2",
10047
- onClick: () => insertRow(index, "above"),
10048
- children: [
10049
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpMini, { className: "text-ui-fg-subtle" }),
10050
- "Insert row above"
10051
- ]
10052
- }
10053
- ),
10054
- /* @__PURE__ */ jsxRuntime.jsxs(
10055
- ui.DropdownMenu.Item,
10056
- {
10057
- className: "gap-x-2",
10058
- onClick: () => insertRow(index, "below"),
10059
- children: [
10060
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownMini, { className: "text-ui-fg-subtle" }),
10061
- "Insert row below"
10062
- ]
10063
- }
10064
- ),
10065
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
10066
- /* @__PURE__ */ jsxRuntime.jsxs(
10067
- ui.DropdownMenu.Item,
10068
- {
10069
- className: "gap-x-2",
10070
- onClick: () => deleteRow(index),
10071
- children: [
10072
- /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
10073
- "Delete row"
10074
- ]
10075
- }
10076
- )
10077
- ] })
10078
- ] })
10079
- ] })
10080
- },
10081
- field.id
10082
- );
10083
- })
10084
- ] }),
10085
- 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." })
10086
- ] }),
10087
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10088
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
9819
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
9820
+ Form$2.Field,
9821
+ {
9822
+ control: form.control,
9823
+ name: "email",
9824
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
9825
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Email" }),
9826
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
9827
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
9828
+ ] })
9829
+ }
9830
+ ) }),
9831
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9832
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10089
9833
  /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10090
9834
  ] }) })
10091
9835
  ]
10092
9836
  }
10093
9837
  ) });
10094
9838
  };
10095
- const GridInput = React.forwardRef(({ className, ...props }, ref) => {
10096
- return /* @__PURE__ */ jsxRuntime.jsx(
10097
- "input",
10098
- {
10099
- ref,
10100
- ...props,
10101
- autoComplete: "off",
10102
- className: ui.clx(
10103
- "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",
10104
- className
10105
- )
10106
- }
10107
- );
9839
+ const schema$3 = objectType({
9840
+ email: stringType().email()
10108
9841
  });
10109
- GridInput.displayName = "MetadataForm.GridInput";
10110
- const PlaceholderInner = () => {
10111
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10112
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10113
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10114
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" }),
10115
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" })
10116
- ] }) })
10117
- ] });
10118
- };
10119
- const EDITABLE_TYPES = ["string", "number", "boolean"];
10120
- function getDefaultValues(metadata) {
10121
- if (!metadata || !Object.keys(metadata).length) {
10122
- return [
10123
- {
10124
- key: "",
10125
- value: "",
10126
- disabled: false
9842
+ const NumberInput = React.forwardRef(
9843
+ ({
9844
+ value,
9845
+ onChange,
9846
+ size = "base",
9847
+ min = 0,
9848
+ max = 100,
9849
+ step = 1,
9850
+ className,
9851
+ disabled,
9852
+ ...props
9853
+ }, ref) => {
9854
+ const handleChange = (event) => {
9855
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
9856
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9857
+ onChange(newValue);
10127
9858
  }
10128
- ];
10129
- }
10130
- return Object.entries(metadata).map(([key, value]) => {
10131
- if (!EDITABLE_TYPES.includes(typeof value)) {
10132
- return {
10133
- key,
10134
- value,
10135
- disabled: true
10136
- };
10137
- }
10138
- let stringValue = value;
10139
- if (typeof value !== "string") {
10140
- stringValue = JSON.stringify(value);
10141
- }
10142
- return {
10143
- key,
10144
- value: stringValue,
10145
- original_key: key
10146
9859
  };
10147
- });
10148
- }
10149
- function parseValues(values) {
10150
- const metadata = values.metadata;
10151
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10152
- if (isEmpty) {
10153
- return null;
10154
- }
10155
- const update = {};
10156
- metadata.forEach((field) => {
10157
- let key = field.key;
10158
- let value = field.value;
10159
- const disabled = field.disabled;
10160
- if (!key || !value) {
10161
- return;
10162
- }
10163
- if (disabled) {
10164
- update[key] = value;
10165
- return;
10166
- }
10167
- key = key.trim();
10168
- value = value.trim();
10169
- if (value === "true") {
10170
- update[key] = true;
10171
- } else if (value === "false") {
10172
- update[key] = false;
10173
- } else {
10174
- const parsedNumber = parseFloat(value);
10175
- if (!isNaN(parsedNumber)) {
10176
- update[key] = parsedNumber;
10177
- } else {
10178
- update[key] = value;
9860
+ const handleIncrement = () => {
9861
+ const newValue = value + step;
9862
+ if (max === void 0 || newValue <= max) {
9863
+ onChange(newValue);
10179
9864
  }
10180
- }
10181
- });
10182
- return update;
10183
- }
10184
- function getHasUneditableRows(metadata) {
10185
- if (!metadata) {
10186
- return false;
9865
+ };
9866
+ const handleDecrement = () => {
9867
+ const newValue = value - step;
9868
+ if (min === void 0 || newValue >= min) {
9869
+ onChange(newValue);
9870
+ }
9871
+ };
9872
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9873
+ "div",
9874
+ {
9875
+ className: ui.clx(
9876
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9877
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9878
+ {
9879
+ "h-7": size === "small",
9880
+ "h-8": size === "base"
9881
+ },
9882
+ className
9883
+ ),
9884
+ children: [
9885
+ /* @__PURE__ */ jsxRuntime.jsx(
9886
+ "input",
9887
+ {
9888
+ ref,
9889
+ type: "number",
9890
+ value,
9891
+ onChange: handleChange,
9892
+ min,
9893
+ max,
9894
+ step,
9895
+ className: ui.clx(
9896
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9897
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9898
+ "placeholder:text-ui-fg-muted"
9899
+ ),
9900
+ ...props
9901
+ }
9902
+ ),
9903
+ /* @__PURE__ */ jsxRuntime.jsxs(
9904
+ "button",
9905
+ {
9906
+ className: ui.clx(
9907
+ "flex items-center justify-center outline-none transition-fg",
9908
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9909
+ "focus:bg-ui-bg-field-component-hover",
9910
+ "hover:bg-ui-bg-field-component-hover",
9911
+ {
9912
+ "size-7": size === "small",
9913
+ "size-8": size === "base"
9914
+ }
9915
+ ),
9916
+ type: "button",
9917
+ onClick: handleDecrement,
9918
+ disabled: min !== void 0 && value <= min || disabled,
9919
+ children: [
9920
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Minus, {}),
9921
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9922
+ ]
9923
+ }
9924
+ ),
9925
+ /* @__PURE__ */ jsxRuntime.jsxs(
9926
+ "button",
9927
+ {
9928
+ className: ui.clx(
9929
+ "flex items-center justify-center outline-none transition-fg",
9930
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9931
+ "focus:bg-ui-bg-field-hover",
9932
+ "hover:bg-ui-bg-field-hover",
9933
+ {
9934
+ "size-7": size === "small",
9935
+ "size-8": size === "base"
9936
+ }
9937
+ ),
9938
+ type: "button",
9939
+ onClick: handleIncrement,
9940
+ disabled: max !== void 0 && value >= max || disabled,
9941
+ children: [
9942
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
9943
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9944
+ ]
9945
+ }
9946
+ )
9947
+ ]
9948
+ }
9949
+ );
10187
9950
  }
10188
- return Object.values(metadata).some(
10189
- (value) => !EDITABLE_TYPES.includes(typeof value)
10190
- );
10191
- }
10192
- const PROMOTION_QUERY_KEY = "promotions";
10193
- const promotionsQueryKeys = {
9951
+ );
9952
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9953
+ const productVariantsQueryKeys = {
10194
9954
  list: (query2) => [
10195
- PROMOTION_QUERY_KEY,
10196
- query2 ? query2 : void 0
10197
- ],
10198
- detail: (id, query2) => [
10199
- PROMOTION_QUERY_KEY,
10200
- id,
9955
+ PRODUCT_VARIANTS_QUERY_KEY,
10201
9956
  query2 ? query2 : void 0
10202
9957
  ]
10203
9958
  };
10204
- const usePromotions = (query2, options) => {
9959
+ const useProductVariants = (query2, options) => {
10205
9960
  const { data, ...rest } = reactQuery.useQuery({
10206
- queryKey: promotionsQueryKeys.list(query2),
10207
- queryFn: async () => sdk.admin.promotion.list(query2),
9961
+ queryKey: productVariantsQueryKeys.list(query2),
9962
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
10208
9963
  ...options
10209
9964
  });
10210
9965
  return { ...data, ...rest };
@@ -10242,566 +9997,921 @@ const useInitiateOrderEdit = ({
10242
9997
  if (preview.order_change) {
10243
9998
  return;
10244
9999
  }
10245
- IS_REQUEST_RUNNING = true;
10246
- await mutateAsync(void 0, {
10247
- onError: (e) => {
10248
- ui.toast.error(e.message);
10249
- navigate(`/draft-orders/${preview.id}`, { replace: true });
10250
- return;
10000
+ IS_REQUEST_RUNNING = true;
10001
+ await mutateAsync(void 0, {
10002
+ onError: (e) => {
10003
+ ui.toast.error(e.message);
10004
+ navigate(`/draft-orders/${preview.id}`, { replace: true });
10005
+ return;
10006
+ }
10007
+ });
10008
+ IS_REQUEST_RUNNING = false;
10009
+ }
10010
+ run();
10011
+ }, [preview, navigate, mutateAsync]);
10012
+ };
10013
+ function convertNumber(value) {
10014
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10015
+ }
10016
+ const STACKED_MODAL_ID = "items_stacked_modal";
10017
+ const Items = () => {
10018
+ const { id } = reactRouterDom.useParams();
10019
+ const {
10020
+ order: preview,
10021
+ isPending: isPreviewPending,
10022
+ isError: isPreviewError,
10023
+ error: previewError
10024
+ } = useOrderPreview(id, void 0, {
10025
+ placeholderData: reactQuery.keepPreviousData
10026
+ });
10027
+ useInitiateOrderEdit({ preview });
10028
+ const { draft_order, isPending, isError, error } = useDraftOrder(
10029
+ id,
10030
+ {
10031
+ fields: "currency_code"
10032
+ },
10033
+ {
10034
+ enabled: !!id
10035
+ }
10036
+ );
10037
+ const { onCancel } = useCancelOrderEdit({ preview });
10038
+ if (isError) {
10039
+ throw error;
10040
+ }
10041
+ if (isPreviewError) {
10042
+ throw previewError;
10043
+ }
10044
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10045
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsxRuntime.jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10046
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10047
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10048
+ ] }) });
10049
+ };
10050
+ const ItemsForm = ({ preview, currencyCode }) => {
10051
+ var _a;
10052
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
10053
+ const [modalContent, setModalContent] = React.useState(
10054
+ null
10055
+ );
10056
+ const { handleSuccess } = useRouteModal();
10057
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10058
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10059
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10060
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10061
+ const matches = React.useMemo(() => {
10062
+ return matchSorter.matchSorter(preview.items, query2, {
10063
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
10064
+ });
10065
+ }, [preview.items, query2]);
10066
+ const onSubmit = async () => {
10067
+ setIsSubmitting(true);
10068
+ let requestSucceeded = false;
10069
+ await requestOrderEdit(void 0, {
10070
+ onError: (e) => {
10071
+ ui.toast.error(`Failed to request order edit: ${e.message}`);
10072
+ },
10073
+ onSuccess: () => {
10074
+ requestSucceeded = true;
10075
+ }
10076
+ });
10077
+ if (!requestSucceeded) {
10078
+ setIsSubmitting(false);
10079
+ return;
10080
+ }
10081
+ await confirmOrderEdit(void 0, {
10082
+ onError: (e) => {
10083
+ ui.toast.error(`Failed to confirm order edit: ${e.message}`);
10084
+ },
10085
+ onSuccess: () => {
10086
+ handleSuccess();
10087
+ },
10088
+ onSettled: () => {
10089
+ setIsSubmitting(false);
10090
+ }
10091
+ });
10092
+ };
10093
+ const onKeyDown = React.useCallback(
10094
+ (e) => {
10095
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10096
+ if (modalContent || isSubmitting) {
10097
+ return;
10098
+ }
10099
+ onSubmit();
10100
+ }
10101
+ },
10102
+ [modalContent, isSubmitting, onSubmit]
10103
+ );
10104
+ React.useEffect(() => {
10105
+ document.addEventListener("keydown", onKeyDown);
10106
+ return () => {
10107
+ document.removeEventListener("keydown", onKeyDown);
10108
+ };
10109
+ }, [onKeyDown]);
10110
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10111
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
10112
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
10113
+ StackedFocusModal,
10114
+ {
10115
+ id: STACKED_MODAL_ID,
10116
+ onOpenChangeCallback: (open) => {
10117
+ if (!open) {
10118
+ setModalContent(null);
10119
+ }
10120
+ },
10121
+ children: [
10122
+ /* @__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: [
10123
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10124
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Items" }) }),
10125
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order." }) })
10126
+ ] }),
10127
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10128
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
10129
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10130
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10131
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10132
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10133
+ ] }),
10134
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
10135
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
10136
+ ui.Input,
10137
+ {
10138
+ type: "search",
10139
+ placeholder: "Search items",
10140
+ value: searchValue,
10141
+ onChange: (e) => onSearchValueChange(e.target.value)
10142
+ }
10143
+ ) }),
10144
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
10145
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}) }) }),
10146
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
10147
+ /* @__PURE__ */ jsxRuntime.jsx(
10148
+ StackedModalTrigger$1,
10149
+ {
10150
+ type: "add-items",
10151
+ setModalContent
10152
+ }
10153
+ ),
10154
+ /* @__PURE__ */ jsxRuntime.jsx(
10155
+ StackedModalTrigger$1,
10156
+ {
10157
+ type: "add-custom-item",
10158
+ setModalContent
10159
+ }
10160
+ )
10161
+ ] })
10162
+ ] })
10163
+ ] })
10164
+ ] }),
10165
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10166
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
10167
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Item" }) }),
10168
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10169
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Price" }) }),
10170
+ /* @__PURE__ */ jsxRuntime.jsx("div", {})
10171
+ ] }) }),
10172
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10173
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10174
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10175
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
10176
+ Item,
10177
+ {
10178
+ item,
10179
+ preview,
10180
+ currencyCode
10181
+ },
10182
+ item.id
10183
+ )) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10184
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10185
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
10186
+ 'No items found for "',
10187
+ query2,
10188
+ '".'
10189
+ ] })
10190
+ ] }) })
10191
+ ] })
10192
+ ] }),
10193
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10194
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10195
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10196
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(
10197
+ ui.Text,
10198
+ {
10199
+ size: "small",
10200
+ leading: "compact",
10201
+ className: "text-ui-fg-subtle",
10202
+ children: [
10203
+ itemCount,
10204
+ " ",
10205
+ itemCount === 1 ? "item" : "items"
10206
+ ]
10207
+ }
10208
+ ) }),
10209
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10210
+ ] })
10211
+ ] }) }),
10212
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsxRuntime.jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsxRuntime.jsx(
10213
+ CustomItemForm,
10214
+ {
10215
+ orderId: preview.id,
10216
+ currencyCode
10217
+ }
10218
+ ) : null)
10219
+ ]
10220
+ }
10221
+ ) }),
10222
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10223
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10224
+ /* @__PURE__ */ jsxRuntime.jsx(
10225
+ ui.Button,
10226
+ {
10227
+ size: "small",
10228
+ type: "button",
10229
+ onClick: onSubmit,
10230
+ isLoading: isSubmitting,
10231
+ children: "Save"
10251
10232
  }
10252
- });
10253
- IS_REQUEST_RUNNING = false;
10254
- }
10255
- run();
10256
- }, [preview, navigate, mutateAsync]);
10233
+ )
10234
+ ] }) })
10235
+ ] });
10257
10236
  };
10258
- const Promotions = () => {
10259
- const { id } = reactRouterDom.useParams();
10260
- const {
10261
- order: preview,
10262
- isError: isPreviewError,
10263
- error: previewError
10264
- } = useOrderPreview(id, void 0);
10265
- useInitiateOrderEdit({ preview });
10266
- const { onCancel } = useCancelOrderEdit({ preview });
10267
- if (isPreviewError) {
10268
- throw previewError;
10237
+ const Item = ({ item, preview, currencyCode }) => {
10238
+ if (item.variant_id) {
10239
+ return /* @__PURE__ */ jsxRuntime.jsx(VariantItem, { item, preview, currencyCode });
10269
10240
  }
10270
- const isReady = !!preview;
10271
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { onClose: onCancel, children: [
10272
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Promotions" }) }) }),
10273
- isReady && /* @__PURE__ */ jsxRuntime.jsx(PromotionForm, { preview })
10274
- ] });
10241
+ return /* @__PURE__ */ jsxRuntime.jsx(CustomItem, { item, preview, currencyCode });
10275
10242
  };
10276
- const PromotionForm = ({ preview }) => {
10277
- const { items, shipping_methods } = preview;
10278
- const [isSubmitting, setIsSubmitting] = React.useState(false);
10279
- const [comboboxValue, setComboboxValue] = React.useState("");
10280
- const { handleSuccess } = useRouteModal();
10281
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10282
- const promoCodes = getPromotionCodes(items, shipping_methods);
10283
- const { promotions, isPending, isError, error } = usePromotions(
10284
- {
10285
- code: promoCodes
10243
+ const VariantItem = ({ item, preview, currencyCode }) => {
10244
+ const [editing, setEditing] = React.useState(false);
10245
+ const form = reactHookForm.useForm({
10246
+ defaultValues: {
10247
+ quantity: item.quantity,
10248
+ unit_price: item.unit_price
10286
10249
  },
10287
- {
10288
- enabled: !!promoCodes.length
10250
+ resolver: zod.zodResolver(variantItemSchema)
10251
+ });
10252
+ const actionId = React.useMemo(() => {
10253
+ var _a, _b;
10254
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10255
+ }, [item]);
10256
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10257
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10258
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10259
+ const onSubmit = form.handleSubmit(async (data) => {
10260
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10261
+ setEditing(false);
10262
+ return;
10289
10263
  }
10290
- );
10291
- const comboboxData = useComboboxData({
10292
- queryKey: ["promotions", "combobox", promoCodes],
10293
- queryFn: async (params) => {
10294
- return await sdk.admin.promotion.list({
10295
- ...params,
10296
- code: {
10297
- $nin: promoCodes
10264
+ if (!actionId) {
10265
+ await updateOriginalItem(
10266
+ {
10267
+ item_id: item.id,
10268
+ quantity: data.quantity,
10269
+ unit_price: convertNumber(data.unit_price)
10270
+ },
10271
+ {
10272
+ onSuccess: () => {
10273
+ setEditing(false);
10274
+ },
10275
+ onError: (e) => {
10276
+ ui.toast.error(e.message);
10277
+ }
10298
10278
  }
10299
- });
10300
- },
10301
- getOptions: (data) => {
10302
- return data.promotions.map((promotion) => ({
10303
- label: promotion.code,
10304
- value: promotion.code
10305
- }));
10306
- }
10307
- });
10308
- const add = async (value) => {
10309
- if (!value) {
10279
+ );
10310
10280
  return;
10311
10281
  }
10312
- addPromotions(
10282
+ await updateActionItem(
10313
10283
  {
10314
- promo_codes: [value]
10284
+ action_id: actionId,
10285
+ quantity: data.quantity,
10286
+ unit_price: convertNumber(data.unit_price)
10315
10287
  },
10316
10288
  {
10289
+ onSuccess: () => {
10290
+ setEditing(false);
10291
+ },
10317
10292
  onError: (e) => {
10318
10293
  ui.toast.error(e.message);
10319
- comboboxData.onSearchValueChange("");
10320
- setComboboxValue("");
10321
- },
10322
- onSuccess: () => {
10323
- comboboxData.onSearchValueChange("");
10324
- setComboboxValue("");
10325
10294
  }
10326
10295
  }
10327
10296
  );
10328
- };
10329
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10330
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10331
- const onSubmit = async () => {
10332
- setIsSubmitting(true);
10333
- let requestSucceeded = false;
10334
- await requestOrderEdit(void 0, {
10335
- onError: (e) => {
10336
- ui.toast.error(e.message);
10337
- },
10338
- onSuccess: () => {
10339
- requestSucceeded = true;
10297
+ });
10298
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10299
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
10300
+ /* @__PURE__ */ jsxRuntime.jsx(
10301
+ Thumbnail,
10302
+ {
10303
+ thumbnail: item.thumbnail,
10304
+ alt: item.product_title ?? void 0
10305
+ }
10306
+ ),
10307
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10308
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
10309
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10310
+ /* @__PURE__ */ jsxRuntime.jsxs(
10311
+ ui.Text,
10312
+ {
10313
+ size: "small",
10314
+ leading: "compact",
10315
+ className: "text-ui-fg-subtle",
10316
+ children: [
10317
+ "(",
10318
+ item.variant_title,
10319
+ ")"
10320
+ ]
10321
+ }
10322
+ )
10323
+ ] }),
10324
+ /* @__PURE__ */ jsxRuntime.jsx(
10325
+ ui.Text,
10326
+ {
10327
+ size: "small",
10328
+ leading: "compact",
10329
+ className: "text-ui-fg-subtle",
10330
+ children: item.variant_sku
10331
+ }
10332
+ )
10333
+ ] })
10334
+ ] }),
10335
+ editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
10336
+ Form$2.Field,
10337
+ {
10338
+ control: form.control,
10339
+ name: "quantity",
10340
+ render: ({ field }) => {
10341
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
10342
+ }
10343
+ }
10344
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }) }),
10345
+ editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
10346
+ Form$2.Field,
10347
+ {
10348
+ control: form.control,
10349
+ name: "unit_price",
10350
+ render: ({ field: { onChange, ...field } }) => {
10351
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10352
+ ui.CurrencyInput,
10353
+ {
10354
+ ...field,
10355
+ symbol: getNativeSymbol(currencyCode),
10356
+ code: currencyCode,
10357
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10358
+ }
10359
+ ) }) });
10360
+ }
10361
+ }
10362
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10363
+ /* @__PURE__ */ jsxRuntime.jsx(
10364
+ ui.IconButton,
10365
+ {
10366
+ type: "button",
10367
+ size: "small",
10368
+ onClick: editing ? onSubmit : () => {
10369
+ setEditing(true);
10370
+ },
10371
+ disabled: isPending,
10372
+ children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
10340
10373
  }
10374
+ )
10375
+ ] }) }) });
10376
+ };
10377
+ const variantItemSchema = objectType({
10378
+ quantity: numberType(),
10379
+ unit_price: unionType([numberType(), stringType()])
10380
+ });
10381
+ const CustomItem = ({ item, preview, currencyCode }) => {
10382
+ const [editing, setEditing] = React.useState(false);
10383
+ const { quantity, unit_price, title } = item;
10384
+ const form = reactHookForm.useForm({
10385
+ defaultValues: {
10386
+ title,
10387
+ quantity,
10388
+ unit_price
10389
+ },
10390
+ resolver: zod.zodResolver(customItemSchema)
10391
+ });
10392
+ React.useEffect(() => {
10393
+ form.reset({
10394
+ title,
10395
+ quantity,
10396
+ unit_price
10341
10397
  });
10342
- if (!requestSucceeded) {
10343
- setIsSubmitting(false);
10398
+ }, [form, title, quantity, unit_price]);
10399
+ const actionId = React.useMemo(() => {
10400
+ var _a, _b;
10401
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10402
+ }, [item]);
10403
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10404
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10405
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10406
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10407
+ const onSubmit = form.handleSubmit(async (data) => {
10408
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10409
+ setEditing(false);
10344
10410
  return;
10345
10411
  }
10346
- await confirmOrderEdit(void 0, {
10347
- onError: (e) => {
10348
- ui.toast.error(e.message);
10349
- },
10350
- onSuccess: () => {
10351
- handleSuccess();
10352
- },
10353
- onSettled: () => {
10354
- setIsSubmitting(false);
10355
- }
10356
- });
10357
- };
10358
- if (isError) {
10359
- throw error;
10360
- }
10361
- return /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10362
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
10363
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
10364
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10365
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10366
- /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10367
- ] }),
10368
- /* @__PURE__ */ jsxRuntime.jsx(
10369
- Combobox,
10370
- {
10371
- id: "promotion-combobox",
10372
- "aria-describedby": "promotion-combobox-hint",
10373
- isFetchingNextPage: comboboxData.isFetchingNextPage,
10374
- fetchNextPage: comboboxData.fetchNextPage,
10375
- options: comboboxData.options,
10376
- onSearchValueChange: comboboxData.onSearchValueChange,
10377
- searchValue: comboboxData.searchValue,
10378
- disabled: comboboxData.disabled || isAddingPromotions,
10379
- onChange: add,
10380
- value: comboboxValue
10381
- }
10382
- )
10383
- ] }),
10384
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10385
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsxRuntime.jsx(
10386
- PromotionItem,
10412
+ if (!actionId) {
10413
+ await updateOriginalItem(
10387
10414
  {
10388
- promotion,
10389
- orderId: preview.id,
10390
- isLoading: isPending
10415
+ item_id: item.id,
10416
+ quantity: data.quantity,
10417
+ unit_price: convertNumber(data.unit_price)
10391
10418
  },
10392
- promotion.id
10393
- )) })
10394
- ] }) }),
10395
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
10396
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10397
- /* @__PURE__ */ jsxRuntime.jsx(
10398
- ui.Button,
10399
10419
  {
10400
- size: "small",
10401
- type: "submit",
10402
- isLoading: isSubmitting || isAddingPromotions,
10403
- children: "Save"
10420
+ onSuccess: () => {
10421
+ setEditing(false);
10422
+ },
10423
+ onError: (e) => {
10424
+ ui.toast.error(e.message);
10425
+ }
10404
10426
  }
10405
- )
10406
- ] }) })
10407
- ] });
10408
- };
10409
- const PromotionItem = ({
10410
- promotion,
10411
- orderId,
10412
- isLoading
10413
- }) => {
10414
- var _a;
10415
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10416
- const onRemove = async () => {
10417
- removePromotions(
10427
+ );
10428
+ return;
10429
+ }
10430
+ if (data.quantity === 0) {
10431
+ await removeActionItem(actionId, {
10432
+ onSuccess: () => {
10433
+ setEditing(false);
10434
+ },
10435
+ onError: (e) => {
10436
+ ui.toast.error(e.message);
10437
+ }
10438
+ });
10439
+ return;
10440
+ }
10441
+ await updateActionItem(
10418
10442
  {
10419
- promo_codes: [promotion.code]
10443
+ action_id: actionId,
10444
+ quantity: data.quantity,
10445
+ unit_price: convertNumber(data.unit_price)
10420
10446
  },
10421
10447
  {
10448
+ onSuccess: () => {
10449
+ setEditing(false);
10450
+ },
10422
10451
  onError: (e) => {
10423
10452
  ui.toast.error(e.message);
10424
10453
  }
10425
10454
  }
10426
10455
  );
10427
- };
10428
- const displayValue = getDisplayValue(promotion);
10429
- return /* @__PURE__ */ jsxRuntime.jsxs(
10430
- "div",
10431
- {
10432
- className: ui.clx(
10433
- "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
10456
+ });
10457
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10458
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
10459
+ /* @__PURE__ */ jsxRuntime.jsx(
10460
+ Thumbnail,
10434
10461
  {
10435
- "animate-pulse": isLoading
10462
+ thumbnail: item.thumbnail,
10463
+ alt: item.title ?? void 0
10436
10464
  }
10437
10465
  ),
10438
- children: [
10439
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10440
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10441
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
10442
- displayValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
10443
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: displayValue }),
10444
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: "·" })
10445
- ] }),
10446
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10447
- ] })
10448
- ] }),
10449
- /* @__PURE__ */ jsxRuntime.jsx(
10450
- ui.IconButton,
10451
- {
10452
- size: "small",
10453
- type: "button",
10454
- variant: "transparent",
10455
- onClick: onRemove,
10456
- isLoading: isPending || isLoading,
10457
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.XMark, {})
10466
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
10467
+ Form$2.Field,
10468
+ {
10469
+ control: form.control,
10470
+ name: "title",
10471
+ render: ({ field }) => {
10472
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }) });
10458
10473
  }
10459
- )
10460
- ]
10461
- },
10462
- promotion.id
10463
- );
10464
- };
10465
- function getDisplayValue(promotion) {
10466
- var _a, _b, _c, _d;
10467
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10468
- if (!value) {
10469
- return null;
10470
- }
10471
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10472
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10473
- if (!currency) {
10474
- return null;
10475
- }
10476
- return getLocaleAmount(value, currency);
10477
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10478
- return formatPercentage(value);
10479
- }
10480
- return null;
10481
- }
10482
- const formatter = new Intl.NumberFormat([], {
10483
- style: "percent",
10484
- minimumFractionDigits: 2
10485
- });
10486
- const formatPercentage = (value, isPercentageValue = false) => {
10487
- let val = value || 0;
10488
- if (!isPercentageValue) {
10489
- val = val / 100;
10490
- }
10491
- return formatter.format(val);
10492
- };
10493
- function getPromotionCodes(items, shippingMethods) {
10494
- const codes = /* @__PURE__ */ new Set();
10495
- for (const item of items) {
10496
- if (item.adjustments) {
10497
- for (const adjustment of item.adjustments) {
10498
- if (adjustment.code) {
10499
- codes.add(adjustment.code);
10474
+ }
10475
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.title })
10476
+ ] }),
10477
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
10478
+ Form$2.Field,
10479
+ {
10480
+ control: form.control,
10481
+ name: "quantity",
10482
+ render: ({ field }) => {
10483
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
10500
10484
  }
10501
10485
  }
10502
- }
10503
- }
10504
- for (const shippingMethod of shippingMethods) {
10505
- if (shippingMethod.adjustments) {
10506
- for (const adjustment of shippingMethod.adjustments) {
10507
- if (adjustment.code) {
10508
- codes.add(adjustment.code);
10486
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }),
10487
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
10488
+ Form$2.Field,
10489
+ {
10490
+ control: form.control,
10491
+ name: "unit_price",
10492
+ render: ({ field: { onChange, ...field } }) => {
10493
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10494
+ ui.CurrencyInput,
10495
+ {
10496
+ ...field,
10497
+ symbol: getNativeSymbol(currencyCode),
10498
+ code: currencyCode,
10499
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10500
+ }
10501
+ ) }) });
10502
+ }
10503
+ }
10504
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10505
+ /* @__PURE__ */ jsxRuntime.jsx(
10506
+ ui.IconButton,
10507
+ {
10508
+ type: "button",
10509
+ size: "small",
10510
+ onClick: editing ? onSubmit : () => {
10511
+ setEditing(true);
10512
+ },
10513
+ disabled: isPending,
10514
+ children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
10515
+ }
10516
+ )
10517
+ ] }) }) });
10518
+ };
10519
+ const StackedModalTrigger$1 = ({
10520
+ type,
10521
+ setModalContent
10522
+ }) => {
10523
+ const { setIsOpen } = useStackedModal();
10524
+ const onClick = React.useCallback(() => {
10525
+ setModalContent(type);
10526
+ setIsOpen(STACKED_MODAL_ID, true);
10527
+ }, [setModalContent, setIsOpen, type]);
10528
+ return /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10529
+ };
10530
+ const VARIANT_PREFIX = "items";
10531
+ const LIMIT = 50;
10532
+ const ExistingItemsForm = ({ orderId, items }) => {
10533
+ const { setIsOpen } = useStackedModal();
10534
+ const [rowSelection, setRowSelection] = React.useState(
10535
+ items.reduce((acc, item) => {
10536
+ acc[item.variant_id] = true;
10537
+ return acc;
10538
+ }, {})
10539
+ );
10540
+ React.useEffect(() => {
10541
+ setRowSelection(
10542
+ items.reduce((acc, item) => {
10543
+ if (item.variant_id) {
10544
+ acc[item.variant_id] = true;
10509
10545
  }
10510
- }
10511
- }
10512
- }
10513
- return Array.from(codes);
10514
- }
10515
- const SalesChannel = () => {
10516
- const { id } = reactRouterDom.useParams();
10517
- const { draft_order, isPending, isError, error } = useDraftOrder(
10518
- id,
10546
+ return acc;
10547
+ }, {})
10548
+ );
10549
+ }, [items]);
10550
+ const { q, order, offset } = useQueryParams(
10551
+ ["q", "order", "offset"],
10552
+ VARIANT_PREFIX
10553
+ );
10554
+ const { variants, count, isPending, isError, error } = useProductVariants(
10519
10555
  {
10520
- fields: "+sales_channel_id"
10556
+ q,
10557
+ order,
10558
+ offset: offset ? parseInt(offset) : void 0,
10559
+ limit: LIMIT
10521
10560
  },
10522
10561
  {
10523
- enabled: !!id
10562
+ placeholderData: reactQuery.keepPreviousData
10524
10563
  }
10525
10564
  );
10526
- if (isError) {
10527
- throw error;
10528
- }
10529
- const ISrEADY = !!draft_order && !isPending;
10530
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
10531
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
10532
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Sales Channel" }) }),
10533
- /* @__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" }) })
10534
- ] }),
10535
- ISrEADY && /* @__PURE__ */ jsxRuntime.jsx(SalesChannelForm, { order: draft_order })
10536
- ] });
10537
- };
10538
- const SalesChannelForm = ({ order }) => {
10539
- const form = reactHookForm.useForm({
10540
- defaultValues: {
10541
- sales_channel_id: order.sales_channel_id || ""
10542
- },
10543
- resolver: zod.zodResolver(schema$2)
10544
- });
10545
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10546
- const { handleSuccess } = useRouteModal();
10547
- const onSubmit = form.handleSubmit(async (data) => {
10565
+ const columns = useColumns();
10566
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10567
+ const onSubmit = async () => {
10568
+ const ids = Object.keys(rowSelection).filter(
10569
+ (id) => !items.find((i) => i.variant_id === id)
10570
+ );
10548
10571
  await mutateAsync(
10549
10572
  {
10550
- sales_channel_id: data.sales_channel_id
10573
+ items: ids.map((id) => ({
10574
+ variant_id: id,
10575
+ quantity: 1
10576
+ }))
10551
10577
  },
10552
10578
  {
10553
10579
  onSuccess: () => {
10554
- ui.toast.success("Sales channel updated");
10555
- handleSuccess();
10580
+ setRowSelection({});
10581
+ setIsOpen(STACKED_MODAL_ID, false);
10556
10582
  },
10557
- onError: (error) => {
10558
- ui.toast.error(error.message);
10583
+ onError: (e) => {
10584
+ ui.toast.error(e.message);
10559
10585
  }
10560
10586
  }
10561
10587
  );
10562
- });
10563
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
10564
- KeyboundForm,
10588
+ };
10589
+ if (isError) {
10590
+ throw error;
10591
+ }
10592
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10593
+ StackedFocusModal.Content,
10565
10594
  {
10566
- className: "flex flex-1 flex-col overflow-hidden",
10567
- onSubmit,
10595
+ onOpenAutoFocus: (e) => {
10596
+ e.preventDefault();
10597
+ const searchInput = document.querySelector(
10598
+ "[data-modal-id='modal-search-input']"
10599
+ );
10600
+ if (searchInput) {
10601
+ searchInput.focus();
10602
+ }
10603
+ },
10568
10604
  children: [
10569
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(SalesChannelField, { control: form.control, order }) }),
10570
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
10571
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10572
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10605
+ /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Header, { children: [
10606
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10607
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10608
+ ] }),
10609
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
10610
+ DataTable,
10611
+ {
10612
+ data: variants,
10613
+ columns,
10614
+ isLoading: isPending,
10615
+ getRowId: (row) => row.id,
10616
+ rowCount: count,
10617
+ prefix: VARIANT_PREFIX,
10618
+ layout: "fill",
10619
+ rowSelection: {
10620
+ state: rowSelection,
10621
+ onRowSelectionChange: setRowSelection,
10622
+ enableRowSelection: (row) => {
10623
+ return !items.find((i) => i.variant_id === row.original.id);
10624
+ }
10625
+ },
10626
+ autoFocusSearch: true
10627
+ }
10628
+ ) }),
10629
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10630
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10631
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10573
10632
  ] }) })
10574
10633
  ]
10575
10634
  }
10576
- ) });
10577
- };
10578
- const SalesChannelField = ({ control, order }) => {
10579
- const salesChannels = useComboboxData({
10580
- queryFn: async (params) => {
10581
- return await sdk.admin.salesChannel.list(params);
10582
- },
10583
- queryKey: ["sales-channels"],
10584
- getOptions: (data) => {
10585
- return data.sales_channels.map((salesChannel) => ({
10586
- label: salesChannel.name,
10587
- value: salesChannel.id
10588
- }));
10589
- },
10590
- defaultValue: order.sales_channel_id || void 0
10591
- });
10592
- return /* @__PURE__ */ jsxRuntime.jsx(
10593
- Form$2.Field,
10594
- {
10595
- control,
10596
- name: "sales_channel_id",
10597
- render: ({ field }) => {
10598
- return /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
10599
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Sales Channel" }),
10600
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10601
- Combobox,
10602
- {
10603
- options: salesChannels.options,
10604
- fetchNextPage: salesChannels.fetchNextPage,
10605
- isFetchingNextPage: salesChannels.isFetchingNextPage,
10606
- searchValue: salesChannels.searchValue,
10607
- onSearchValueChange: salesChannels.onSearchValueChange,
10608
- placeholder: "Select sales channel",
10609
- ...field
10610
- }
10611
- ) }),
10612
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
10613
- ] });
10614
- }
10615
- }
10616
10635
  );
10617
10636
  };
10618
- const schema$2 = objectType({
10619
- sales_channel_id: stringType().min(1)
10620
- });
10621
- const NumberInput = React.forwardRef(
10622
- ({
10623
- value,
10624
- onChange,
10625
- size = "base",
10626
- min = 0,
10627
- max = 100,
10628
- step = 1,
10629
- className,
10630
- disabled,
10631
- ...props
10632
- }, ref) => {
10633
- const handleChange = (event) => {
10634
- const newValue = event.target.value === "" ? min : Number(event.target.value);
10635
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
10636
- onChange(newValue);
10637
- }
10638
- };
10639
- const handleIncrement = () => {
10640
- const newValue = value + step;
10641
- if (max === void 0 || newValue <= max) {
10642
- onChange(newValue);
10643
- }
10644
- };
10645
- const handleDecrement = () => {
10646
- const newValue = value - step;
10647
- if (min === void 0 || newValue >= min) {
10648
- onChange(newValue);
10649
- }
10650
- };
10651
- return /* @__PURE__ */ jsxRuntime.jsxs(
10652
- "div",
10653
- {
10654
- className: ui.clx(
10655
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
10656
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
10657
- {
10658
- "h-7": size === "small",
10659
- "h-8": size === "base"
10660
- },
10661
- className
10662
- ),
10663
- children: [
10664
- /* @__PURE__ */ jsxRuntime.jsx(
10665
- "input",
10666
- {
10667
- ref,
10668
- type: "number",
10669
- value,
10670
- onChange: handleChange,
10671
- min,
10672
- max,
10673
- step,
10674
- className: ui.clx(
10675
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
10676
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
10677
- "placeholder:text-ui-fg-muted"
10678
- ),
10679
- ...props
10680
- }
10681
- ),
10682
- /* @__PURE__ */ jsxRuntime.jsxs(
10683
- "button",
10637
+ const columnHelper = ui.createDataTableColumnHelper();
10638
+ const useColumns = () => {
10639
+ return React.useMemo(() => {
10640
+ return [
10641
+ columnHelper.select(),
10642
+ columnHelper.accessor("product.title", {
10643
+ header: "Product",
10644
+ cell: ({ row }) => {
10645
+ var _a, _b, _c;
10646
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
10647
+ /* @__PURE__ */ jsxRuntime.jsx(
10648
+ Thumbnail,
10649
+ {
10650
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10651
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
10652
+ }
10653
+ ),
10654
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10655
+ ] });
10656
+ },
10657
+ enableSorting: true
10658
+ }),
10659
+ columnHelper.accessor("title", {
10660
+ header: "Variant",
10661
+ enableSorting: true
10662
+ }),
10663
+ columnHelper.accessor("sku", {
10664
+ header: "SKU",
10665
+ cell: ({ getValue }) => {
10666
+ return getValue() ?? "-";
10667
+ },
10668
+ enableSorting: true
10669
+ }),
10670
+ columnHelper.accessor("updated_at", {
10671
+ header: "Updated",
10672
+ cell: ({ getValue }) => {
10673
+ return /* @__PURE__ */ jsxRuntime.jsx(
10674
+ ui.Tooltip,
10684
10675
  {
10685
- className: ui.clx(
10686
- "flex items-center justify-center outline-none transition-fg",
10687
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10688
- "focus:bg-ui-bg-field-component-hover",
10689
- "hover:bg-ui-bg-field-component-hover",
10690
- {
10691
- "size-7": size === "small",
10692
- "size-8": size === "base"
10693
- }
10694
- ),
10695
- type: "button",
10696
- onClick: handleDecrement,
10697
- disabled: min !== void 0 && value <= min || disabled,
10698
- children: [
10699
- /* @__PURE__ */ jsxRuntime.jsx(icons.Minus, {}),
10700
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
10701
- ]
10676
+ content: getFullDate({ date: getValue(), includeTime: true }),
10677
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
10702
10678
  }
10703
- ),
10704
- /* @__PURE__ */ jsxRuntime.jsxs(
10705
- "button",
10679
+ );
10680
+ },
10681
+ enableSorting: true,
10682
+ sortAscLabel: "Oldest first",
10683
+ sortDescLabel: "Newest first"
10684
+ }),
10685
+ columnHelper.accessor("created_at", {
10686
+ header: "Created",
10687
+ cell: ({ getValue }) => {
10688
+ return /* @__PURE__ */ jsxRuntime.jsx(
10689
+ ui.Tooltip,
10706
10690
  {
10707
- className: ui.clx(
10708
- "flex items-center justify-center outline-none transition-fg",
10709
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10710
- "focus:bg-ui-bg-field-hover",
10711
- "hover:bg-ui-bg-field-hover",
10712
- {
10713
- "size-7": size === "small",
10714
- "size-8": size === "base"
10715
- }
10716
- ),
10717
- type: "button",
10718
- onClick: handleIncrement,
10719
- disabled: max !== void 0 && value >= max || disabled,
10720
- children: [
10721
- /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
10722
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Increase by ${step}` })
10723
- ]
10691
+ content: getFullDate({ date: getValue(), includeTime: true }),
10692
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
10724
10693
  }
10725
- )
10694
+ );
10695
+ },
10696
+ enableSorting: true,
10697
+ sortAscLabel: "Oldest first",
10698
+ sortDescLabel: "Newest first"
10699
+ })
10700
+ ];
10701
+ }, []);
10702
+ };
10703
+ const CustomItemForm = ({ orderId, currencyCode }) => {
10704
+ const { setIsOpen } = useStackedModal();
10705
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10706
+ const form = reactHookForm.useForm({
10707
+ defaultValues: {
10708
+ title: "",
10709
+ quantity: 1,
10710
+ unit_price: ""
10711
+ },
10712
+ resolver: zod.zodResolver(customItemSchema)
10713
+ });
10714
+ const onSubmit = form.handleSubmit(async (data) => {
10715
+ await addItems(
10716
+ {
10717
+ items: [
10718
+ {
10719
+ title: data.title,
10720
+ quantity: data.quantity,
10721
+ unit_price: convertNumber(data.unit_price)
10722
+ }
10726
10723
  ]
10724
+ },
10725
+ {
10726
+ onSuccess: () => {
10727
+ setIsOpen(STACKED_MODAL_ID, false);
10728
+ },
10729
+ onError: (e) => {
10730
+ ui.toast.error(e.message);
10731
+ }
10727
10732
  }
10728
10733
  );
10729
- }
10730
- );
10731
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
10732
- const productVariantsQueryKeys = {
10734
+ });
10735
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Content, { children: [
10736
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Header, {}),
10737
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.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-2 py-16", children: [
10738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10739
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Add custom item" }) }),
10740
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a custom item to the order. This will add a new line item that is not associated with an existing product." }) })
10741
+ ] }),
10742
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10743
+ /* @__PURE__ */ jsxRuntime.jsx(
10744
+ Form$2.Field,
10745
+ {
10746
+ control: form.control,
10747
+ name: "title",
10748
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10749
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10750
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Title" }),
10751
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the title of the item" })
10752
+ ] }),
10753
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10754
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
10755
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
10756
+ ] })
10757
+ ] }) })
10758
+ }
10759
+ ),
10760
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10761
+ /* @__PURE__ */ jsxRuntime.jsx(
10762
+ Form$2.Field,
10763
+ {
10764
+ control: form.control,
10765
+ name: "unit_price",
10766
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10767
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10768
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Unit price" }),
10769
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10770
+ ] }),
10771
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10772
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10773
+ ui.CurrencyInput,
10774
+ {
10775
+ symbol: getNativeSymbol(currencyCode),
10776
+ code: currencyCode,
10777
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10778
+ ...field
10779
+ }
10780
+ ) }),
10781
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
10782
+ ] })
10783
+ ] }) })
10784
+ }
10785
+ ),
10786
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10787
+ /* @__PURE__ */ jsxRuntime.jsx(
10788
+ Form$2.Field,
10789
+ {
10790
+ control: form.control,
10791
+ name: "quantity",
10792
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10793
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10794
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Quantity" }),
10795
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10796
+ ] }),
10797
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 w-full", children: [
10798
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10799
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
10800
+ ] })
10801
+ ] }) })
10802
+ }
10803
+ )
10804
+ ] }) }) }),
10805
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10806
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10807
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10808
+ ] }) })
10809
+ ] }) }) });
10810
+ };
10811
+ const customItemSchema = objectType({
10812
+ title: stringType().min(1),
10813
+ quantity: numberType(),
10814
+ unit_price: unionType([numberType(), stringType()])
10815
+ });
10816
+ const PROMOTION_QUERY_KEY = "promotions";
10817
+ const promotionsQueryKeys = {
10733
10818
  list: (query2) => [
10734
- PRODUCT_VARIANTS_QUERY_KEY,
10819
+ PROMOTION_QUERY_KEY,
10820
+ query2 ? query2 : void 0
10821
+ ],
10822
+ detail: (id, query2) => [
10823
+ PROMOTION_QUERY_KEY,
10824
+ id,
10735
10825
  query2 ? query2 : void 0
10736
10826
  ]
10737
10827
  };
10738
- const useProductVariants = (query2, options) => {
10828
+ const usePromotions = (query2, options) => {
10739
10829
  const { data, ...rest } = reactQuery.useQuery({
10740
- queryKey: productVariantsQueryKeys.list(query2),
10741
- queryFn: async () => await sdk.admin.productVariant.list(query2),
10830
+ queryKey: promotionsQueryKeys.list(query2),
10831
+ queryFn: async () => sdk.admin.promotion.list(query2),
10742
10832
  ...options
10743
10833
  });
10744
10834
  return { ...data, ...rest };
10745
10835
  };
10746
- function convertNumber(value) {
10747
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10748
- }
10749
- const STACKED_MODAL_ID = "items_stacked_modal";
10750
- const Items = () => {
10836
+ const Promotions = () => {
10751
10837
  const { id } = reactRouterDom.useParams();
10752
10838
  const {
10753
10839
  order: preview,
10754
- isPending: isPreviewPending,
10755
10840
  isError: isPreviewError,
10756
10841
  error: previewError
10757
- } = useOrderPreview(id, void 0, {
10758
- placeholderData: reactQuery.keepPreviousData
10759
- });
10842
+ } = useOrderPreview(id, void 0);
10760
10843
  useInitiateOrderEdit({ preview });
10761
- const { draft_order, isPending, isError, error } = useDraftOrder(
10762
- id,
10763
- {
10764
- fields: "currency_code"
10765
- },
10766
- {
10767
- enabled: !!id
10768
- }
10769
- );
10770
10844
  const { onCancel } = useCancelOrderEdit({ preview });
10771
- if (isError) {
10772
- throw error;
10773
- }
10774
10845
  if (isPreviewError) {
10775
10846
  throw previewError;
10776
10847
  }
10777
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10778
- return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsxRuntime.jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10779
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10780
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10781
- ] }) });
10848
+ const isReady = !!preview;
10849
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { onClose: onCancel, children: [
10850
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Promotions" }) }) }),
10851
+ isReady && /* @__PURE__ */ jsxRuntime.jsx(PromotionForm, { preview })
10852
+ ] });
10782
10853
  };
10783
- const ItemsForm = ({ preview, currencyCode }) => {
10784
- var _a;
10854
+ const PromotionForm = ({ preview }) => {
10855
+ const { items, shipping_methods } = preview;
10785
10856
  const [isSubmitting, setIsSubmitting] = React.useState(false);
10786
- const [modalContent, setModalContent] = React.useState(
10787
- null
10857
+ const [comboboxValue, setComboboxValue] = React.useState("");
10858
+ const { handleSuccess } = useRouteModal();
10859
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10860
+ const promoCodes = getPromotionCodes(items, shipping_methods);
10861
+ const { promotions, isPending, isError, error } = usePromotions(
10862
+ {
10863
+ code: promoCodes
10864
+ },
10865
+ {
10866
+ enabled: !!promoCodes.length
10867
+ }
10788
10868
  );
10789
- const { handleSuccess } = useRouteModal();
10790
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10869
+ const comboboxData = useComboboxData({
10870
+ queryKey: ["promotions", "combobox", promoCodes],
10871
+ queryFn: async (params) => {
10872
+ return await sdk.admin.promotion.list({
10873
+ ...params,
10874
+ code: {
10875
+ $nin: promoCodes
10876
+ }
10877
+ });
10878
+ },
10879
+ getOptions: (data) => {
10880
+ return data.promotions.map((promotion) => ({
10881
+ label: promotion.code,
10882
+ value: promotion.code
10883
+ }));
10884
+ }
10885
+ });
10886
+ const add = async (value) => {
10887
+ if (!value) {
10888
+ return;
10889
+ }
10890
+ addPromotions(
10891
+ {
10892
+ promo_codes: [value]
10893
+ },
10894
+ {
10895
+ onError: (e) => {
10896
+ ui.toast.error(e.message);
10897
+ comboboxData.onSearchValueChange("");
10898
+ setComboboxValue("");
10899
+ },
10900
+ onSuccess: () => {
10901
+ comboboxData.onSearchValueChange("");
10902
+ setComboboxValue("");
10903
+ }
10904
+ }
10905
+ );
10906
+ };
10791
10907
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10792
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10793
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10794
- const matches = React.useMemo(() => {
10795
- return matchSorter.matchSorter(preview.items, query2, {
10796
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10797
- });
10798
- }, [preview.items, query2]);
10908
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10799
10909
  const onSubmit = async () => {
10800
10910
  setIsSubmitting(true);
10801
10911
  let requestSucceeded = false;
10802
10912
  await requestOrderEdit(void 0, {
10803
10913
  onError: (e) => {
10804
- ui.toast.error(`Failed to request order edit: ${e.message}`);
10914
+ ui.toast.error(e.message);
10805
10915
  },
10806
10916
  onSuccess: () => {
10807
10917
  requestSucceeded = true;
@@ -10813,7 +10923,7 @@ const ItemsForm = ({ preview, currencyCode }) => {
10813
10923
  }
10814
10924
  await confirmOrderEdit(void 0, {
10815
10925
  onError: (e) => {
10816
- ui.toast.error(`Failed to confirm order edit: ${e.message}`);
10926
+ ui.toast.error(e.message);
10817
10927
  },
10818
10928
  onSuccess: () => {
10819
10929
  handleSuccess();
@@ -10823,729 +10933,619 @@ const ItemsForm = ({ preview, currencyCode }) => {
10823
10933
  }
10824
10934
  });
10825
10935
  };
10826
- const onKeyDown = React.useCallback(
10827
- (e) => {
10828
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10829
- if (modalContent || isSubmitting) {
10830
- return;
10831
- }
10832
- onSubmit();
10833
- }
10834
- },
10835
- [modalContent, isSubmitting, onSubmit]
10836
- );
10837
- React.useEffect(() => {
10838
- document.addEventListener("keydown", onKeyDown);
10839
- return () => {
10840
- document.removeEventListener("keydown", onKeyDown);
10841
- };
10842
- }, [onKeyDown]);
10843
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10844
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
10845
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
10846
- StackedFocusModal,
10847
- {
10848
- id: STACKED_MODAL_ID,
10849
- onOpenChangeCallback: (open) => {
10850
- if (!open) {
10851
- setModalContent(null);
10852
- }
10853
- },
10854
- children: [
10855
- /* @__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: [
10856
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10857
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Items" }) }),
10858
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order." }) })
10859
- ] }),
10860
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10861
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
10862
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10863
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10864
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10865
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10866
- ] }),
10867
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
10868
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
10869
- ui.Input,
10870
- {
10871
- type: "search",
10872
- placeholder: "Search items",
10873
- value: searchValue,
10874
- onChange: (e) => onSearchValueChange(e.target.value)
10875
- }
10876
- ) }),
10877
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
10878
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}) }) }),
10879
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
10880
- /* @__PURE__ */ jsxRuntime.jsx(
10881
- StackedModalTrigger$1,
10882
- {
10883
- type: "add-items",
10884
- setModalContent
10885
- }
10886
- ),
10887
- /* @__PURE__ */ jsxRuntime.jsx(
10888
- StackedModalTrigger$1,
10889
- {
10890
- type: "add-custom-item",
10891
- setModalContent
10892
- }
10893
- )
10894
- ] })
10895
- ] })
10896
- ] })
10897
- ] }),
10898
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10899
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
10900
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Item" }) }),
10901
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10902
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Price" }) }),
10903
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10904
- ] }) }),
10905
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10906
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10907
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10908
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
10909
- Item,
10910
- {
10911
- item,
10912
- preview,
10913
- currencyCode
10914
- },
10915
- item.id
10916
- )) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10917
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10918
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
10919
- 'No items found for "',
10920
- query2,
10921
- '".'
10922
- ] })
10923
- ] }) })
10924
- ] })
10925
- ] }),
10926
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10927
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10928
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10929
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(
10930
- ui.Text,
10931
- {
10932
- size: "small",
10933
- leading: "compact",
10934
- className: "text-ui-fg-subtle",
10935
- children: [
10936
- itemCount,
10937
- " ",
10938
- itemCount === 1 ? "item" : "items"
10939
- ]
10940
- }
10941
- ) }),
10942
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10943
- ] })
10944
- ] }) }),
10945
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsxRuntime.jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsxRuntime.jsx(
10946
- CustomItemForm,
10947
- {
10948
- orderId: preview.id,
10949
- currencyCode
10950
- }
10951
- ) : null)
10952
- ]
10953
- }
10954
- ) }),
10955
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10956
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10957
- /* @__PURE__ */ jsxRuntime.jsx(
10958
- ui.Button,
10959
- {
10960
- size: "small",
10961
- type: "button",
10962
- onClick: onSubmit,
10963
- isLoading: isSubmitting,
10964
- children: "Save"
10965
- }
10966
- )
10967
- ] }) })
10968
- ] });
10969
- };
10970
- const Item = ({ item, preview, currencyCode }) => {
10971
- if (item.variant_id) {
10972
- return /* @__PURE__ */ jsxRuntime.jsx(VariantItem, { item, preview, currencyCode });
10936
+ if (isError) {
10937
+ throw error;
10973
10938
  }
10974
- return /* @__PURE__ */ jsxRuntime.jsx(CustomItem, { item, preview, currencyCode });
10975
- };
10976
- const VariantItem = ({ item, preview, currencyCode }) => {
10977
- const [editing, setEditing] = React.useState(false);
10978
- const form = reactHookForm.useForm({
10979
- defaultValues: {
10980
- quantity: item.quantity,
10981
- unit_price: item.unit_price
10982
- },
10983
- resolver: zod.zodResolver(variantItemSchema)
10984
- });
10985
- const actionId = React.useMemo(() => {
10986
- var _a, _b;
10987
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10988
- }, [item]);
10989
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10990
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10991
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10992
- const onSubmit = form.handleSubmit(async (data) => {
10993
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10994
- setEditing(false);
10995
- return;
10996
- }
10997
- if (!actionId) {
10998
- await updateOriginalItem(
10939
+ return /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10940
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
10941
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
10942
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10943
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10944
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10945
+ ] }),
10946
+ /* @__PURE__ */ jsxRuntime.jsx(
10947
+ Combobox,
10948
+ {
10949
+ id: "promotion-combobox",
10950
+ "aria-describedby": "promotion-combobox-hint",
10951
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
10952
+ fetchNextPage: comboboxData.fetchNextPage,
10953
+ options: comboboxData.options,
10954
+ onSearchValueChange: comboboxData.onSearchValueChange,
10955
+ searchValue: comboboxData.searchValue,
10956
+ disabled: comboboxData.disabled || isAddingPromotions,
10957
+ onChange: add,
10958
+ value: comboboxValue
10959
+ }
10960
+ )
10961
+ ] }),
10962
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10963
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsxRuntime.jsx(
10964
+ PromotionItem,
10999
10965
  {
11000
- item_id: item.id,
11001
- quantity: data.quantity,
11002
- unit_price: convertNumber(data.unit_price)
10966
+ promotion,
10967
+ orderId: preview.id,
10968
+ isLoading: isPending
11003
10969
  },
10970
+ promotion.id
10971
+ )) })
10972
+ ] }) }),
10973
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
10974
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10975
+ /* @__PURE__ */ jsxRuntime.jsx(
10976
+ ui.Button,
11004
10977
  {
11005
- onSuccess: () => {
11006
- setEditing(false);
11007
- },
11008
- onError: (e) => {
11009
- ui.toast.error(e.message);
11010
- }
10978
+ size: "small",
10979
+ type: "submit",
10980
+ isLoading: isSubmitting || isAddingPromotions,
10981
+ children: "Save"
11011
10982
  }
11012
- );
11013
- return;
11014
- }
11015
- await updateActionItem(
10983
+ )
10984
+ ] }) })
10985
+ ] });
10986
+ };
10987
+ const PromotionItem = ({
10988
+ promotion,
10989
+ orderId,
10990
+ isLoading
10991
+ }) => {
10992
+ var _a;
10993
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10994
+ const onRemove = async () => {
10995
+ removePromotions(
11016
10996
  {
11017
- action_id: actionId,
11018
- quantity: data.quantity,
11019
- unit_price: convertNumber(data.unit_price)
10997
+ promo_codes: [promotion.code]
11020
10998
  },
11021
10999
  {
11022
- onSuccess: () => {
11023
- setEditing(false);
11024
- },
11025
11000
  onError: (e) => {
11026
11001
  ui.toast.error(e.message);
11027
11002
  }
11028
11003
  }
11029
11004
  );
11030
- });
11031
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
11032
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
11033
- /* @__PURE__ */ jsxRuntime.jsx(
11034
- Thumbnail,
11005
+ };
11006
+ const displayValue = getDisplayValue(promotion);
11007
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11008
+ "div",
11009
+ {
11010
+ className: ui.clx(
11011
+ "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
11035
11012
  {
11036
- thumbnail: item.thumbnail,
11037
- alt: item.product_title ?? void 0
11013
+ "animate-pulse": isLoading
11038
11014
  }
11039
11015
  ),
11040
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11041
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
11042
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
11043
- /* @__PURE__ */ jsxRuntime.jsxs(
11044
- ui.Text,
11045
- {
11046
- size: "small",
11047
- leading: "compact",
11048
- className: "text-ui-fg-subtle",
11049
- children: [
11050
- "(",
11051
- item.variant_title,
11052
- ")"
11053
- ]
11054
- }
11055
- )
11016
+ children: [
11017
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11018
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11019
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
11020
+ displayValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
11021
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: displayValue }),
11022
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: "·" })
11023
+ ] }),
11024
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11025
+ ] })
11056
11026
  ] }),
11057
11027
  /* @__PURE__ */ jsxRuntime.jsx(
11058
- ui.Text,
11028
+ ui.IconButton,
11059
11029
  {
11060
11030
  size: "small",
11061
- leading: "compact",
11062
- className: "text-ui-fg-subtle",
11063
- children: item.variant_sku
11031
+ type: "button",
11032
+ variant: "transparent",
11033
+ onClick: onRemove,
11034
+ isLoading: isPending || isLoading,
11035
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.XMark, {})
11064
11036
  }
11065
11037
  )
11066
- ] })
11067
- ] }),
11068
- editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
11069
- Form$2.Field,
11070
- {
11071
- control: form.control,
11072
- name: "quantity",
11073
- render: ({ field }) => {
11074
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
11075
- }
11076
- }
11077
- ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }) }),
11078
- editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
11079
- Form$2.Field,
11080
- {
11081
- control: form.control,
11082
- name: "unit_price",
11083
- render: ({ field: { onChange, ...field } }) => {
11084
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11085
- ui.CurrencyInput,
11086
- {
11087
- ...field,
11088
- symbol: getNativeSymbol(currencyCode),
11089
- code: currencyCode,
11090
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
11091
- }
11092
- ) }) });
11093
- }
11094
- }
11095
- ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
11096
- /* @__PURE__ */ jsxRuntime.jsx(
11097
- ui.IconButton,
11098
- {
11099
- type: "button",
11100
- size: "small",
11101
- onClick: editing ? onSubmit : () => {
11102
- setEditing(true);
11103
- },
11104
- disabled: isPending,
11105
- children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
11106
- }
11107
- )
11108
- ] }) }) });
11109
- };
11110
- const variantItemSchema = objectType({
11111
- quantity: numberType(),
11112
- unit_price: unionType([numberType(), stringType()])
11113
- });
11114
- const CustomItem = ({ item, preview, currencyCode }) => {
11115
- const [editing, setEditing] = React.useState(false);
11116
- const { quantity, unit_price, title } = item;
11117
- const form = reactHookForm.useForm({
11118
- defaultValues: {
11119
- title,
11120
- quantity,
11121
- unit_price
11038
+ ]
11122
11039
  },
11123
- resolver: zod.zodResolver(customItemSchema)
11124
- });
11125
- React.useEffect(() => {
11126
- form.reset({
11127
- title,
11128
- quantity,
11129
- unit_price
11130
- });
11131
- }, [form, title, quantity, unit_price]);
11132
- const actionId = React.useMemo(() => {
11133
- var _a, _b;
11134
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
11135
- }, [item]);
11136
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
11137
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
11138
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
11139
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
11140
- const onSubmit = form.handleSubmit(async (data) => {
11141
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
11142
- setEditing(false);
11143
- return;
11040
+ promotion.id
11041
+ );
11042
+ };
11043
+ function getDisplayValue(promotion) {
11044
+ var _a, _b, _c, _d;
11045
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11046
+ if (!value) {
11047
+ return null;
11048
+ }
11049
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11050
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11051
+ if (!currency) {
11052
+ return null;
11144
11053
  }
11145
- if (!actionId) {
11146
- await updateOriginalItem(
11147
- {
11148
- item_id: item.id,
11149
- quantity: data.quantity,
11150
- unit_price: convertNumber(data.unit_price)
11151
- },
11152
- {
11153
- onSuccess: () => {
11154
- setEditing(false);
11155
- },
11156
- onError: (e) => {
11157
- ui.toast.error(e.message);
11158
- }
11054
+ return getLocaleAmount(value, currency);
11055
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11056
+ return formatPercentage(value);
11057
+ }
11058
+ return null;
11059
+ }
11060
+ const formatter = new Intl.NumberFormat([], {
11061
+ style: "percent",
11062
+ minimumFractionDigits: 2
11063
+ });
11064
+ const formatPercentage = (value, isPercentageValue = false) => {
11065
+ let val = value || 0;
11066
+ if (!isPercentageValue) {
11067
+ val = val / 100;
11068
+ }
11069
+ return formatter.format(val);
11070
+ };
11071
+ function getPromotionCodes(items, shippingMethods) {
11072
+ const codes = /* @__PURE__ */ new Set();
11073
+ for (const item of items) {
11074
+ if (item.adjustments) {
11075
+ for (const adjustment of item.adjustments) {
11076
+ if (adjustment.code) {
11077
+ codes.add(adjustment.code);
11159
11078
  }
11160
- );
11161
- return;
11079
+ }
11162
11080
  }
11163
- if (data.quantity === 0) {
11164
- await removeActionItem(actionId, {
11165
- onSuccess: () => {
11166
- setEditing(false);
11167
- },
11168
- onError: (e) => {
11169
- ui.toast.error(e.message);
11081
+ }
11082
+ for (const shippingMethod of shippingMethods) {
11083
+ if (shippingMethod.adjustments) {
11084
+ for (const adjustment of shippingMethod.adjustments) {
11085
+ if (adjustment.code) {
11086
+ codes.add(adjustment.code);
11170
11087
  }
11171
- });
11172
- return;
11088
+ }
11089
+ }
11090
+ }
11091
+ return Array.from(codes);
11092
+ }
11093
+ const SalesChannel = () => {
11094
+ const { id } = reactRouterDom.useParams();
11095
+ const { draft_order, isPending, isError, error } = useDraftOrder(
11096
+ id,
11097
+ {
11098
+ fields: "+sales_channel_id"
11099
+ },
11100
+ {
11101
+ enabled: !!id
11173
11102
  }
11174
- await updateActionItem(
11103
+ );
11104
+ if (isError) {
11105
+ throw error;
11106
+ }
11107
+ const ISrEADY = !!draft_order && !isPending;
11108
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
11109
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
11110
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Sales Channel" }) }),
11111
+ /* @__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" }) })
11112
+ ] }),
11113
+ ISrEADY && /* @__PURE__ */ jsxRuntime.jsx(SalesChannelForm, { order: draft_order })
11114
+ ] });
11115
+ };
11116
+ const SalesChannelForm = ({ order }) => {
11117
+ const form = reactHookForm.useForm({
11118
+ defaultValues: {
11119
+ sales_channel_id: order.sales_channel_id || ""
11120
+ },
11121
+ resolver: zod.zodResolver(schema$2)
11122
+ });
11123
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11124
+ const { handleSuccess } = useRouteModal();
11125
+ const onSubmit = form.handleSubmit(async (data) => {
11126
+ await mutateAsync(
11175
11127
  {
11176
- action_id: actionId,
11177
- quantity: data.quantity,
11178
- unit_price: convertNumber(data.unit_price)
11128
+ sales_channel_id: data.sales_channel_id
11179
11129
  },
11180
11130
  {
11181
11131
  onSuccess: () => {
11182
- setEditing(false);
11132
+ ui.toast.success("Sales channel updated");
11133
+ handleSuccess();
11183
11134
  },
11184
- onError: (e) => {
11185
- ui.toast.error(e.message);
11135
+ onError: (error) => {
11136
+ ui.toast.error(error.message);
11186
11137
  }
11187
11138
  }
11188
11139
  );
11189
11140
  });
11190
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
11191
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
11192
- /* @__PURE__ */ jsxRuntime.jsx(
11193
- Thumbnail,
11194
- {
11195
- thumbnail: item.thumbnail,
11196
- alt: item.title ?? void 0
11197
- }
11198
- ),
11199
- editing ? /* @__PURE__ */ jsxRuntime.jsx(
11200
- Form$2.Field,
11201
- {
11202
- control: form.control,
11203
- name: "title",
11204
- render: ({ field }) => {
11205
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }) });
11206
- }
11207
- }
11208
- ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.title })
11209
- ] }),
11210
- editing ? /* @__PURE__ */ jsxRuntime.jsx(
11211
- Form$2.Field,
11212
- {
11213
- control: form.control,
11214
- name: "quantity",
11215
- render: ({ field }) => {
11216
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
11217
- }
11218
- }
11219
- ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }),
11220
- editing ? /* @__PURE__ */ jsxRuntime.jsx(
11221
- Form$2.Field,
11222
- {
11223
- control: form.control,
11224
- name: "unit_price",
11225
- render: ({ field: { onChange, ...field } }) => {
11226
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11227
- ui.CurrencyInput,
11141
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
11142
+ KeyboundForm,
11143
+ {
11144
+ className: "flex flex-1 flex-col overflow-hidden",
11145
+ onSubmit,
11146
+ children: [
11147
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(SalesChannelField, { control: form.control, order }) }),
11148
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
11149
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11150
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11151
+ ] }) })
11152
+ ]
11153
+ }
11154
+ ) });
11155
+ };
11156
+ const SalesChannelField = ({ control, order }) => {
11157
+ const salesChannels = useComboboxData({
11158
+ queryFn: async (params) => {
11159
+ return await sdk.admin.salesChannel.list(params);
11160
+ },
11161
+ queryKey: ["sales-channels"],
11162
+ getOptions: (data) => {
11163
+ return data.sales_channels.map((salesChannel) => ({
11164
+ label: salesChannel.name,
11165
+ value: salesChannel.id
11166
+ }));
11167
+ },
11168
+ defaultValue: order.sales_channel_id || void 0
11169
+ });
11170
+ return /* @__PURE__ */ jsxRuntime.jsx(
11171
+ Form$2.Field,
11172
+ {
11173
+ control,
11174
+ name: "sales_channel_id",
11175
+ render: ({ field }) => {
11176
+ return /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
11177
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Sales Channel" }),
11178
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11179
+ Combobox,
11228
11180
  {
11229
- ...field,
11230
- symbol: getNativeSymbol(currencyCode),
11231
- code: currencyCode,
11232
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
11181
+ options: salesChannels.options,
11182
+ fetchNextPage: salesChannels.fetchNextPage,
11183
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
11184
+ searchValue: salesChannels.searchValue,
11185
+ onSearchValueChange: salesChannels.onSearchValueChange,
11186
+ placeholder: "Select sales channel",
11187
+ ...field
11233
11188
  }
11234
- ) }) });
11235
- }
11189
+ ) }),
11190
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11191
+ ] });
11236
11192
  }
11237
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
11238
- /* @__PURE__ */ jsxRuntime.jsx(
11239
- ui.IconButton,
11193
+ }
11194
+ );
11195
+ };
11196
+ const schema$2 = objectType({
11197
+ sales_channel_id: stringType().min(1)
11198
+ });
11199
+ const InlineTip = React.forwardRef(
11200
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
11201
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
11202
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11203
+ "div",
11240
11204
  {
11241
- type: "button",
11242
- size: "small",
11243
- onClick: editing ? onSubmit : () => {
11244
- setEditing(true);
11245
- },
11246
- disabled: isPending,
11247
- children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
11205
+ ref,
11206
+ className: ui.clx(
11207
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
11208
+ className
11209
+ ),
11210
+ ...props,
11211
+ children: [
11212
+ /* @__PURE__ */ jsxRuntime.jsx(
11213
+ "div",
11214
+ {
11215
+ role: "presentation",
11216
+ className: ui.clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
11217
+ "bg-ui-tag-orange-icon": variant === "warning"
11218
+ })
11219
+ }
11220
+ ),
11221
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-pretty", children: [
11222
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
11223
+ labelValue,
11224
+ ":"
11225
+ ] }),
11226
+ " ",
11227
+ children
11228
+ ] })
11229
+ ]
11248
11230
  }
11249
- )
11250
- ] }) }) });
11251
- };
11252
- const StackedModalTrigger$1 = ({
11253
- type,
11254
- setModalContent
11255
- }) => {
11256
- const { setIsOpen } = useStackedModal();
11257
- const onClick = React.useCallback(() => {
11258
- setModalContent(type);
11259
- setIsOpen(STACKED_MODAL_ID, true);
11260
- }, [setModalContent, setIsOpen, type]);
11261
- return /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
11262
- };
11263
- const VARIANT_PREFIX = "items";
11264
- const LIMIT = 50;
11265
- const ExistingItemsForm = ({ orderId, items }) => {
11266
- const { setIsOpen } = useStackedModal();
11267
- const [rowSelection, setRowSelection] = React.useState(
11268
- items.reduce((acc, item) => {
11269
- acc[item.variant_id] = true;
11270
- return acc;
11271
- }, {})
11272
- );
11273
- React.useEffect(() => {
11274
- setRowSelection(
11275
- items.reduce((acc, item) => {
11276
- if (item.variant_id) {
11277
- acc[item.variant_id] = true;
11278
- }
11279
- return acc;
11280
- }, {})
11281
11231
  );
11282
- }, [items]);
11283
- const { q, order, offset } = useQueryParams(
11284
- ["q", "order", "offset"],
11285
- VARIANT_PREFIX
11286
- );
11287
- const { variants, count, isPending, isError, error } = useProductVariants(
11288
- {
11289
- q,
11290
- order,
11291
- offset: offset ? parseInt(offset) : void 0,
11292
- limit: LIMIT
11232
+ }
11233
+ );
11234
+ InlineTip.displayName = "InlineTip";
11235
+ const MetadataFieldSchema = objectType({
11236
+ key: stringType(),
11237
+ disabled: booleanType().optional(),
11238
+ value: anyType()
11239
+ });
11240
+ const MetadataSchema = objectType({
11241
+ metadata: arrayType(MetadataFieldSchema)
11242
+ });
11243
+ const Metadata = () => {
11244
+ const { id } = reactRouterDom.useParams();
11245
+ const { order, isPending, isError, error } = useOrder(id, {
11246
+ fields: "metadata"
11247
+ });
11248
+ if (isError) {
11249
+ throw error;
11250
+ }
11251
+ const isReady = !isPending && !!order;
11252
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
11253
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
11254
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Metadata" }) }),
11255
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
11256
+ ] }),
11257
+ !isReady ? /* @__PURE__ */ jsxRuntime.jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
11258
+ ] });
11259
+ };
11260
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
11261
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
11262
+ const MetadataForm = ({ orderId, metadata }) => {
11263
+ const { handleSuccess } = useRouteModal();
11264
+ const hasUneditableRows = getHasUneditableRows(metadata);
11265
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
11266
+ const form = reactHookForm.useForm({
11267
+ defaultValues: {
11268
+ metadata: getDefaultValues(metadata)
11293
11269
  },
11294
- {
11295
- placeholderData: reactQuery.keepPreviousData
11296
- }
11297
- );
11298
- const columns = useColumns();
11299
- const { mutateAsync } = useDraftOrderAddItems(orderId);
11300
- const onSubmit = async () => {
11301
- const ids = Object.keys(rowSelection).filter(
11302
- (id) => !items.find((i) => i.variant_id === id)
11303
- );
11270
+ resolver: zod.zodResolver(MetadataSchema)
11271
+ });
11272
+ const handleSubmit = form.handleSubmit(async (data) => {
11273
+ const parsedData = parseValues(data);
11304
11274
  await mutateAsync(
11305
11275
  {
11306
- items: ids.map((id) => ({
11307
- variant_id: id,
11308
- quantity: 1
11309
- }))
11276
+ metadata: parsedData
11310
11277
  },
11311
11278
  {
11312
11279
  onSuccess: () => {
11313
- setRowSelection({});
11314
- setIsOpen(STACKED_MODAL_ID, false);
11280
+ ui.toast.success("Metadata updated");
11281
+ handleSuccess();
11315
11282
  },
11316
- onError: (e) => {
11317
- ui.toast.error(e.message);
11283
+ onError: (error) => {
11284
+ ui.toast.error(error.message);
11318
11285
  }
11319
11286
  }
11320
11287
  );
11321
- };
11322
- if (isError) {
11323
- throw error;
11288
+ });
11289
+ const { fields, insert, remove } = reactHookForm.useFieldArray({
11290
+ control: form.control,
11291
+ name: "metadata"
11292
+ });
11293
+ function deleteRow(index) {
11294
+ remove(index);
11295
+ if (fields.length === 1) {
11296
+ insert(0, {
11297
+ key: "",
11298
+ value: "",
11299
+ disabled: false
11300
+ });
11301
+ }
11324
11302
  }
11325
- return /* @__PURE__ */ jsxRuntime.jsxs(
11326
- StackedFocusModal.Content,
11303
+ function insertRow(index, position) {
11304
+ insert(index + (position === "above" ? 0 : 1), {
11305
+ key: "",
11306
+ value: "",
11307
+ disabled: false
11308
+ });
11309
+ }
11310
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
11311
+ KeyboundForm,
11327
11312
  {
11328
- onOpenAutoFocus: (e) => {
11329
- e.preventDefault();
11330
- const searchInput = document.querySelector(
11331
- "[data-modal-id='modal-search-input']"
11332
- );
11333
- if (searchInput) {
11334
- searchInput.focus();
11335
- }
11336
- },
11313
+ onSubmit: handleSubmit,
11314
+ className: "flex flex-1 flex-col overflow-hidden",
11337
11315
  children: [
11338
- /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Header, { children: [
11339
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Product Variants" }) }),
11340
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
11341
- ] }),
11342
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
11343
- DataTable,
11344
- {
11345
- data: variants,
11346
- columns,
11347
- isLoading: isPending,
11348
- getRowId: (row) => row.id,
11349
- rowCount: count,
11350
- prefix: VARIANT_PREFIX,
11351
- layout: "fill",
11352
- rowSelection: {
11353
- state: rowSelection,
11354
- onRowSelectionChange: setRowSelection,
11355
- enableRowSelection: (row) => {
11356
- return !items.find((i) => i.variant_id === row.original.id);
11316
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
11317
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
11318
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
11319
+ /* @__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" }) }),
11320
+ /* @__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" }) })
11321
+ ] }),
11322
+ fields.map((field, index) => {
11323
+ const isDisabled = field.disabled || false;
11324
+ let placeholder = "-";
11325
+ if (typeof field.value === "object") {
11326
+ placeholder = "{ ... }";
11357
11327
  }
11358
- },
11359
- autoFocusSearch: true
11360
- }
11361
- ) }),
11362
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11363
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11364
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
11328
+ if (Array.isArray(field.value)) {
11329
+ placeholder = "[ ... ]";
11330
+ }
11331
+ return /* @__PURE__ */ jsxRuntime.jsx(
11332
+ ConditionalTooltip,
11333
+ {
11334
+ showTooltip: isDisabled,
11335
+ content: "This row is disabled because it contains non-primitive data.",
11336
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/table relative", children: [
11337
+ /* @__PURE__ */ jsxRuntime.jsxs(
11338
+ "div",
11339
+ {
11340
+ className: ui.clx("grid grid-cols-2 divide-x", {
11341
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
11342
+ }),
11343
+ children: [
11344
+ /* @__PURE__ */ jsxRuntime.jsx(
11345
+ Form$2.Field,
11346
+ {
11347
+ control: form.control,
11348
+ name: `metadata.${index}.key`,
11349
+ render: ({ field: field2 }) => {
11350
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11351
+ GridInput,
11352
+ {
11353
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
11354
+ ...field2,
11355
+ disabled: isDisabled,
11356
+ placeholder: "Key"
11357
+ }
11358
+ ) }) });
11359
+ }
11360
+ }
11361
+ ),
11362
+ /* @__PURE__ */ jsxRuntime.jsx(
11363
+ Form$2.Field,
11364
+ {
11365
+ control: form.control,
11366
+ name: `metadata.${index}.value`,
11367
+ render: ({ field: { value, ...field2 } }) => {
11368
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11369
+ GridInput,
11370
+ {
11371
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
11372
+ ...field2,
11373
+ value: isDisabled ? placeholder : value,
11374
+ disabled: isDisabled,
11375
+ placeholder: "Value"
11376
+ }
11377
+ ) }) });
11378
+ }
11379
+ }
11380
+ )
11381
+ ]
11382
+ }
11383
+ ),
11384
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
11385
+ /* @__PURE__ */ jsxRuntime.jsx(
11386
+ ui.DropdownMenu.Trigger,
11387
+ {
11388
+ className: ui.clx(
11389
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
11390
+ {
11391
+ hidden: isDisabled
11392
+ }
11393
+ ),
11394
+ disabled: isDisabled,
11395
+ asChild: true,
11396
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisVertical, {}) })
11397
+ }
11398
+ ),
11399
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
11400
+ /* @__PURE__ */ jsxRuntime.jsxs(
11401
+ ui.DropdownMenu.Item,
11402
+ {
11403
+ className: "gap-x-2",
11404
+ onClick: () => insertRow(index, "above"),
11405
+ children: [
11406
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpMini, { className: "text-ui-fg-subtle" }),
11407
+ "Insert row above"
11408
+ ]
11409
+ }
11410
+ ),
11411
+ /* @__PURE__ */ jsxRuntime.jsxs(
11412
+ ui.DropdownMenu.Item,
11413
+ {
11414
+ className: "gap-x-2",
11415
+ onClick: () => insertRow(index, "below"),
11416
+ children: [
11417
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownMini, { className: "text-ui-fg-subtle" }),
11418
+ "Insert row below"
11419
+ ]
11420
+ }
11421
+ ),
11422
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
11423
+ /* @__PURE__ */ jsxRuntime.jsxs(
11424
+ ui.DropdownMenu.Item,
11425
+ {
11426
+ className: "gap-x-2",
11427
+ onClick: () => deleteRow(index),
11428
+ children: [
11429
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
11430
+ "Delete row"
11431
+ ]
11432
+ }
11433
+ )
11434
+ ] })
11435
+ ] })
11436
+ ] })
11437
+ },
11438
+ field.id
11439
+ );
11440
+ })
11441
+ ] }),
11442
+ 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." })
11443
+ ] }),
11444
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11445
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11446
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11365
11447
  ] }) })
11366
11448
  ]
11367
11449
  }
11368
- );
11450
+ ) });
11369
11451
  };
11370
- const columnHelper = ui.createDataTableColumnHelper();
11371
- const useColumns = () => {
11372
- return React.useMemo(() => {
11452
+ const GridInput = React.forwardRef(({ className, ...props }, ref) => {
11453
+ return /* @__PURE__ */ jsxRuntime.jsx(
11454
+ "input",
11455
+ {
11456
+ ref,
11457
+ ...props,
11458
+ autoComplete: "off",
11459
+ className: ui.clx(
11460
+ "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",
11461
+ className
11462
+ )
11463
+ }
11464
+ );
11465
+ });
11466
+ GridInput.displayName = "MetadataForm.GridInput";
11467
+ const PlaceholderInner = () => {
11468
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11469
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11470
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11471
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" }),
11472
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" })
11473
+ ] }) })
11474
+ ] });
11475
+ };
11476
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
11477
+ function getDefaultValues(metadata) {
11478
+ if (!metadata || !Object.keys(metadata).length) {
11373
11479
  return [
11374
- columnHelper.select(),
11375
- columnHelper.accessor("product.title", {
11376
- header: "Product",
11377
- cell: ({ row }) => {
11378
- var _a, _b, _c;
11379
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
11380
- /* @__PURE__ */ jsxRuntime.jsx(
11381
- Thumbnail,
11382
- {
11383
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
11384
- alt: (_b = row.original.product) == null ? void 0 : _b.title
11385
- }
11386
- ),
11387
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
11388
- ] });
11389
- },
11390
- enableSorting: true
11391
- }),
11392
- columnHelper.accessor("title", {
11393
- header: "Variant",
11394
- enableSorting: true
11395
- }),
11396
- columnHelper.accessor("sku", {
11397
- header: "SKU",
11398
- cell: ({ getValue }) => {
11399
- return getValue() ?? "-";
11400
- },
11401
- enableSorting: true
11402
- }),
11403
- columnHelper.accessor("updated_at", {
11404
- header: "Updated",
11405
- cell: ({ getValue }) => {
11406
- return /* @__PURE__ */ jsxRuntime.jsx(
11407
- ui.Tooltip,
11408
- {
11409
- content: getFullDate({ date: getValue(), includeTime: true }),
11410
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
11411
- }
11412
- );
11413
- },
11414
- enableSorting: true,
11415
- sortAscLabel: "Oldest first",
11416
- sortDescLabel: "Newest first"
11417
- }),
11418
- columnHelper.accessor("created_at", {
11419
- header: "Created",
11420
- cell: ({ getValue }) => {
11421
- return /* @__PURE__ */ jsxRuntime.jsx(
11422
- ui.Tooltip,
11423
- {
11424
- content: getFullDate({ date: getValue(), includeTime: true }),
11425
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
11426
- }
11427
- );
11428
- },
11429
- enableSorting: true,
11430
- sortAscLabel: "Oldest first",
11431
- sortDescLabel: "Newest first"
11432
- })
11480
+ {
11481
+ key: "",
11482
+ value: "",
11483
+ disabled: false
11484
+ }
11433
11485
  ];
11434
- }, []);
11435
- };
11436
- const CustomItemForm = ({ orderId, currencyCode }) => {
11437
- const { setIsOpen } = useStackedModal();
11438
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
11439
- const form = reactHookForm.useForm({
11440
- defaultValues: {
11441
- title: "",
11442
- quantity: 1,
11443
- unit_price: ""
11444
- },
11445
- resolver: zod.zodResolver(customItemSchema)
11486
+ }
11487
+ return Object.entries(metadata).map(([key, value]) => {
11488
+ if (!EDITABLE_TYPES.includes(typeof value)) {
11489
+ return {
11490
+ key,
11491
+ value,
11492
+ disabled: true
11493
+ };
11494
+ }
11495
+ let stringValue = value;
11496
+ if (typeof value !== "string") {
11497
+ stringValue = JSON.stringify(value);
11498
+ }
11499
+ return {
11500
+ key,
11501
+ value: stringValue,
11502
+ original_key: key
11503
+ };
11446
11504
  });
11447
- const onSubmit = form.handleSubmit(async (data) => {
11448
- await addItems(
11449
- {
11450
- items: [
11451
- {
11452
- title: data.title,
11453
- quantity: data.quantity,
11454
- unit_price: convertNumber(data.unit_price)
11455
- }
11456
- ]
11457
- },
11458
- {
11459
- onSuccess: () => {
11460
- setIsOpen(STACKED_MODAL_ID, false);
11461
- },
11462
- onError: (e) => {
11463
- ui.toast.error(e.message);
11464
- }
11505
+ }
11506
+ function parseValues(values) {
11507
+ const metadata = values.metadata;
11508
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11509
+ if (isEmpty) {
11510
+ return null;
11511
+ }
11512
+ const update = {};
11513
+ metadata.forEach((field) => {
11514
+ let key = field.key;
11515
+ let value = field.value;
11516
+ const disabled = field.disabled;
11517
+ if (!key || !value) {
11518
+ return;
11519
+ }
11520
+ if (disabled) {
11521
+ update[key] = value;
11522
+ return;
11523
+ }
11524
+ key = key.trim();
11525
+ value = value.trim();
11526
+ if (value === "true") {
11527
+ update[key] = true;
11528
+ } else if (value === "false") {
11529
+ update[key] = false;
11530
+ } else {
11531
+ const parsedNumber = parseFloat(value);
11532
+ if (!isNaN(parsedNumber)) {
11533
+ update[key] = parsedNumber;
11534
+ } else {
11535
+ update[key] = value;
11465
11536
  }
11466
- );
11537
+ }
11467
11538
  });
11468
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Content, { children: [
11469
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Header, {}),
11470
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.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-2 py-16", children: [
11471
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11472
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Add custom item" }) }),
11473
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a custom item to the order. This will add a new line item that is not associated with an existing product." }) })
11474
- ] }),
11475
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11476
- /* @__PURE__ */ jsxRuntime.jsx(
11477
- Form$2.Field,
11478
- {
11479
- control: form.control,
11480
- name: "title",
11481
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11482
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11483
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Title" }),
11484
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the title of the item" })
11485
- ] }),
11486
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11487
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
11488
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11489
- ] })
11490
- ] }) })
11491
- }
11492
- ),
11493
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11494
- /* @__PURE__ */ jsxRuntime.jsx(
11495
- Form$2.Field,
11496
- {
11497
- control: form.control,
11498
- name: "unit_price",
11499
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11500
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11501
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Unit price" }),
11502
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
11503
- ] }),
11504
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11505
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11506
- ui.CurrencyInput,
11507
- {
11508
- symbol: getNativeSymbol(currencyCode),
11509
- code: currencyCode,
11510
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
11511
- ...field
11512
- }
11513
- ) }),
11514
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11515
- ] })
11516
- ] }) })
11517
- }
11518
- ),
11519
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11520
- /* @__PURE__ */ jsxRuntime.jsx(
11521
- Form$2.Field,
11522
- {
11523
- control: form.control,
11524
- name: "quantity",
11525
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11526
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11527
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Quantity" }),
11528
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
11529
- ] }),
11530
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 w-full", children: [
11531
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field, className: "w-full" }) }) }),
11532
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11533
- ] })
11534
- ] }) })
11535
- }
11536
- )
11537
- ] }) }) }),
11538
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11539
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11540
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
11541
- ] }) })
11542
- ] }) }) });
11543
- };
11544
- const customItemSchema = objectType({
11545
- title: stringType().min(1),
11546
- quantity: numberType(),
11547
- unit_price: unionType([numberType(), stringType()])
11548
- });
11539
+ return update;
11540
+ }
11541
+ function getHasUneditableRows(metadata) {
11542
+ if (!metadata) {
11543
+ return false;
11544
+ }
11545
+ return Object.values(metadata).some(
11546
+ (value) => !EDITABLE_TYPES.includes(typeof value)
11547
+ );
11548
+ }
11549
11549
  const STACKED_FOCUS_MODAL_ID = "shipping-form";
11550
11550
  const Shipping = () => {
11551
11551
  var _a;
@@ -13053,20 +13053,20 @@ const routeModule = {
13053
13053
  loader,
13054
13054
  children: [
13055
13055
  {
13056
- Component: Email,
13057
- path: "/draft-orders/:id/email"
13056
+ Component: BillingAddress,
13057
+ path: "/draft-orders/:id/billing-address"
13058
13058
  },
13059
13059
  {
13060
13060
  Component: CustomItems,
13061
13061
  path: "/draft-orders/:id/custom-items"
13062
13062
  },
13063
13063
  {
13064
- Component: BillingAddress,
13065
- path: "/draft-orders/:id/billing-address"
13064
+ Component: Email,
13065
+ path: "/draft-orders/:id/email"
13066
13066
  },
13067
13067
  {
13068
- Component: Metadata,
13069
- path: "/draft-orders/:id/metadata"
13068
+ Component: Items,
13069
+ path: "/draft-orders/:id/items"
13070
13070
  },
13071
13071
  {
13072
13072
  Component: Promotions,
@@ -13077,8 +13077,8 @@ const routeModule = {
13077
13077
  path: "/draft-orders/:id/sales-channel"
13078
13078
  },
13079
13079
  {
13080
- Component: Items,
13081
- path: "/draft-orders/:id/items"
13080
+ Component: Metadata,
13081
+ path: "/draft-orders/:id/metadata"
13082
13082
  },
13083
13083
  {
13084
13084
  Component: Shipping,