@medusajs/draft-order 2.11.0-preview-20251020090157 → 2.11.0-preview-20251020141229

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