@medusajs/draft-order 2.10.2-preview-20250908180200 → 2.10.2-preview-20250909000311

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.
@@ -9567,6 +9567,217 @@ const ID = () => {
9567
9567
  /* @__PURE__ */ jsx(Outlet, {})
9568
9568
  ] });
9569
9569
  };
9570
+ const CustomItems = () => {
9571
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9572
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
9573
+ /* @__PURE__ */ jsx(CustomItemsForm, {})
9574
+ ] });
9575
+ };
9576
+ const CustomItemsForm = () => {
9577
+ const form = useForm({
9578
+ resolver: zodResolver(schema$5)
9579
+ });
9580
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9581
+ /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
9582
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9583
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9584
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
9585
+ ] }) })
9586
+ ] }) });
9587
+ };
9588
+ const schema$5 = objectType({
9589
+ email: stringType().email()
9590
+ });
9591
+ const BillingAddress = () => {
9592
+ const { id } = useParams();
9593
+ const { order, isPending, isError, error } = useOrder(id, {
9594
+ fields: "+billing_address"
9595
+ });
9596
+ if (isError) {
9597
+ throw error;
9598
+ }
9599
+ const isReady = !isPending && !!order;
9600
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9601
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9602
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Billing Address" }) }),
9603
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the billing address for the draft order" }) })
9604
+ ] }),
9605
+ isReady && /* @__PURE__ */ jsx(BillingAddressForm, { order })
9606
+ ] });
9607
+ };
9608
+ const BillingAddressForm = ({ order }) => {
9609
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
9610
+ const form = useForm({
9611
+ defaultValues: {
9612
+ first_name: ((_a = order.billing_address) == null ? void 0 : _a.first_name) ?? "",
9613
+ last_name: ((_b = order.billing_address) == null ? void 0 : _b.last_name) ?? "",
9614
+ company: ((_c = order.billing_address) == null ? void 0 : _c.company) ?? "",
9615
+ address_1: ((_d = order.billing_address) == null ? void 0 : _d.address_1) ?? "",
9616
+ address_2: ((_e = order.billing_address) == null ? void 0 : _e.address_2) ?? "",
9617
+ city: ((_f = order.billing_address) == null ? void 0 : _f.city) ?? "",
9618
+ province: ((_g = order.billing_address) == null ? void 0 : _g.province) ?? "",
9619
+ country_code: ((_h = order.billing_address) == null ? void 0 : _h.country_code) ?? "",
9620
+ postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
9621
+ phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
9622
+ },
9623
+ resolver: zodResolver(schema$4)
9624
+ });
9625
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9626
+ const { handleSuccess } = useRouteModal();
9627
+ const onSubmit = form.handleSubmit(async (data) => {
9628
+ await mutateAsync(
9629
+ { billing_address: data },
9630
+ {
9631
+ onSuccess: () => {
9632
+ handleSuccess();
9633
+ },
9634
+ onError: (error) => {
9635
+ toast.error(error.message);
9636
+ }
9637
+ }
9638
+ );
9639
+ });
9640
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9641
+ KeyboundForm,
9642
+ {
9643
+ className: "flex flex-1 flex-col overflow-hidden",
9644
+ onSubmit,
9645
+ children: [
9646
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
9647
+ /* @__PURE__ */ jsx(
9648
+ Form$2.Field,
9649
+ {
9650
+ control: form.control,
9651
+ name: "country_code",
9652
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9653
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
9654
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
9655
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9656
+ ] })
9657
+ }
9658
+ ),
9659
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
9660
+ /* @__PURE__ */ jsx(
9661
+ Form$2.Field,
9662
+ {
9663
+ control: form.control,
9664
+ name: "first_name",
9665
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9666
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
9667
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9668
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9669
+ ] })
9670
+ }
9671
+ ),
9672
+ /* @__PURE__ */ jsx(
9673
+ Form$2.Field,
9674
+ {
9675
+ control: form.control,
9676
+ name: "last_name",
9677
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9678
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
9679
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9680
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9681
+ ] })
9682
+ }
9683
+ )
9684
+ ] }),
9685
+ /* @__PURE__ */ jsx(
9686
+ Form$2.Field,
9687
+ {
9688
+ control: form.control,
9689
+ name: "company",
9690
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9691
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
9692
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9693
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9694
+ ] })
9695
+ }
9696
+ ),
9697
+ /* @__PURE__ */ jsx(
9698
+ Form$2.Field,
9699
+ {
9700
+ control: form.control,
9701
+ name: "address_1",
9702
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9703
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
9704
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9705
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9706
+ ] })
9707
+ }
9708
+ ),
9709
+ /* @__PURE__ */ jsx(
9710
+ Form$2.Field,
9711
+ {
9712
+ control: form.control,
9713
+ name: "address_2",
9714
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9715
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
9716
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9717
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9718
+ ] })
9719
+ }
9720
+ ),
9721
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
9722
+ /* @__PURE__ */ jsx(
9723
+ Form$2.Field,
9724
+ {
9725
+ control: form.control,
9726
+ name: "postal_code",
9727
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9728
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
9729
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9730
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9731
+ ] })
9732
+ }
9733
+ ),
9734
+ /* @__PURE__ */ jsx(
9735
+ Form$2.Field,
9736
+ {
9737
+ control: form.control,
9738
+ name: "city",
9739
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9740
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
9741
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9742
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9743
+ ] })
9744
+ }
9745
+ )
9746
+ ] }),
9747
+ /* @__PURE__ */ jsx(
9748
+ Form$2.Field,
9749
+ {
9750
+ control: form.control,
9751
+ name: "province",
9752
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9753
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
9754
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9755
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9756
+ ] })
9757
+ }
9758
+ ),
9759
+ /* @__PURE__ */ jsx(
9760
+ Form$2.Field,
9761
+ {
9762
+ control: form.control,
9763
+ name: "phone",
9764
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9765
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
9766
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9767
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9768
+ ] })
9769
+ }
9770
+ )
9771
+ ] }) }),
9772
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9773
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9774
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9775
+ ] }) })
9776
+ ]
9777
+ }
9778
+ ) });
9779
+ };
9780
+ const schema$4 = addressSchema;
9570
9781
  const Email = () => {
9571
9782
  const { id } = useParams();
9572
9783
  const { order, isPending, isError, error } = useOrder(id, {
@@ -9589,7 +9800,7 @@ const EmailForm = ({ order }) => {
9589
9800
  defaultValues: {
9590
9801
  email: order.email ?? ""
9591
9802
  },
9592
- resolver: zodResolver(schema$5)
9803
+ resolver: zodResolver(schema$3)
9593
9804
  });
9594
9805
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9595
9806
  const { handleSuccess } = useRouteModal();
@@ -9632,130 +9843,25 @@ const EmailForm = ({ order }) => {
9632
9843
  }
9633
9844
  ) });
9634
9845
  };
9635
- const schema$5 = objectType({
9846
+ const schema$3 = objectType({
9636
9847
  email: stringType().email()
9637
9848
  });
9638
- const NumberInput = forwardRef(
9639
- ({
9640
- value,
9641
- onChange,
9642
- size = "base",
9643
- min = 0,
9644
- max = 100,
9645
- step = 1,
9646
- className,
9647
- disabled,
9648
- ...props
9649
- }, ref) => {
9650
- const handleChange = (event) => {
9651
- const newValue = event.target.value === "" ? min : Number(event.target.value);
9652
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9653
- onChange(newValue);
9654
- }
9655
- };
9656
- const handleIncrement = () => {
9657
- const newValue = value + step;
9658
- if (max === void 0 || newValue <= max) {
9659
- onChange(newValue);
9660
- }
9661
- };
9662
- const handleDecrement = () => {
9663
- const newValue = value - step;
9664
- if (min === void 0 || newValue >= min) {
9665
- onChange(newValue);
9666
- }
9667
- };
9668
- return /* @__PURE__ */ jsxs(
9669
- "div",
9670
- {
9671
- className: clx(
9672
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9673
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9674
- {
9675
- "h-7": size === "small",
9676
- "h-8": size === "base"
9677
- },
9678
- className
9679
- ),
9680
- children: [
9681
- /* @__PURE__ */ jsx(
9682
- "input",
9683
- {
9684
- ref,
9685
- type: "number",
9686
- value,
9687
- onChange: handleChange,
9688
- min,
9689
- max,
9690
- step,
9691
- className: clx(
9692
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9693
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9694
- "placeholder:text-ui-fg-muted"
9695
- ),
9696
- ...props
9697
- }
9698
- ),
9699
- /* @__PURE__ */ jsxs(
9700
- "button",
9701
- {
9702
- className: clx(
9703
- "flex items-center justify-center outline-none transition-fg",
9704
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9705
- "focus:bg-ui-bg-field-component-hover",
9706
- "hover:bg-ui-bg-field-component-hover",
9707
- {
9708
- "size-7": size === "small",
9709
- "size-8": size === "base"
9710
- }
9711
- ),
9712
- type: "button",
9713
- onClick: handleDecrement,
9714
- disabled: min !== void 0 && value <= min || disabled,
9715
- children: [
9716
- /* @__PURE__ */ jsx(Minus, {}),
9717
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9718
- ]
9719
- }
9720
- ),
9721
- /* @__PURE__ */ jsxs(
9722
- "button",
9723
- {
9724
- className: clx(
9725
- "flex items-center justify-center outline-none transition-fg",
9726
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9727
- "focus:bg-ui-bg-field-hover",
9728
- "hover:bg-ui-bg-field-hover",
9729
- {
9730
- "size-7": size === "small",
9731
- "size-8": size === "base"
9732
- }
9733
- ),
9734
- type: "button",
9735
- onClick: handleIncrement,
9736
- disabled: max !== void 0 && value >= max || disabled,
9737
- children: [
9738
- /* @__PURE__ */ jsx(Plus, {}),
9739
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9740
- ]
9741
- }
9742
- )
9743
- ]
9744
- }
9745
- );
9746
- }
9747
- );
9748
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9749
- const productVariantsQueryKeys = {
9849
+ const PROMOTION_QUERY_KEY = "promotions";
9850
+ const promotionsQueryKeys = {
9750
9851
  list: (query2) => [
9751
- PRODUCT_VARIANTS_QUERY_KEY,
9852
+ PROMOTION_QUERY_KEY,
9853
+ query2 ? query2 : void 0
9854
+ ],
9855
+ detail: (id, query2) => [
9856
+ PROMOTION_QUERY_KEY,
9857
+ id,
9752
9858
  query2 ? query2 : void 0
9753
9859
  ]
9754
9860
  };
9755
- const useProductVariants = (query2, options) => {
9861
+ const usePromotions = (query2, options) => {
9756
9862
  const { data, ...rest } = useQuery({
9757
- queryKey: productVariantsQueryKeys.list(query2),
9758
- queryFn: async () => await sdk.admin.productVariant.list(query2),
9863
+ queryKey: promotionsQueryKeys.list(query2),
9864
+ queryFn: async () => sdk.admin.promotion.list(query2),
9759
9865
  ...options
9760
9866
  });
9761
9867
  return { ...data, ...rest };
@@ -9806,65 +9912,85 @@ const useInitiateOrderEdit = ({
9806
9912
  run();
9807
9913
  }, [preview, navigate, mutateAsync]);
9808
9914
  };
9809
- function convertNumber(value) {
9810
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
9811
- }
9812
- const STACKED_MODAL_ID = "items_stacked_modal";
9813
- const Items = () => {
9915
+ const Promotions = () => {
9814
9916
  const { id } = useParams();
9815
9917
  const {
9816
9918
  order: preview,
9817
- isPending: isPreviewPending,
9818
9919
  isError: isPreviewError,
9819
9920
  error: previewError
9820
- } = useOrderPreview(id, void 0, {
9821
- placeholderData: keepPreviousData
9822
- });
9921
+ } = useOrderPreview(id, void 0);
9823
9922
  useInitiateOrderEdit({ preview });
9824
- const { draft_order, isPending, isError, error } = useDraftOrder(
9825
- id,
9826
- {
9827
- fields: "currency_code"
9828
- },
9829
- {
9830
- enabled: !!id
9831
- }
9832
- );
9833
9923
  const { onCancel } = useCancelOrderEdit({ preview });
9834
- if (isError) {
9835
- throw error;
9836
- }
9837
9924
  if (isPreviewError) {
9838
9925
  throw previewError;
9839
9926
  }
9840
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
9841
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
9842
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
9843
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
9844
- ] }) });
9927
+ const isReady = !!preview;
9928
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
9929
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
9930
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
9931
+ ] });
9845
9932
  };
9846
- const ItemsForm = ({ preview, currencyCode }) => {
9847
- var _a;
9933
+ const PromotionForm = ({ preview }) => {
9934
+ const { items, shipping_methods } = preview;
9848
9935
  const [isSubmitting, setIsSubmitting] = useState(false);
9849
- const [modalContent, setModalContent] = useState(
9850
- null
9851
- );
9936
+ const [comboboxValue, setComboboxValue] = useState("");
9852
9937
  const { handleSuccess } = useRouteModal();
9853
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
9938
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
9939
+ const promoIds = getPromotionIds(items, shipping_methods);
9940
+ const { promotions, isPending, isError, error } = usePromotions(
9941
+ {
9942
+ id: promoIds
9943
+ },
9944
+ {
9945
+ enabled: !!promoIds.length
9946
+ }
9947
+ );
9948
+ const comboboxData = useComboboxData({
9949
+ queryKey: ["promotions", "combobox", promoIds],
9950
+ queryFn: async (params) => {
9951
+ return await sdk.admin.promotion.list({
9952
+ ...params,
9953
+ id: {
9954
+ $nin: promoIds
9955
+ }
9956
+ });
9957
+ },
9958
+ getOptions: (data) => {
9959
+ return data.promotions.map((promotion) => ({
9960
+ label: promotion.code,
9961
+ value: promotion.code
9962
+ }));
9963
+ }
9964
+ });
9965
+ const add = async (value) => {
9966
+ if (!value) {
9967
+ return;
9968
+ }
9969
+ addPromotions(
9970
+ {
9971
+ promo_codes: [value]
9972
+ },
9973
+ {
9974
+ onError: (e) => {
9975
+ toast.error(e.message);
9976
+ comboboxData.onSearchValueChange("");
9977
+ setComboboxValue("");
9978
+ },
9979
+ onSuccess: () => {
9980
+ comboboxData.onSearchValueChange("");
9981
+ setComboboxValue("");
9982
+ }
9983
+ }
9984
+ );
9985
+ };
9854
9986
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
9855
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
9856
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
9857
- const matches = useMemo(() => {
9858
- return matchSorter(preview.items, query2, {
9859
- keys: ["product_title", "variant_title", "variant_sku", "title"]
9860
- });
9861
- }, [preview.items, query2]);
9987
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
9862
9988
  const onSubmit = async () => {
9863
9989
  setIsSubmitting(true);
9864
9990
  let requestSucceeded = false;
9865
9991
  await requestOrderEdit(void 0, {
9866
9992
  onError: (e) => {
9867
- toast.error(`Failed to request order edit: ${e.message}`);
9993
+ toast.error(e.message);
9868
9994
  },
9869
9995
  onSuccess: () => {
9870
9996
  requestSucceeded = true;
@@ -9876,7 +10002,7 @@ const ItemsForm = ({ preview, currencyCode }) => {
9876
10002
  }
9877
10003
  await confirmOrderEdit(void 0, {
9878
10004
  onError: (e) => {
9879
- toast.error(`Failed to confirm order edit: ${e.message}`);
10005
+ toast.error(e.message);
9880
10006
  },
9881
10007
  onSuccess: () => {
9882
10008
  handleSuccess();
@@ -9886,1589 +10012,399 @@ const ItemsForm = ({ preview, currencyCode }) => {
9886
10012
  }
9887
10013
  });
9888
10014
  };
9889
- const onKeyDown = useCallback(
9890
- (e) => {
9891
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
9892
- if (modalContent || isSubmitting) {
9893
- return;
9894
- }
9895
- onSubmit();
9896
- }
9897
- },
9898
- [modalContent, isSubmitting, onSubmit]
9899
- );
9900
- useEffect(() => {
9901
- document.addEventListener("keydown", onKeyDown);
9902
- return () => {
9903
- document.removeEventListener("keydown", onKeyDown);
9904
- };
9905
- }, [onKeyDown]);
9906
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
9907
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
9908
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
9909
- StackedFocusModal,
9910
- {
9911
- id: STACKED_MODAL_ID,
9912
- onOpenChangeCallback: (open) => {
9913
- if (!open) {
9914
- setModalContent(null);
10015
+ if (isError) {
10016
+ throw error;
10017
+ }
10018
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10019
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10020
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10021
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10022
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10023
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10024
+ ] }),
10025
+ /* @__PURE__ */ jsx(
10026
+ Combobox,
10027
+ {
10028
+ id: "promotion-combobox",
10029
+ "aria-describedby": "promotion-combobox-hint",
10030
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
10031
+ fetchNextPage: comboboxData.fetchNextPage,
10032
+ options: comboboxData.options,
10033
+ onSearchValueChange: comboboxData.onSearchValueChange,
10034
+ searchValue: comboboxData.searchValue,
10035
+ disabled: comboboxData.disabled || isAddingPromotions,
10036
+ onChange: add,
10037
+ value: comboboxValue
9915
10038
  }
10039
+ )
10040
+ ] }),
10041
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10042
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10043
+ PromotionItem,
10044
+ {
10045
+ promotion,
10046
+ orderId: preview.id,
10047
+ isLoading: isPending
9916
10048
  },
9917
- children: [
9918
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
9919
- /* @__PURE__ */ jsxs("div", { children: [
9920
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
9921
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order" }) })
9922
- ] }),
9923
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
9924
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
9925
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
9926
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
9927
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
9928
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
9929
- ] }),
9930
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9931
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
9932
- Input,
9933
- {
9934
- type: "search",
9935
- placeholder: "Search items",
9936
- value: searchValue,
9937
- onChange: (e) => onSearchValueChange(e.target.value)
9938
- }
9939
- ) }),
9940
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
9941
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
9942
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
9943
- /* @__PURE__ */ jsx(
9944
- StackedModalTrigger$1,
9945
- {
9946
- type: "add-items",
9947
- setModalContent
9948
- }
9949
- ),
9950
- /* @__PURE__ */ jsx(
9951
- StackedModalTrigger$1,
9952
- {
9953
- type: "add-custom-item",
9954
- setModalContent
9955
- }
9956
- )
9957
- ] })
9958
- ] })
9959
- ] })
9960
- ] }),
9961
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
9962
- /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
9963
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
9964
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
9965
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
9966
- /* @__PURE__ */ jsx("div", {})
9967
- ] }) }),
9968
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ 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: [
9969
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
9970
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
9971
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
9972
- Item,
9973
- {
9974
- item,
9975
- preview,
9976
- currencyCode
9977
- },
9978
- item.id
9979
- )) : /* @__PURE__ */ 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: [
9980
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
9981
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
9982
- 'No items found for "',
9983
- query2,
9984
- '".'
9985
- ] })
9986
- ] }) })
9987
- ] })
9988
- ] }),
9989
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
9990
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
9991
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
9992
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
9993
- Text,
9994
- {
9995
- size: "small",
9996
- leading: "compact",
9997
- className: "text-ui-fg-subtle",
9998
- children: [
9999
- itemCount,
10000
- " ",
10001
- itemCount === 1 ? "item" : "items"
10002
- ]
10003
- }
10004
- ) }),
10005
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10006
- ] })
10007
- ] }) }),
10008
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10009
- CustomItemForm,
10010
- {
10011
- orderId: preview.id,
10012
- currencyCode
10013
- }
10014
- ) : null)
10015
- ]
10016
- }
10017
- ) }),
10018
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10019
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10049
+ promotion.id
10050
+ )) })
10051
+ ] }) }),
10052
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10053
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10020
10054
  /* @__PURE__ */ jsx(
10021
10055
  Button,
10022
10056
  {
10023
10057
  size: "small",
10024
- type: "button",
10025
- onClick: onSubmit,
10026
- isLoading: isSubmitting,
10058
+ type: "submit",
10059
+ isLoading: isSubmitting || isAddingPromotions,
10027
10060
  children: "Save"
10028
10061
  }
10029
10062
  )
10030
10063
  ] }) })
10031
10064
  ] });
10032
10065
  };
10033
- const Item = ({ item, preview, currencyCode }) => {
10034
- if (item.variant_id) {
10035
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10036
- }
10037
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10038
- };
10039
- const VariantItem = ({ item, preview, currencyCode }) => {
10040
- const [editing, setEditing] = useState(false);
10041
- const form = useForm({
10042
- defaultValues: {
10043
- quantity: item.quantity,
10044
- unit_price: item.unit_price
10045
- },
10046
- resolver: zodResolver(variantItemSchema)
10047
- });
10048
- const actionId = useMemo(() => {
10049
- var _a, _b;
10050
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10051
- }, [item]);
10052
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10053
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10054
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10055
- const onSubmit = form.handleSubmit(async (data) => {
10056
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10057
- setEditing(false);
10058
- return;
10059
- }
10060
- if (!actionId) {
10061
- await updateOriginalItem(
10062
- {
10063
- item_id: item.id,
10064
- quantity: data.quantity,
10065
- unit_price: convertNumber(data.unit_price)
10066
- },
10067
- {
10068
- onSuccess: () => {
10069
- setEditing(false);
10070
- },
10071
- onError: (e) => {
10072
- toast.error(e.message);
10073
- }
10074
- }
10075
- );
10076
- return;
10077
- }
10078
- await updateActionItem(
10066
+ const PromotionItem = ({
10067
+ promotion,
10068
+ orderId,
10069
+ isLoading
10070
+ }) => {
10071
+ var _a;
10072
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10073
+ const onRemove = async () => {
10074
+ removePromotions(
10079
10075
  {
10080
- action_id: actionId,
10081
- quantity: data.quantity,
10082
- unit_price: convertNumber(data.unit_price)
10076
+ promo_codes: [promotion.code]
10083
10077
  },
10084
10078
  {
10085
- onSuccess: () => {
10086
- setEditing(false);
10087
- },
10088
10079
  onError: (e) => {
10089
10080
  toast.error(e.message);
10090
10081
  }
10091
10082
  }
10092
10083
  );
10093
- });
10094
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ 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: [
10095
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10096
- /* @__PURE__ */ jsx(
10097
- Thumbnail,
10084
+ };
10085
+ const displayValue = getDisplayValue(promotion);
10086
+ return /* @__PURE__ */ jsxs(
10087
+ "div",
10088
+ {
10089
+ className: clx(
10090
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
10098
10091
  {
10099
- thumbnail: item.thumbnail,
10100
- alt: item.product_title ?? void 0
10092
+ "animate-pulse": isLoading
10101
10093
  }
10102
10094
  ),
10103
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10104
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10105
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10106
- /* @__PURE__ */ jsxs(
10107
- Text,
10108
- {
10109
- size: "small",
10110
- leading: "compact",
10111
- className: "text-ui-fg-subtle",
10112
- children: [
10113
- "(",
10114
- item.variant_title,
10115
- ")"
10116
- ]
10117
- }
10118
- )
10095
+ children: [
10096
+ /* @__PURE__ */ jsxs("div", { children: [
10097
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10098
+ /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
10099
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
10100
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
10101
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
10102
+ ] }),
10103
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10104
+ ] })
10119
10105
  ] }),
10120
10106
  /* @__PURE__ */ jsx(
10121
- Text,
10107
+ IconButton,
10122
10108
  {
10123
10109
  size: "small",
10124
- leading: "compact",
10125
- className: "text-ui-fg-subtle",
10126
- children: item.variant_sku
10110
+ type: "button",
10111
+ variant: "transparent",
10112
+ onClick: onRemove,
10113
+ isLoading: isPending || isLoading,
10114
+ children: /* @__PURE__ */ jsx(XMark, {})
10127
10115
  }
10128
10116
  )
10129
- ] })
10130
- ] }),
10131
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10132
- Form$2.Field,
10133
- {
10134
- control: form.control,
10135
- name: "quantity",
10136
- render: ({ field }) => {
10137
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10138
- }
10139
- }
10140
- ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10141
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10142
- Form$2.Field,
10143
- {
10144
- control: form.control,
10145
- name: "unit_price",
10146
- render: ({ field: { onChange, ...field } }) => {
10147
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10148
- CurrencyInput,
10149
- {
10150
- ...field,
10151
- symbol: getNativeSymbol(currencyCode),
10152
- code: currencyCode,
10153
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10154
- }
10155
- ) }) });
10156
- }
10157
- }
10158
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10159
- /* @__PURE__ */ jsx(
10160
- IconButton,
10161
- {
10162
- type: "button",
10163
- size: "small",
10164
- onClick: editing ? onSubmit : () => {
10165
- setEditing(true);
10166
- },
10167
- disabled: isPending,
10168
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10169
- }
10170
- )
10171
- ] }) }) });
10172
- };
10173
- const variantItemSchema = objectType({
10174
- quantity: numberType(),
10175
- unit_price: unionType([numberType(), stringType()])
10176
- });
10177
- const CustomItem = ({ item, preview, currencyCode }) => {
10178
- const [editing, setEditing] = useState(false);
10179
- const { quantity, unit_price, title } = item;
10180
- const form = useForm({
10181
- defaultValues: {
10182
- title,
10183
- quantity,
10184
- unit_price
10117
+ ]
10185
10118
  },
10186
- resolver: zodResolver(customItemSchema)
10187
- });
10188
- useEffect(() => {
10189
- form.reset({
10190
- title,
10191
- quantity,
10192
- unit_price
10193
- });
10194
- }, [form, title, quantity, unit_price]);
10195
- const actionId = useMemo(() => {
10196
- var _a, _b;
10197
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10198
- }, [item]);
10199
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10200
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10201
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10202
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10203
- const onSubmit = form.handleSubmit(async (data) => {
10204
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10205
- setEditing(false);
10206
- return;
10119
+ promotion.id
10120
+ );
10121
+ };
10122
+ function getDisplayValue(promotion) {
10123
+ var _a, _b, _c, _d;
10124
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10125
+ if (!value) {
10126
+ return null;
10127
+ }
10128
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10129
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10130
+ if (!currency) {
10131
+ return null;
10207
10132
  }
10208
- if (!actionId) {
10209
- await updateOriginalItem(
10210
- {
10211
- item_id: item.id,
10212
- quantity: data.quantity,
10213
- unit_price: convertNumber(data.unit_price)
10214
- },
10215
- {
10216
- onSuccess: () => {
10217
- setEditing(false);
10218
- },
10219
- onError: (e) => {
10220
- toast.error(e.message);
10221
- }
10133
+ return getLocaleAmount(value, currency);
10134
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10135
+ return formatPercentage(value);
10136
+ }
10137
+ return null;
10138
+ }
10139
+ const formatter = new Intl.NumberFormat([], {
10140
+ style: "percent",
10141
+ minimumFractionDigits: 2
10142
+ });
10143
+ const formatPercentage = (value, isPercentageValue = false) => {
10144
+ let val = value || 0;
10145
+ if (!isPercentageValue) {
10146
+ val = val / 100;
10147
+ }
10148
+ return formatter.format(val);
10149
+ };
10150
+ function getPromotionIds(items, shippingMethods) {
10151
+ const promotionIds = /* @__PURE__ */ new Set();
10152
+ for (const item of items) {
10153
+ if (item.adjustments) {
10154
+ for (const adjustment of item.adjustments) {
10155
+ if (adjustment.promotion_id) {
10156
+ promotionIds.add(adjustment.promotion_id);
10222
10157
  }
10223
- );
10224
- return;
10158
+ }
10225
10159
  }
10226
- if (data.quantity === 0) {
10227
- await removeActionItem(actionId, {
10228
- onSuccess: () => {
10229
- setEditing(false);
10230
- },
10231
- onError: (e) => {
10232
- toast.error(e.message);
10160
+ }
10161
+ for (const shippingMethod of shippingMethods) {
10162
+ if (shippingMethod.adjustments) {
10163
+ for (const adjustment of shippingMethod.adjustments) {
10164
+ if (adjustment.promotion_id) {
10165
+ promotionIds.add(adjustment.promotion_id);
10233
10166
  }
10234
- });
10235
- return;
10167
+ }
10236
10168
  }
10237
- await updateActionItem(
10169
+ }
10170
+ return Array.from(promotionIds);
10171
+ }
10172
+ const SalesChannel = () => {
10173
+ const { id } = useParams();
10174
+ const { draft_order, isPending, isError, error } = useDraftOrder(
10175
+ id,
10176
+ {
10177
+ fields: "+sales_channel_id"
10178
+ },
10179
+ {
10180
+ enabled: !!id
10181
+ }
10182
+ );
10183
+ if (isError) {
10184
+ throw error;
10185
+ }
10186
+ const ISrEADY = !!draft_order && !isPending;
10187
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10188
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10189
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
10190
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
10191
+ ] }),
10192
+ ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
10193
+ ] });
10194
+ };
10195
+ const SalesChannelForm = ({ order }) => {
10196
+ const form = useForm({
10197
+ defaultValues: {
10198
+ sales_channel_id: order.sales_channel_id || ""
10199
+ },
10200
+ resolver: zodResolver(schema$2)
10201
+ });
10202
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10203
+ const { handleSuccess } = useRouteModal();
10204
+ const onSubmit = form.handleSubmit(async (data) => {
10205
+ await mutateAsync(
10238
10206
  {
10239
- action_id: actionId,
10240
- quantity: data.quantity,
10241
- unit_price: convertNumber(data.unit_price)
10207
+ sales_channel_id: data.sales_channel_id
10242
10208
  },
10243
10209
  {
10244
10210
  onSuccess: () => {
10245
- setEditing(false);
10211
+ toast.success("Sales channel updated");
10212
+ handleSuccess();
10246
10213
  },
10247
- onError: (e) => {
10248
- toast.error(e.message);
10214
+ onError: (error) => {
10215
+ toast.error(error.message);
10249
10216
  }
10250
10217
  }
10251
10218
  );
10252
10219
  });
10253
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ 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: [
10254
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10255
- /* @__PURE__ */ jsx(
10256
- Thumbnail,
10257
- {
10258
- thumbnail: item.thumbnail,
10259
- alt: item.title ?? void 0
10260
- }
10261
- ),
10262
- editing ? /* @__PURE__ */ jsx(
10263
- Form$2.Field,
10264
- {
10265
- control: form.control,
10266
- name: "title",
10267
- render: ({ field }) => {
10268
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10269
- }
10270
- }
10271
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10272
- ] }),
10273
- editing ? /* @__PURE__ */ jsx(
10274
- Form$2.Field,
10275
- {
10276
- control: form.control,
10277
- name: "quantity",
10278
- render: ({ field }) => {
10279
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10280
- }
10281
- }
10282
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10283
- editing ? /* @__PURE__ */ jsx(
10284
- Form$2.Field,
10285
- {
10286
- control: form.control,
10287
- name: "unit_price",
10288
- render: ({ field: { onChange, ...field } }) => {
10289
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10290
- CurrencyInput,
10220
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10221
+ KeyboundForm,
10222
+ {
10223
+ className: "flex flex-1 flex-col overflow-hidden",
10224
+ onSubmit,
10225
+ children: [
10226
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
10227
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10228
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10229
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10230
+ ] }) })
10231
+ ]
10232
+ }
10233
+ ) });
10234
+ };
10235
+ const SalesChannelField = ({ control, order }) => {
10236
+ const salesChannels = useComboboxData({
10237
+ queryFn: async (params) => {
10238
+ return await sdk.admin.salesChannel.list(params);
10239
+ },
10240
+ queryKey: ["sales-channels"],
10241
+ getOptions: (data) => {
10242
+ return data.sales_channels.map((salesChannel) => ({
10243
+ label: salesChannel.name,
10244
+ value: salesChannel.id
10245
+ }));
10246
+ },
10247
+ defaultValue: order.sales_channel_id || void 0
10248
+ });
10249
+ return /* @__PURE__ */ jsx(
10250
+ Form$2.Field,
10251
+ {
10252
+ control,
10253
+ name: "sales_channel_id",
10254
+ render: ({ field }) => {
10255
+ return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
10256
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
10257
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10258
+ Combobox,
10291
10259
  {
10292
- ...field,
10293
- symbol: getNativeSymbol(currencyCode),
10294
- code: currencyCode,
10295
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10260
+ options: salesChannels.options,
10261
+ fetchNextPage: salesChannels.fetchNextPage,
10262
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
10263
+ searchValue: salesChannels.searchValue,
10264
+ onSearchValueChange: salesChannels.onSearchValueChange,
10265
+ placeholder: "Select sales channel",
10266
+ ...field
10296
10267
  }
10297
- ) }) });
10298
- }
10268
+ ) }),
10269
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10270
+ ] });
10299
10271
  }
10300
- ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10301
- /* @__PURE__ */ jsx(
10302
- IconButton,
10303
- {
10304
- type: "button",
10305
- size: "small",
10306
- onClick: editing ? onSubmit : () => {
10307
- setEditing(true);
10308
- },
10309
- disabled: isPending,
10310
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10311
- }
10312
- )
10313
- ] }) }) });
10272
+ }
10273
+ );
10314
10274
  };
10315
- const StackedModalTrigger$1 = ({
10316
- type,
10317
- setModalContent
10318
- }) => {
10319
- const { setIsOpen } = useStackedModal();
10320
- const onClick = useCallback(() => {
10321
- setModalContent(type);
10322
- setIsOpen(STACKED_MODAL_ID, true);
10323
- }, [setModalContent, setIsOpen, type]);
10324
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10275
+ const schema$2 = objectType({
10276
+ sales_channel_id: stringType().min(1)
10277
+ });
10278
+ function convertNumber(value) {
10279
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10280
+ }
10281
+ const STACKED_FOCUS_MODAL_ID = "shipping-form";
10282
+ const Shipping = () => {
10283
+ var _a;
10284
+ const { id } = useParams();
10285
+ const { order, isPending, isError, error } = useOrder(id, {
10286
+ fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
10287
+ });
10288
+ const {
10289
+ order: preview,
10290
+ isPending: isPreviewPending,
10291
+ isError: isPreviewError,
10292
+ error: previewError
10293
+ } = useOrderPreview(id);
10294
+ useInitiateOrderEdit({ preview });
10295
+ const { onCancel } = useCancelOrderEdit({ preview });
10296
+ if (isError) {
10297
+ throw error;
10298
+ }
10299
+ if (isPreviewError) {
10300
+ throw previewError;
10301
+ }
10302
+ const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
10303
+ const isReady = preview && !isPreviewPending && order && !isPending;
10304
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
10305
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10306
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 py-16 px-6", children: [
10307
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
10308
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
10309
+ ] }) }) }),
10310
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
10311
+ ] }) : isReady ? /* @__PURE__ */ jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxs("div", { children: [
10312
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
10313
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10314
+ ] }) });
10325
10315
  };
10326
- const VARIANT_PREFIX = "items";
10327
- const LIMIT = 50;
10328
- const ExistingItemsForm = ({ orderId, items }) => {
10316
+ const ShippingForm = ({ preview, order }) => {
10317
+ var _a;
10329
10318
  const { setIsOpen } = useStackedModal();
10330
- const [rowSelection, setRowSelection] = useState(
10331
- items.reduce((acc, item) => {
10332
- acc[item.variant_id] = true;
10333
- return acc;
10334
- }, {})
10335
- );
10336
- useEffect(() => {
10337
- setRowSelection(
10338
- items.reduce((acc, item) => {
10339
- if (item.variant_id) {
10340
- acc[item.variant_id] = true;
10341
- }
10342
- return acc;
10343
- }, {})
10344
- );
10345
- }, [items]);
10346
- const { q, order, offset } = useQueryParams(
10347
- ["q", "order", "offset"],
10348
- VARIANT_PREFIX
10349
- );
10350
- const { variants, count, isPending, isError, error } = useProductVariants(
10319
+ const [isSubmitting, setIsSubmitting] = useState(false);
10320
+ const [data, setData] = useState(null);
10321
+ const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
10322
+ const { shipping_options } = useShippingOptions(
10351
10323
  {
10352
- q,
10353
- order,
10354
- offset: offset ? parseInt(offset) : void 0,
10355
- limit: LIMIT
10324
+ id: appliedShippingOptionIds,
10325
+ fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
10356
10326
  },
10357
10327
  {
10358
- placeholderData: keepPreviousData
10328
+ enabled: appliedShippingOptionIds.length > 0
10359
10329
  }
10360
10330
  );
10361
- const columns = useColumns();
10362
- const { mutateAsync } = useDraftOrderAddItems(orderId);
10331
+ const uniqueShippingProfiles = useMemo(() => {
10332
+ const profiles = /* @__PURE__ */ new Map();
10333
+ getUniqueShippingProfiles(order.items).forEach((profile) => {
10334
+ profiles.set(profile.id, profile);
10335
+ });
10336
+ shipping_options == null ? void 0 : shipping_options.forEach((option) => {
10337
+ profiles.set(option.shipping_profile_id, option.shipping_profile);
10338
+ });
10339
+ return Array.from(profiles.values());
10340
+ }, [order.items, shipping_options]);
10341
+ const { handleSuccess } = useRouteModal();
10342
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10343
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10344
+ const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
10345
+ const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
10363
10346
  const onSubmit = async () => {
10364
- const ids = Object.keys(rowSelection).filter(
10365
- (id) => !items.find((i) => i.variant_id === id)
10366
- );
10367
- await mutateAsync(
10368
- {
10369
- items: ids.map((id) => ({
10370
- variant_id: id,
10371
- quantity: 1
10372
- }))
10347
+ setIsSubmitting(true);
10348
+ let requestSucceeded = false;
10349
+ await requestOrderEdit(void 0, {
10350
+ onError: (e) => {
10351
+ toast.error(`Failed to request order edit: ${e.message}`);
10373
10352
  },
10374
- {
10375
- onSuccess: () => {
10376
- setRowSelection({});
10377
- setIsOpen(STACKED_MODAL_ID, false);
10378
- },
10379
- onError: (e) => {
10380
- toast.error(e.message);
10381
- }
10353
+ onSuccess: () => {
10354
+ requestSucceeded = true;
10382
10355
  }
10383
- );
10356
+ });
10357
+ if (!requestSucceeded) {
10358
+ setIsSubmitting(false);
10359
+ return;
10360
+ }
10361
+ await confirmOrderEdit(void 0, {
10362
+ onError: (e) => {
10363
+ toast.error(`Failed to confirm order edit: ${e.message}`);
10364
+ },
10365
+ onSuccess: () => {
10366
+ handleSuccess();
10367
+ },
10368
+ onSettled: () => {
10369
+ setIsSubmitting(false);
10370
+ }
10371
+ });
10384
10372
  };
10385
- if (isError) {
10386
- throw error;
10387
- }
10388
- return /* @__PURE__ */ jsxs(
10389
- StackedFocusModal.Content,
10390
- {
10391
- onOpenAutoFocus: (e) => {
10392
- e.preventDefault();
10393
- const searchInput = document.querySelector(
10394
- "[data-modal-id='modal-search-input']"
10395
- );
10396
- if (searchInput) {
10397
- searchInput.focus();
10373
+ const onKeydown = useCallback(
10374
+ (e) => {
10375
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10376
+ if (data || isSubmitting) {
10377
+ return;
10398
10378
  }
10399
- },
10400
- children: [
10401
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10402
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10403
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10404
- ] }),
10405
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10406
- DataTable,
10407
- {
10408
- data: variants,
10409
- columns,
10410
- isLoading: isPending,
10411
- getRowId: (row) => row.id,
10412
- rowCount: count,
10413
- prefix: VARIANT_PREFIX,
10414
- layout: "fill",
10415
- rowSelection: {
10416
- state: rowSelection,
10417
- onRowSelectionChange: setRowSelection,
10418
- enableRowSelection: (row) => {
10419
- return !items.find((i) => i.variant_id === row.original.id);
10420
- }
10421
- },
10422
- autoFocusSearch: true
10423
- }
10424
- ) }),
10425
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10426
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10427
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10428
- ] }) })
10429
- ]
10430
- }
10379
+ onSubmit();
10380
+ }
10381
+ },
10382
+ [data, isSubmitting, onSubmit]
10431
10383
  );
10432
- };
10433
- const columnHelper = createDataTableColumnHelper();
10434
- const useColumns = () => {
10435
- return useMemo(() => {
10436
- return [
10437
- columnHelper.select(),
10438
- columnHelper.accessor("product.title", {
10439
- header: "Product",
10440
- cell: ({ row }) => {
10441
- var _a, _b, _c;
10442
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10384
+ useEffect(() => {
10385
+ document.addEventListener("keydown", onKeydown);
10386
+ return () => {
10387
+ document.removeEventListener("keydown", onKeydown);
10388
+ };
10389
+ }, [onKeydown]);
10390
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10391
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10392
+ /* @__PURE__ */ jsxs(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: [
10393
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 py-16 px-6", children: [
10394
+ /* @__PURE__ */ jsxs("div", { children: [
10395
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
10396
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose which shipping method(s) to use for the items in the order." }) })
10397
+ ] }),
10398
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10399
+ /* @__PURE__ */ jsx(Accordion.Root, { type: "multiple", children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle rounded-xl shadow-elevation-card-rest", children: [
10400
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 flex items-center justify-between", children: [
10443
10401
  /* @__PURE__ */ jsx(
10444
- Thumbnail,
10402
+ Text,
10445
10403
  {
10446
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10447
- alt: (_b = row.original.product) == null ? void 0 : _b.title
10448
- }
10449
- ),
10450
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10451
- ] });
10452
- },
10453
- enableSorting: true
10454
- }),
10455
- columnHelper.accessor("title", {
10456
- header: "Variant",
10457
- enableSorting: true
10458
- }),
10459
- columnHelper.accessor("sku", {
10460
- header: "SKU",
10461
- cell: ({ getValue }) => {
10462
- return getValue() ?? "-";
10463
- },
10464
- enableSorting: true
10465
- }),
10466
- columnHelper.accessor("updated_at", {
10467
- header: "Updated",
10468
- cell: ({ getValue }) => {
10469
- return /* @__PURE__ */ jsx(
10470
- Tooltip,
10471
- {
10472
- content: getFullDate({ date: getValue(), includeTime: true }),
10473
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10474
- }
10475
- );
10476
- },
10477
- enableSorting: true,
10478
- sortAscLabel: "Oldest first",
10479
- sortDescLabel: "Newest first"
10480
- }),
10481
- columnHelper.accessor("created_at", {
10482
- header: "Created",
10483
- cell: ({ getValue }) => {
10484
- return /* @__PURE__ */ jsx(
10485
- Tooltip,
10486
- {
10487
- content: getFullDate({ date: getValue(), includeTime: true }),
10488
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10489
- }
10490
- );
10491
- },
10492
- enableSorting: true,
10493
- sortAscLabel: "Oldest first",
10494
- sortDescLabel: "Newest first"
10495
- })
10496
- ];
10497
- }, []);
10498
- };
10499
- const CustomItemForm = ({ orderId, currencyCode }) => {
10500
- const { setIsOpen } = useStackedModal();
10501
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10502
- const form = useForm({
10503
- defaultValues: {
10504
- title: "",
10505
- quantity: 1,
10506
- unit_price: ""
10507
- },
10508
- resolver: zodResolver(customItemSchema)
10509
- });
10510
- const onSubmit = form.handleSubmit(async (data) => {
10511
- await addItems(
10512
- {
10513
- items: [
10514
- {
10515
- title: data.title,
10516
- quantity: data.quantity,
10517
- unit_price: convertNumber(data.unit_price)
10518
- }
10519
- ]
10520
- },
10521
- {
10522
- onSuccess: () => {
10523
- setIsOpen(STACKED_MODAL_ID, false);
10524
- },
10525
- onError: (e) => {
10526
- toast.error(e.message);
10527
- }
10528
- }
10529
- );
10530
- });
10531
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10532
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10533
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-2 py-16", children: [
10534
- /* @__PURE__ */ jsxs("div", { children: [
10535
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10536
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(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." }) })
10537
- ] }),
10538
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10539
- /* @__PURE__ */ jsx(
10540
- Form$2.Field,
10541
- {
10542
- control: form.control,
10543
- name: "title",
10544
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10545
- /* @__PURE__ */ jsxs("div", { children: [
10546
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10547
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10548
- ] }),
10549
- /* @__PURE__ */ jsxs("div", { children: [
10550
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10551
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10552
- ] })
10553
- ] }) })
10554
- }
10555
- ),
10556
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10557
- /* @__PURE__ */ jsx(
10558
- Form$2.Field,
10559
- {
10560
- control: form.control,
10561
- name: "unit_price",
10562
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10563
- /* @__PURE__ */ jsxs("div", { children: [
10564
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10565
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10566
- ] }),
10567
- /* @__PURE__ */ jsxs("div", { children: [
10568
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10569
- CurrencyInput,
10570
- {
10571
- symbol: getNativeSymbol(currencyCode),
10572
- code: currencyCode,
10573
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10574
- ...field
10575
- }
10576
- ) }),
10577
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10578
- ] })
10579
- ] }) })
10580
- }
10581
- ),
10582
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10583
- /* @__PURE__ */ jsx(
10584
- Form$2.Field,
10585
- {
10586
- control: form.control,
10587
- name: "quantity",
10588
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10589
- /* @__PURE__ */ jsxs("div", { children: [
10590
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10591
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10592
- ] }),
10593
- /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
10594
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10595
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10596
- ] })
10597
- ] }) })
10598
- }
10599
- )
10600
- ] }) }) }),
10601
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10602
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10603
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10604
- ] }) })
10605
- ] }) }) });
10606
- };
10607
- const customItemSchema = objectType({
10608
- title: stringType().min(1),
10609
- quantity: numberType(),
10610
- unit_price: unionType([numberType(), stringType()])
10611
- });
10612
- const InlineTip = forwardRef(
10613
- ({ variant = "tip", label, className, children, ...props }, ref) => {
10614
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10615
- return /* @__PURE__ */ jsxs(
10616
- "div",
10617
- {
10618
- ref,
10619
- className: clx(
10620
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10621
- className
10622
- ),
10623
- ...props,
10624
- children: [
10625
- /* @__PURE__ */ jsx(
10626
- "div",
10627
- {
10628
- role: "presentation",
10629
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10630
- "bg-ui-tag-orange-icon": variant === "warning"
10631
- })
10632
- }
10633
- ),
10634
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10635
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10636
- labelValue,
10637
- ":"
10638
- ] }),
10639
- " ",
10640
- children
10641
- ] })
10642
- ]
10643
- }
10644
- );
10645
- }
10646
- );
10647
- InlineTip.displayName = "InlineTip";
10648
- const MetadataFieldSchema = objectType({
10649
- key: stringType(),
10650
- disabled: booleanType().optional(),
10651
- value: anyType()
10652
- });
10653
- const MetadataSchema = objectType({
10654
- metadata: arrayType(MetadataFieldSchema)
10655
- });
10656
- const Metadata = () => {
10657
- const { id } = useParams();
10658
- const { order, isPending, isError, error } = useOrder(id, {
10659
- fields: "metadata"
10660
- });
10661
- if (isError) {
10662
- throw error;
10663
- }
10664
- const isReady = !isPending && !!order;
10665
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10666
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10667
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10668
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10669
- ] }),
10670
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10671
- ] });
10672
- };
10673
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10674
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10675
- const MetadataForm = ({ orderId, metadata }) => {
10676
- const { handleSuccess } = useRouteModal();
10677
- const hasUneditableRows = getHasUneditableRows(metadata);
10678
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10679
- const form = useForm({
10680
- defaultValues: {
10681
- metadata: getDefaultValues(metadata)
10682
- },
10683
- resolver: zodResolver(MetadataSchema)
10684
- });
10685
- const handleSubmit = form.handleSubmit(async (data) => {
10686
- const parsedData = parseValues(data);
10687
- await mutateAsync(
10688
- {
10689
- metadata: parsedData
10690
- },
10691
- {
10692
- onSuccess: () => {
10693
- toast.success("Metadata updated");
10694
- handleSuccess();
10695
- },
10696
- onError: (error) => {
10697
- toast.error(error.message);
10698
- }
10699
- }
10700
- );
10701
- });
10702
- const { fields, insert, remove } = useFieldArray({
10703
- control: form.control,
10704
- name: "metadata"
10705
- });
10706
- function deleteRow(index) {
10707
- remove(index);
10708
- if (fields.length === 1) {
10709
- insert(0, {
10710
- key: "",
10711
- value: "",
10712
- disabled: false
10713
- });
10714
- }
10715
- }
10716
- function insertRow(index, position) {
10717
- insert(index + (position === "above" ? 0 : 1), {
10718
- key: "",
10719
- value: "",
10720
- disabled: false
10721
- });
10722
- }
10723
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10724
- KeyboundForm,
10725
- {
10726
- onSubmit: handleSubmit,
10727
- className: "flex flex-1 flex-col overflow-hidden",
10728
- children: [
10729
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10730
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10731
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10732
- /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_KEY_LABEL_ID, children: "Key" }) }),
10733
- /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_VALUE_LABEL_ID, children: "Value" }) })
10734
- ] }),
10735
- fields.map((field, index) => {
10736
- const isDisabled = field.disabled || false;
10737
- let placeholder = "-";
10738
- if (typeof field.value === "object") {
10739
- placeholder = "{ ... }";
10740
- }
10741
- if (Array.isArray(field.value)) {
10742
- placeholder = "[ ... ]";
10743
- }
10744
- return /* @__PURE__ */ jsx(
10745
- ConditionalTooltip,
10746
- {
10747
- showTooltip: isDisabled,
10748
- content: "This row is disabled because it contains non-primitive data.",
10749
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10750
- /* @__PURE__ */ jsxs(
10751
- "div",
10752
- {
10753
- className: clx("grid grid-cols-2 divide-x", {
10754
- "overflow-hidden rounded-b-lg": index === fields.length - 1
10755
- }),
10756
- children: [
10757
- /* @__PURE__ */ jsx(
10758
- Form$2.Field,
10759
- {
10760
- control: form.control,
10761
- name: `metadata.${index}.key`,
10762
- render: ({ field: field2 }) => {
10763
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10764
- GridInput,
10765
- {
10766
- "aria-labelledby": METADATA_KEY_LABEL_ID,
10767
- ...field2,
10768
- disabled: isDisabled,
10769
- placeholder: "Key"
10770
- }
10771
- ) }) });
10772
- }
10773
- }
10774
- ),
10775
- /* @__PURE__ */ jsx(
10776
- Form$2.Field,
10777
- {
10778
- control: form.control,
10779
- name: `metadata.${index}.value`,
10780
- render: ({ field: { value, ...field2 } }) => {
10781
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10782
- GridInput,
10783
- {
10784
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10785
- ...field2,
10786
- value: isDisabled ? placeholder : value,
10787
- disabled: isDisabled,
10788
- placeholder: "Value"
10789
- }
10790
- ) }) });
10791
- }
10792
- }
10793
- )
10794
- ]
10795
- }
10796
- ),
10797
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10798
- /* @__PURE__ */ jsx(
10799
- DropdownMenu.Trigger,
10800
- {
10801
- className: clx(
10802
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10803
- {
10804
- hidden: isDisabled
10805
- }
10806
- ),
10807
- disabled: isDisabled,
10808
- asChild: true,
10809
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10810
- }
10811
- ),
10812
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10813
- /* @__PURE__ */ jsxs(
10814
- DropdownMenu.Item,
10815
- {
10816
- className: "gap-x-2",
10817
- onClick: () => insertRow(index, "above"),
10818
- children: [
10819
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10820
- "Insert row above"
10821
- ]
10822
- }
10823
- ),
10824
- /* @__PURE__ */ jsxs(
10825
- DropdownMenu.Item,
10826
- {
10827
- className: "gap-x-2",
10828
- onClick: () => insertRow(index, "below"),
10829
- children: [
10830
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10831
- "Insert row below"
10832
- ]
10833
- }
10834
- ),
10835
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10836
- /* @__PURE__ */ jsxs(
10837
- DropdownMenu.Item,
10838
- {
10839
- className: "gap-x-2",
10840
- onClick: () => deleteRow(index),
10841
- children: [
10842
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10843
- "Delete row"
10844
- ]
10845
- }
10846
- )
10847
- ] })
10848
- ] })
10849
- ] })
10850
- },
10851
- field.id
10852
- );
10853
- })
10854
- ] }),
10855
- hasUneditableRows && /* @__PURE__ */ 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." })
10856
- ] }),
10857
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10858
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10859
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10860
- ] }) })
10861
- ]
10862
- }
10863
- ) });
10864
- };
10865
- const GridInput = forwardRef(({ className, ...props }, ref) => {
10866
- return /* @__PURE__ */ jsx(
10867
- "input",
10868
- {
10869
- ref,
10870
- ...props,
10871
- autoComplete: "off",
10872
- className: clx(
10873
- "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",
10874
- className
10875
- )
10876
- }
10877
- );
10878
- });
10879
- GridInput.displayName = "MetadataForm.GridInput";
10880
- const PlaceholderInner = () => {
10881
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10882
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10883
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10884
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10885
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10886
- ] }) })
10887
- ] });
10888
- };
10889
- const EDITABLE_TYPES = ["string", "number", "boolean"];
10890
- function getDefaultValues(metadata) {
10891
- if (!metadata || !Object.keys(metadata).length) {
10892
- return [
10893
- {
10894
- key: "",
10895
- value: "",
10896
- disabled: false
10897
- }
10898
- ];
10899
- }
10900
- return Object.entries(metadata).map(([key, value]) => {
10901
- if (!EDITABLE_TYPES.includes(typeof value)) {
10902
- return {
10903
- key,
10904
- value,
10905
- disabled: true
10906
- };
10907
- }
10908
- let stringValue = value;
10909
- if (typeof value !== "string") {
10910
- stringValue = JSON.stringify(value);
10911
- }
10912
- return {
10913
- key,
10914
- value: stringValue,
10915
- original_key: key
10916
- };
10917
- });
10918
- }
10919
- function parseValues(values) {
10920
- const metadata = values.metadata;
10921
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10922
- if (isEmpty) {
10923
- return null;
10924
- }
10925
- const update = {};
10926
- metadata.forEach((field) => {
10927
- let key = field.key;
10928
- let value = field.value;
10929
- const disabled = field.disabled;
10930
- if (!key || !value) {
10931
- return;
10932
- }
10933
- if (disabled) {
10934
- update[key] = value;
10935
- return;
10936
- }
10937
- key = key.trim();
10938
- value = value.trim();
10939
- if (value === "true") {
10940
- update[key] = true;
10941
- } else if (value === "false") {
10942
- update[key] = false;
10943
- } else {
10944
- const parsedNumber = parseFloat(value);
10945
- if (!isNaN(parsedNumber)) {
10946
- update[key] = parsedNumber;
10947
- } else {
10948
- update[key] = value;
10949
- }
10950
- }
10951
- });
10952
- return update;
10953
- }
10954
- function getHasUneditableRows(metadata) {
10955
- if (!metadata) {
10956
- return false;
10957
- }
10958
- return Object.values(metadata).some(
10959
- (value) => !EDITABLE_TYPES.includes(typeof value)
10960
- );
10961
- }
10962
- const PROMOTION_QUERY_KEY = "promotions";
10963
- const promotionsQueryKeys = {
10964
- list: (query2) => [
10965
- PROMOTION_QUERY_KEY,
10966
- query2 ? query2 : void 0
10967
- ],
10968
- detail: (id, query2) => [
10969
- PROMOTION_QUERY_KEY,
10970
- id,
10971
- query2 ? query2 : void 0
10972
- ]
10973
- };
10974
- const usePromotions = (query2, options) => {
10975
- const { data, ...rest } = useQuery({
10976
- queryKey: promotionsQueryKeys.list(query2),
10977
- queryFn: async () => sdk.admin.promotion.list(query2),
10978
- ...options
10979
- });
10980
- return { ...data, ...rest };
10981
- };
10982
- const Promotions = () => {
10983
- const { id } = useParams();
10984
- const {
10985
- order: preview,
10986
- isError: isPreviewError,
10987
- error: previewError
10988
- } = useOrderPreview(id, void 0);
10989
- useInitiateOrderEdit({ preview });
10990
- const { onCancel } = useCancelOrderEdit({ preview });
10991
- if (isPreviewError) {
10992
- throw previewError;
10993
- }
10994
- const isReady = !!preview;
10995
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10996
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10997
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10998
- ] });
10999
- };
11000
- const PromotionForm = ({ preview }) => {
11001
- const { items, shipping_methods } = preview;
11002
- const [isSubmitting, setIsSubmitting] = useState(false);
11003
- const [comboboxValue, setComboboxValue] = useState("");
11004
- const { handleSuccess } = useRouteModal();
11005
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11006
- const promoIds = getPromotionIds(items, shipping_methods);
11007
- const { promotions, isPending, isError, error } = usePromotions(
11008
- {
11009
- id: promoIds
11010
- },
11011
- {
11012
- enabled: !!promoIds.length
11013
- }
11014
- );
11015
- const comboboxData = useComboboxData({
11016
- queryKey: ["promotions", "combobox", promoIds],
11017
- queryFn: async (params) => {
11018
- return await sdk.admin.promotion.list({
11019
- ...params,
11020
- id: {
11021
- $nin: promoIds
11022
- }
11023
- });
11024
- },
11025
- getOptions: (data) => {
11026
- return data.promotions.map((promotion) => ({
11027
- label: promotion.code,
11028
- value: promotion.code
11029
- }));
11030
- }
11031
- });
11032
- const add = async (value) => {
11033
- if (!value) {
11034
- return;
11035
- }
11036
- addPromotions(
11037
- {
11038
- promo_codes: [value]
11039
- },
11040
- {
11041
- onError: (e) => {
11042
- toast.error(e.message);
11043
- comboboxData.onSearchValueChange("");
11044
- setComboboxValue("");
11045
- },
11046
- onSuccess: () => {
11047
- comboboxData.onSearchValueChange("");
11048
- setComboboxValue("");
11049
- }
11050
- }
11051
- );
11052
- };
11053
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11054
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
11055
- const onSubmit = async () => {
11056
- setIsSubmitting(true);
11057
- let requestSucceeded = false;
11058
- await requestOrderEdit(void 0, {
11059
- onError: (e) => {
11060
- toast.error(e.message);
11061
- },
11062
- onSuccess: () => {
11063
- requestSucceeded = true;
11064
- }
11065
- });
11066
- if (!requestSucceeded) {
11067
- setIsSubmitting(false);
11068
- return;
11069
- }
11070
- await confirmOrderEdit(void 0, {
11071
- onError: (e) => {
11072
- toast.error(e.message);
11073
- },
11074
- onSuccess: () => {
11075
- handleSuccess();
11076
- },
11077
- onSettled: () => {
11078
- setIsSubmitting(false);
11079
- }
11080
- });
11081
- };
11082
- if (isError) {
11083
- throw error;
11084
- }
11085
- return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11086
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
11087
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
11088
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11089
- /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
11090
- /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11091
- ] }),
11092
- /* @__PURE__ */ jsx(
11093
- Combobox,
11094
- {
11095
- id: "promotion-combobox",
11096
- "aria-describedby": "promotion-combobox-hint",
11097
- isFetchingNextPage: comboboxData.isFetchingNextPage,
11098
- fetchNextPage: comboboxData.fetchNextPage,
11099
- options: comboboxData.options,
11100
- onSearchValueChange: comboboxData.onSearchValueChange,
11101
- searchValue: comboboxData.searchValue,
11102
- disabled: comboboxData.disabled || isAddingPromotions,
11103
- onChange: add,
11104
- value: comboboxValue
11105
- }
11106
- )
11107
- ] }),
11108
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11109
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
11110
- PromotionItem,
11111
- {
11112
- promotion,
11113
- orderId: preview.id,
11114
- isLoading: isPending
11115
- },
11116
- promotion.id
11117
- )) })
11118
- ] }) }),
11119
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11120
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11121
- /* @__PURE__ */ jsx(
11122
- Button,
11123
- {
11124
- size: "small",
11125
- type: "submit",
11126
- isLoading: isSubmitting || isAddingPromotions,
11127
- children: "Save"
11128
- }
11129
- )
11130
- ] }) })
11131
- ] });
11132
- };
11133
- const PromotionItem = ({
11134
- promotion,
11135
- orderId,
11136
- isLoading
11137
- }) => {
11138
- var _a;
11139
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
11140
- const onRemove = async () => {
11141
- removePromotions(
11142
- {
11143
- promo_codes: [promotion.code]
11144
- },
11145
- {
11146
- onError: (e) => {
11147
- toast.error(e.message);
11148
- }
11149
- }
11150
- );
11151
- };
11152
- const displayValue = getDisplayValue(promotion);
11153
- return /* @__PURE__ */ jsxs(
11154
- "div",
11155
- {
11156
- className: clx(
11157
- "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11158
- {
11159
- "animate-pulse": isLoading
11160
- }
11161
- ),
11162
- children: [
11163
- /* @__PURE__ */ jsxs("div", { children: [
11164
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11165
- /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11166
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11167
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11168
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11169
- ] }),
11170
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11171
- ] })
11172
- ] }),
11173
- /* @__PURE__ */ jsx(
11174
- IconButton,
11175
- {
11176
- size: "small",
11177
- type: "button",
11178
- variant: "transparent",
11179
- onClick: onRemove,
11180
- isLoading: isPending || isLoading,
11181
- children: /* @__PURE__ */ jsx(XMark, {})
11182
- }
11183
- )
11184
- ]
11185
- },
11186
- promotion.id
11187
- );
11188
- };
11189
- function getDisplayValue(promotion) {
11190
- var _a, _b, _c, _d;
11191
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11192
- if (!value) {
11193
- return null;
11194
- }
11195
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11196
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11197
- if (!currency) {
11198
- return null;
11199
- }
11200
- return getLocaleAmount(value, currency);
11201
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11202
- return formatPercentage(value);
11203
- }
11204
- return null;
11205
- }
11206
- const formatter = new Intl.NumberFormat([], {
11207
- style: "percent",
11208
- minimumFractionDigits: 2
11209
- });
11210
- const formatPercentage = (value, isPercentageValue = false) => {
11211
- let val = value || 0;
11212
- if (!isPercentageValue) {
11213
- val = val / 100;
11214
- }
11215
- return formatter.format(val);
11216
- };
11217
- function getPromotionIds(items, shippingMethods) {
11218
- const promotionIds = /* @__PURE__ */ new Set();
11219
- for (const item of items) {
11220
- if (item.adjustments) {
11221
- for (const adjustment of item.adjustments) {
11222
- if (adjustment.promotion_id) {
11223
- promotionIds.add(adjustment.promotion_id);
11224
- }
11225
- }
11226
- }
11227
- }
11228
- for (const shippingMethod of shippingMethods) {
11229
- if (shippingMethod.adjustments) {
11230
- for (const adjustment of shippingMethod.adjustments) {
11231
- if (adjustment.promotion_id) {
11232
- promotionIds.add(adjustment.promotion_id);
11233
- }
11234
- }
11235
- }
11236
- }
11237
- return Array.from(promotionIds);
11238
- }
11239
- const SalesChannel = () => {
11240
- const { id } = useParams();
11241
- const { draft_order, isPending, isError, error } = useDraftOrder(
11242
- id,
11243
- {
11244
- fields: "+sales_channel_id"
11245
- },
11246
- {
11247
- enabled: !!id
11248
- }
11249
- );
11250
- if (isError) {
11251
- throw error;
11252
- }
11253
- const ISrEADY = !!draft_order && !isPending;
11254
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11255
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11256
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
11257
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
11258
- ] }),
11259
- ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
11260
- ] });
11261
- };
11262
- const SalesChannelForm = ({ order }) => {
11263
- const form = useForm({
11264
- defaultValues: {
11265
- sales_channel_id: order.sales_channel_id || ""
11266
- },
11267
- resolver: zodResolver(schema$4)
11268
- });
11269
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11270
- const { handleSuccess } = useRouteModal();
11271
- const onSubmit = form.handleSubmit(async (data) => {
11272
- await mutateAsync(
11273
- {
11274
- sales_channel_id: data.sales_channel_id
11275
- },
11276
- {
11277
- onSuccess: () => {
11278
- toast.success("Sales channel updated");
11279
- handleSuccess();
11280
- },
11281
- onError: (error) => {
11282
- toast.error(error.message);
11283
- }
11284
- }
11285
- );
11286
- });
11287
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11288
- KeyboundForm,
11289
- {
11290
- className: "flex flex-1 flex-col overflow-hidden",
11291
- onSubmit,
11292
- children: [
11293
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
11294
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11295
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11296
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11297
- ] }) })
11298
- ]
11299
- }
11300
- ) });
11301
- };
11302
- const SalesChannelField = ({ control, order }) => {
11303
- const salesChannels = useComboboxData({
11304
- queryFn: async (params) => {
11305
- return await sdk.admin.salesChannel.list(params);
11306
- },
11307
- queryKey: ["sales-channels"],
11308
- getOptions: (data) => {
11309
- return data.sales_channels.map((salesChannel) => ({
11310
- label: salesChannel.name,
11311
- value: salesChannel.id
11312
- }));
11313
- },
11314
- defaultValue: order.sales_channel_id || void 0
11315
- });
11316
- return /* @__PURE__ */ jsx(
11317
- Form$2.Field,
11318
- {
11319
- control,
11320
- name: "sales_channel_id",
11321
- render: ({ field }) => {
11322
- return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11323
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
11324
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11325
- Combobox,
11326
- {
11327
- options: salesChannels.options,
11328
- fetchNextPage: salesChannels.fetchNextPage,
11329
- isFetchingNextPage: salesChannels.isFetchingNextPage,
11330
- searchValue: salesChannels.searchValue,
11331
- onSearchValueChange: salesChannels.onSearchValueChange,
11332
- placeholder: "Select sales channel",
11333
- ...field
11334
- }
11335
- ) }),
11336
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11337
- ] });
11338
- }
11339
- }
11340
- );
11341
- };
11342
- const schema$4 = objectType({
11343
- sales_channel_id: stringType().min(1)
11344
- });
11345
- const STACKED_FOCUS_MODAL_ID = "shipping-form";
11346
- const Shipping = () => {
11347
- var _a;
11348
- const { id } = useParams();
11349
- const { order, isPending, isError, error } = useOrder(id, {
11350
- fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
11351
- });
11352
- const {
11353
- order: preview,
11354
- isPending: isPreviewPending,
11355
- isError: isPreviewError,
11356
- error: previewError
11357
- } = useOrderPreview(id);
11358
- useInitiateOrderEdit({ preview });
11359
- const { onCancel } = useCancelOrderEdit({ preview });
11360
- if (isError) {
11361
- throw error;
11362
- }
11363
- if (isPreviewError) {
11364
- throw previewError;
11365
- }
11366
- const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
11367
- const isReady = preview && !isPreviewPending && order && !isPending;
11368
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
11369
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
11370
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 py-16 px-6", children: [
11371
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
11372
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
11373
- ] }) }) }),
11374
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
11375
- ] }) : isReady ? /* @__PURE__ */ jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxs("div", { children: [
11376
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
11377
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
11378
- ] }) });
11379
- };
11380
- const ShippingForm = ({ preview, order }) => {
11381
- var _a;
11382
- const { setIsOpen } = useStackedModal();
11383
- const [isSubmitting, setIsSubmitting] = useState(false);
11384
- const [data, setData] = useState(null);
11385
- const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
11386
- const { shipping_options } = useShippingOptions(
11387
- {
11388
- id: appliedShippingOptionIds,
11389
- fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
11390
- },
11391
- {
11392
- enabled: appliedShippingOptionIds.length > 0
11393
- }
11394
- );
11395
- const uniqueShippingProfiles = useMemo(() => {
11396
- const profiles = /* @__PURE__ */ new Map();
11397
- getUniqueShippingProfiles(order.items).forEach((profile) => {
11398
- profiles.set(profile.id, profile);
11399
- });
11400
- shipping_options == null ? void 0 : shipping_options.forEach((option) => {
11401
- profiles.set(option.shipping_profile_id, option.shipping_profile);
11402
- });
11403
- return Array.from(profiles.values());
11404
- }, [order.items, shipping_options]);
11405
- const { handleSuccess } = useRouteModal();
11406
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11407
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
11408
- const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
11409
- const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
11410
- const onSubmit = async () => {
11411
- setIsSubmitting(true);
11412
- let requestSucceeded = false;
11413
- await requestOrderEdit(void 0, {
11414
- onError: (e) => {
11415
- toast.error(`Failed to request order edit: ${e.message}`);
11416
- },
11417
- onSuccess: () => {
11418
- requestSucceeded = true;
11419
- }
11420
- });
11421
- if (!requestSucceeded) {
11422
- setIsSubmitting(false);
11423
- return;
11424
- }
11425
- await confirmOrderEdit(void 0, {
11426
- onError: (e) => {
11427
- toast.error(`Failed to confirm order edit: ${e.message}`);
11428
- },
11429
- onSuccess: () => {
11430
- handleSuccess();
11431
- },
11432
- onSettled: () => {
11433
- setIsSubmitting(false);
11434
- }
11435
- });
11436
- };
11437
- const onKeydown = useCallback(
11438
- (e) => {
11439
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11440
- if (data || isSubmitting) {
11441
- return;
11442
- }
11443
- onSubmit();
11444
- }
11445
- },
11446
- [data, isSubmitting, onSubmit]
11447
- );
11448
- useEffect(() => {
11449
- document.addEventListener("keydown", onKeydown);
11450
- return () => {
11451
- document.removeEventListener("keydown", onKeydown);
11452
- };
11453
- }, [onKeydown]);
11454
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
11455
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
11456
- /* @__PURE__ */ jsxs(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: [
11457
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 py-16 px-6", children: [
11458
- /* @__PURE__ */ jsxs("div", { children: [
11459
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
11460
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose which shipping method(s) to use for the items in the order." }) })
11461
- ] }),
11462
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11463
- /* @__PURE__ */ jsx(Accordion.Root, { type: "multiple", children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle rounded-xl shadow-elevation-card-rest", children: [
11464
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 flex items-center justify-between", children: [
11465
- /* @__PURE__ */ jsx(
11466
- Text,
11467
- {
11468
- size: "xsmall",
11469
- weight: "plus",
11470
- className: "text-ui-fg-muted",
11471
- children: "Shipping profile"
10404
+ size: "xsmall",
10405
+ weight: "plus",
10406
+ className: "text-ui-fg-muted",
10407
+ children: "Shipping profile"
11472
10408
  }
11473
10409
  ),
11474
10410
  /* @__PURE__ */ jsx(
@@ -11649,7 +10585,7 @@ const ShippingForm = ({ preview, order }) => {
11649
10585
  ]
11650
10586
  }
11651
10587
  ) : /* @__PURE__ */ jsx(
11652
- StackedModalTrigger,
10588
+ StackedModalTrigger$1,
11653
10589
  {
11654
10590
  shippingProfileId: profile.id,
11655
10591
  shippingOption,
@@ -11760,7 +10696,7 @@ const ShippingForm = ({ preview, order }) => {
11760
10696
  ] }) })
11761
10697
  ] });
11762
10698
  };
11763
- const StackedModalTrigger = ({
10699
+ const StackedModalTrigger$1 = ({
11764
10700
  shippingProfileId,
11765
10701
  shippingOption,
11766
10702
  shippingMethod,
@@ -12181,7 +11117,7 @@ const ShippingAddressForm = ({ order }) => {
12181
11117
  postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12182
11118
  phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12183
11119
  },
12184
- resolver: zodResolver(schema$3)
11120
+ resolver: zodResolver(schema$1)
12185
11121
  });
12186
11122
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12187
11123
  const { handleSuccess } = useRouteModal();
@@ -12351,7 +11287,7 @@ const ShippingAddressForm = ({ order }) => {
12351
11287
  }
12352
11288
  ) });
12353
11289
  };
12354
- const schema$3 = addressSchema;
11290
+ const schema$1 = addressSchema;
12355
11291
  const TransferOwnership = () => {
12356
11292
  const { id } = useParams();
12357
11293
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -12375,7 +11311,7 @@ const TransferOwnershipForm = ({ order }) => {
12375
11311
  defaultValues: {
12376
11312
  customer_id: order.customer_id || ""
12377
11313
  },
12378
- resolver: zodResolver(schema$2)
11314
+ resolver: zodResolver(schema)
12379
11315
  });
12380
11316
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12381
11317
  const { handleSuccess } = useRouteModal();
@@ -12701,137 +11637,1106 @@ const Illustration = () => {
12701
11637
  /* @__PURE__ */ jsx(
12702
11638
  "path",
12703
11639
  {
12704
- d: "M104.562 57.0927C103.13 56.265 100.792 56.2515 99.3501 57.0626C97.9081 57.8738 97.9004 59.2065 99.333 60.0343C100.766 60.862 103.103 60.8754 104.545 60.0643C105.987 59.2532 105.995 57.9204 104.562 57.0927ZM103.858 58.8972L100.815 59.1265C100.683 59.1367 100.55 59.1134 100.449 59.063C100.44 59.0585 100.432 59.0545 100.425 59.05C100.339 59.0005 100.29 58.9336 100.291 58.8637L100.294 58.1201C100.294 57.9752 100.501 57.8585 100.756 57.86C101.01 57.8615 101.217 57.98 101.216 58.1256L101.214 58.5669L103.732 58.3769C103.984 58.3578 104.217 58.4584 104.251 58.603C104.286 58.7468 104.11 58.8788 103.858 58.8977L103.858 58.8972Z",
12705
- fill: "#52525B"
12706
- }
11640
+ d: "M104.562 57.0927C103.13 56.265 100.792 56.2515 99.3501 57.0626C97.9081 57.8738 97.9004 59.2065 99.333 60.0343C100.766 60.862 103.103 60.8754 104.545 60.0643C105.987 59.2532 105.995 57.9204 104.562 57.0927ZM103.858 58.8972L100.815 59.1265C100.683 59.1367 100.55 59.1134 100.449 59.063C100.44 59.0585 100.432 59.0545 100.425 59.05C100.339 59.0005 100.29 58.9336 100.291 58.8637L100.294 58.1201C100.294 57.9752 100.501 57.8585 100.756 57.86C101.01 57.8615 101.217 57.98 101.216 58.1256L101.214 58.5669L103.732 58.3769C103.984 58.3578 104.217 58.4584 104.251 58.603C104.286 58.7468 104.11 58.8788 103.858 58.8977L103.858 58.8972Z",
11641
+ fill: "#52525B"
11642
+ }
11643
+ ),
11644
+ /* @__PURE__ */ jsx("g", { clipPath: "url(#clip0_20915_38670)", children: /* @__PURE__ */ jsx(
11645
+ "path",
11646
+ {
11647
+ d: "M133.106 81.8022L140.49 81.8447L140.515 77.6349",
11648
+ stroke: "#A1A1AA",
11649
+ strokeWidth: "1.5",
11650
+ strokeLinecap: "round",
11651
+ strokeLinejoin: "round"
11652
+ }
11653
+ ) }),
11654
+ /* @__PURE__ */ jsx("g", { clipPath: "url(#clip1_20915_38670)", children: /* @__PURE__ */ jsx(
11655
+ "path",
11656
+ {
11657
+ d: "M143.496 87.8055L150.881 87.8481L150.905 83.6383",
11658
+ stroke: "#A1A1AA",
11659
+ strokeWidth: "1.5",
11660
+ strokeLinecap: "round",
11661
+ strokeLinejoin: "round"
11662
+ }
11663
+ ) }),
11664
+ /* @__PURE__ */ jsx("g", { clipPath: "url(#clip2_20915_38670)", children: /* @__PURE__ */ jsx(
11665
+ "path",
11666
+ {
11667
+ d: "M153.887 93.8088L161.271 93.8514L161.295 89.6416",
11668
+ stroke: "#A1A1AA",
11669
+ strokeWidth: "1.5",
11670
+ strokeLinecap: "round",
11671
+ strokeLinejoin: "round"
11672
+ }
11673
+ ) }),
11674
+ /* @__PURE__ */ jsx("g", { clipPath: "url(#clip3_20915_38670)", children: /* @__PURE__ */ jsx(
11675
+ "path",
11676
+ {
11677
+ d: "M126.114 89.1912L118.729 89.1486L118.705 93.3584",
11678
+ stroke: "#A1A1AA",
11679
+ strokeWidth: "1.5",
11680
+ strokeLinecap: "round",
11681
+ strokeLinejoin: "round"
11682
+ }
11683
+ ) }),
11684
+ /* @__PURE__ */ jsx("g", { clipPath: "url(#clip4_20915_38670)", children: /* @__PURE__ */ jsx(
11685
+ "path",
11686
+ {
11687
+ d: "M136.504 95.1945L129.12 95.1519L129.095 99.3617",
11688
+ stroke: "#A1A1AA",
11689
+ strokeWidth: "1.5",
11690
+ strokeLinecap: "round",
11691
+ strokeLinejoin: "round"
11692
+ }
11693
+ ) }),
11694
+ /* @__PURE__ */ jsx("g", { clipPath: "url(#clip5_20915_38670)", children: /* @__PURE__ */ jsx(
11695
+ "path",
11696
+ {
11697
+ d: "M146.894 101.198L139.51 101.155L139.486 105.365",
11698
+ stroke: "#A1A1AA",
11699
+ strokeWidth: "1.5",
11700
+ strokeLinecap: "round",
11701
+ strokeLinejoin: "round"
11702
+ }
11703
+ ) }),
11704
+ /* @__PURE__ */ jsxs("defs", { children: [
11705
+ /* @__PURE__ */ jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsx(
11706
+ "rect",
11707
+ {
11708
+ width: "12",
11709
+ height: "12",
11710
+ fill: "white",
11711
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
11712
+ }
11713
+ ) }),
11714
+ /* @__PURE__ */ jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsx(
11715
+ "rect",
11716
+ {
11717
+ width: "12",
11718
+ height: "12",
11719
+ fill: "white",
11720
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
11721
+ }
11722
+ ) }),
11723
+ /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
11724
+ "rect",
11725
+ {
11726
+ width: "12",
11727
+ height: "12",
11728
+ fill: "white",
11729
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
11730
+ }
11731
+ ) }),
11732
+ /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
11733
+ "rect",
11734
+ {
11735
+ width: "12",
11736
+ height: "12",
11737
+ fill: "white",
11738
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
11739
+ }
11740
+ ) }),
11741
+ /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
11742
+ "rect",
11743
+ {
11744
+ width: "12",
11745
+ height: "12",
11746
+ fill: "white",
11747
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
11748
+ }
11749
+ ) }),
11750
+ /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
11751
+ "rect",
11752
+ {
11753
+ width: "12",
11754
+ height: "12",
11755
+ fill: "white",
11756
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
11757
+ }
11758
+ ) })
11759
+ ] })
11760
+ ]
11761
+ }
11762
+ );
11763
+ };
11764
+ const schema = objectType({
11765
+ customer_id: stringType().min(1)
11766
+ });
11767
+ const NumberInput = forwardRef(
11768
+ ({
11769
+ value,
11770
+ onChange,
11771
+ size = "base",
11772
+ min = 0,
11773
+ max = 100,
11774
+ step = 1,
11775
+ className,
11776
+ disabled,
11777
+ ...props
11778
+ }, ref) => {
11779
+ const handleChange = (event) => {
11780
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
11781
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
11782
+ onChange(newValue);
11783
+ }
11784
+ };
11785
+ const handleIncrement = () => {
11786
+ const newValue = value + step;
11787
+ if (max === void 0 || newValue <= max) {
11788
+ onChange(newValue);
11789
+ }
11790
+ };
11791
+ const handleDecrement = () => {
11792
+ const newValue = value - step;
11793
+ if (min === void 0 || newValue >= min) {
11794
+ onChange(newValue);
11795
+ }
11796
+ };
11797
+ return /* @__PURE__ */ jsxs(
11798
+ "div",
11799
+ {
11800
+ className: clx(
11801
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
11802
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
11803
+ {
11804
+ "h-7": size === "small",
11805
+ "h-8": size === "base"
11806
+ },
11807
+ className
12707
11808
  ),
12708
- /* @__PURE__ */ jsx("g", { clipPath: "url(#clip0_20915_38670)", children: /* @__PURE__ */ jsx(
12709
- "path",
12710
- {
12711
- d: "M133.106 81.8022L140.49 81.8447L140.515 77.6349",
12712
- stroke: "#A1A1AA",
12713
- strokeWidth: "1.5",
12714
- strokeLinecap: "round",
12715
- strokeLinejoin: "round"
11809
+ children: [
11810
+ /* @__PURE__ */ jsx(
11811
+ "input",
11812
+ {
11813
+ ref,
11814
+ type: "number",
11815
+ value,
11816
+ onChange: handleChange,
11817
+ min,
11818
+ max,
11819
+ step,
11820
+ className: clx(
11821
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
11822
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
11823
+ "placeholder:text-ui-fg-muted"
11824
+ ),
11825
+ ...props
11826
+ }
11827
+ ),
11828
+ /* @__PURE__ */ jsxs(
11829
+ "button",
11830
+ {
11831
+ className: clx(
11832
+ "flex items-center justify-center outline-none transition-fg",
11833
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
11834
+ "focus:bg-ui-bg-field-component-hover",
11835
+ "hover:bg-ui-bg-field-component-hover",
11836
+ {
11837
+ "size-7": size === "small",
11838
+ "size-8": size === "base"
11839
+ }
11840
+ ),
11841
+ type: "button",
11842
+ onClick: handleDecrement,
11843
+ disabled: min !== void 0 && value <= min || disabled,
11844
+ children: [
11845
+ /* @__PURE__ */ jsx(Minus, {}),
11846
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
11847
+ ]
11848
+ }
11849
+ ),
11850
+ /* @__PURE__ */ jsxs(
11851
+ "button",
11852
+ {
11853
+ className: clx(
11854
+ "flex items-center justify-center outline-none transition-fg",
11855
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
11856
+ "focus:bg-ui-bg-field-hover",
11857
+ "hover:bg-ui-bg-field-hover",
11858
+ {
11859
+ "size-7": size === "small",
11860
+ "size-8": size === "base"
11861
+ }
11862
+ ),
11863
+ type: "button",
11864
+ onClick: handleIncrement,
11865
+ disabled: max !== void 0 && value >= max || disabled,
11866
+ children: [
11867
+ /* @__PURE__ */ jsx(Plus, {}),
11868
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
11869
+ ]
11870
+ }
11871
+ )
11872
+ ]
11873
+ }
11874
+ );
11875
+ }
11876
+ );
11877
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
11878
+ const productVariantsQueryKeys = {
11879
+ list: (query2) => [
11880
+ PRODUCT_VARIANTS_QUERY_KEY,
11881
+ query2 ? query2 : void 0
11882
+ ]
11883
+ };
11884
+ const useProductVariants = (query2, options) => {
11885
+ const { data, ...rest } = useQuery({
11886
+ queryKey: productVariantsQueryKeys.list(query2),
11887
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
11888
+ ...options
11889
+ });
11890
+ return { ...data, ...rest };
11891
+ };
11892
+ const STACKED_MODAL_ID = "items_stacked_modal";
11893
+ const Items = () => {
11894
+ const { id } = useParams();
11895
+ const {
11896
+ order: preview,
11897
+ isPending: isPreviewPending,
11898
+ isError: isPreviewError,
11899
+ error: previewError
11900
+ } = useOrderPreview(id, void 0, {
11901
+ placeholderData: keepPreviousData
11902
+ });
11903
+ useInitiateOrderEdit({ preview });
11904
+ const { draft_order, isPending, isError, error } = useDraftOrder(
11905
+ id,
11906
+ {
11907
+ fields: "currency_code"
11908
+ },
11909
+ {
11910
+ enabled: !!id
11911
+ }
11912
+ );
11913
+ const { onCancel } = useCancelOrderEdit({ preview });
11914
+ if (isError) {
11915
+ throw error;
11916
+ }
11917
+ if (isPreviewError) {
11918
+ throw previewError;
11919
+ }
11920
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
11921
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
11922
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
11923
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
11924
+ ] }) });
11925
+ };
11926
+ const ItemsForm = ({ preview, currencyCode }) => {
11927
+ var _a;
11928
+ const [isSubmitting, setIsSubmitting] = useState(false);
11929
+ const [modalContent, setModalContent] = useState(
11930
+ null
11931
+ );
11932
+ const { handleSuccess } = useRouteModal();
11933
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
11934
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11935
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
11936
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
11937
+ const matches = useMemo(() => {
11938
+ return matchSorter(preview.items, query2, {
11939
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
11940
+ });
11941
+ }, [preview.items, query2]);
11942
+ const onSubmit = async () => {
11943
+ setIsSubmitting(true);
11944
+ let requestSucceeded = false;
11945
+ await requestOrderEdit(void 0, {
11946
+ onError: (e) => {
11947
+ toast.error(`Failed to request order edit: ${e.message}`);
11948
+ },
11949
+ onSuccess: () => {
11950
+ requestSucceeded = true;
11951
+ }
11952
+ });
11953
+ if (!requestSucceeded) {
11954
+ setIsSubmitting(false);
11955
+ return;
11956
+ }
11957
+ await confirmOrderEdit(void 0, {
11958
+ onError: (e) => {
11959
+ toast.error(`Failed to confirm order edit: ${e.message}`);
11960
+ },
11961
+ onSuccess: () => {
11962
+ handleSuccess();
11963
+ },
11964
+ onSettled: () => {
11965
+ setIsSubmitting(false);
11966
+ }
11967
+ });
11968
+ };
11969
+ const onKeyDown = useCallback(
11970
+ (e) => {
11971
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11972
+ if (modalContent || isSubmitting) {
11973
+ return;
11974
+ }
11975
+ onSubmit();
11976
+ }
11977
+ },
11978
+ [modalContent, isSubmitting, onSubmit]
11979
+ );
11980
+ useEffect(() => {
11981
+ document.addEventListener("keydown", onKeyDown);
11982
+ return () => {
11983
+ document.removeEventListener("keydown", onKeyDown);
11984
+ };
11985
+ }, [onKeyDown]);
11986
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
11987
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
11988
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
11989
+ StackedFocusModal,
11990
+ {
11991
+ id: STACKED_MODAL_ID,
11992
+ onOpenChangeCallback: (open) => {
11993
+ if (!open) {
11994
+ setModalContent(null);
12716
11995
  }
12717
- ) }),
12718
- /* @__PURE__ */ jsx("g", { clipPath: "url(#clip1_20915_38670)", children: /* @__PURE__ */ jsx(
12719
- "path",
12720
- {
12721
- d: "M143.496 87.8055L150.881 87.8481L150.905 83.6383",
12722
- stroke: "#A1A1AA",
12723
- strokeWidth: "1.5",
12724
- strokeLinecap: "round",
12725
- strokeLinejoin: "round"
11996
+ },
11997
+ children: [
11998
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
11999
+ /* @__PURE__ */ jsxs("div", { children: [
12000
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
12001
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order" }) })
12002
+ ] }),
12003
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12004
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
12005
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
12006
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12007
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
12008
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
12009
+ ] }),
12010
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
12011
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
12012
+ Input,
12013
+ {
12014
+ type: "search",
12015
+ placeholder: "Search items",
12016
+ value: searchValue,
12017
+ onChange: (e) => onSearchValueChange(e.target.value)
12018
+ }
12019
+ ) }),
12020
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
12021
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
12022
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
12023
+ /* @__PURE__ */ jsx(
12024
+ StackedModalTrigger,
12025
+ {
12026
+ type: "add-items",
12027
+ setModalContent
12028
+ }
12029
+ ),
12030
+ /* @__PURE__ */ jsx(
12031
+ StackedModalTrigger,
12032
+ {
12033
+ type: "add-custom-item",
12034
+ setModalContent
12035
+ }
12036
+ )
12037
+ ] })
12038
+ ] })
12039
+ ] })
12040
+ ] }),
12041
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
12042
+ /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
12043
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
12044
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
12045
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
12046
+ /* @__PURE__ */ jsx("div", {})
12047
+ ] }) }),
12048
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ 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: [
12049
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
12050
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
12051
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
12052
+ Item,
12053
+ {
12054
+ item,
12055
+ preview,
12056
+ currencyCode
12057
+ },
12058
+ item.id
12059
+ )) : /* @__PURE__ */ 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: [
12060
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
12061
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
12062
+ 'No items found for "',
12063
+ query2,
12064
+ '".'
12065
+ ] })
12066
+ ] }) })
12067
+ ] })
12068
+ ] }),
12069
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12070
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
12071
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
12072
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
12073
+ Text,
12074
+ {
12075
+ size: "small",
12076
+ leading: "compact",
12077
+ className: "text-ui-fg-subtle",
12078
+ children: [
12079
+ itemCount,
12080
+ " ",
12081
+ itemCount === 1 ? "item" : "items"
12082
+ ]
12083
+ }
12084
+ ) }),
12085
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
12086
+ ] })
12087
+ ] }) }),
12088
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
12089
+ CustomItemForm,
12090
+ {
12091
+ orderId: preview.id,
12092
+ currencyCode
12093
+ }
12094
+ ) : null)
12095
+ ]
12096
+ }
12097
+ ) }),
12098
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12099
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12100
+ /* @__PURE__ */ jsx(
12101
+ Button,
12102
+ {
12103
+ size: "small",
12104
+ type: "button",
12105
+ onClick: onSubmit,
12106
+ isLoading: isSubmitting,
12107
+ children: "Save"
12108
+ }
12109
+ )
12110
+ ] }) })
12111
+ ] });
12112
+ };
12113
+ const Item = ({ item, preview, currencyCode }) => {
12114
+ if (item.variant_id) {
12115
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
12116
+ }
12117
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
12118
+ };
12119
+ const VariantItem = ({ item, preview, currencyCode }) => {
12120
+ const [editing, setEditing] = useState(false);
12121
+ const form = useForm({
12122
+ defaultValues: {
12123
+ quantity: item.quantity,
12124
+ unit_price: item.unit_price
12125
+ },
12126
+ resolver: zodResolver(variantItemSchema)
12127
+ });
12128
+ const actionId = useMemo(() => {
12129
+ var _a, _b;
12130
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12131
+ }, [item]);
12132
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12133
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12134
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12135
+ const onSubmit = form.handleSubmit(async (data) => {
12136
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
12137
+ setEditing(false);
12138
+ return;
12139
+ }
12140
+ if (!actionId) {
12141
+ await updateOriginalItem(
12142
+ {
12143
+ item_id: item.id,
12144
+ quantity: data.quantity,
12145
+ unit_price: convertNumber(data.unit_price)
12146
+ },
12147
+ {
12148
+ onSuccess: () => {
12149
+ setEditing(false);
12150
+ },
12151
+ onError: (e) => {
12152
+ toast.error(e.message);
12726
12153
  }
12727
- ) }),
12728
- /* @__PURE__ */ jsx("g", { clipPath: "url(#clip2_20915_38670)", children: /* @__PURE__ */ jsx(
12729
- "path",
12154
+ }
12155
+ );
12156
+ return;
12157
+ }
12158
+ await updateActionItem(
12159
+ {
12160
+ action_id: actionId,
12161
+ quantity: data.quantity,
12162
+ unit_price: convertNumber(data.unit_price)
12163
+ },
12164
+ {
12165
+ onSuccess: () => {
12166
+ setEditing(false);
12167
+ },
12168
+ onError: (e) => {
12169
+ toast.error(e.message);
12170
+ }
12171
+ }
12172
+ );
12173
+ });
12174
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ 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: [
12175
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
12176
+ /* @__PURE__ */ jsx(
12177
+ Thumbnail,
12178
+ {
12179
+ thumbnail: item.thumbnail,
12180
+ alt: item.product_title ?? void 0
12181
+ }
12182
+ ),
12183
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12184
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
12185
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
12186
+ /* @__PURE__ */ jsxs(
12187
+ Text,
12188
+ {
12189
+ size: "small",
12190
+ leading: "compact",
12191
+ className: "text-ui-fg-subtle",
12192
+ children: [
12193
+ "(",
12194
+ item.variant_title,
12195
+ ")"
12196
+ ]
12197
+ }
12198
+ )
12199
+ ] }),
12200
+ /* @__PURE__ */ jsx(
12201
+ Text,
12730
12202
  {
12731
- d: "M153.887 93.8088L161.271 93.8514L161.295 89.6416",
12732
- stroke: "#A1A1AA",
12733
- strokeWidth: "1.5",
12734
- strokeLinecap: "round",
12735
- strokeLinejoin: "round"
12203
+ size: "small",
12204
+ leading: "compact",
12205
+ className: "text-ui-fg-subtle",
12206
+ children: item.variant_sku
12736
12207
  }
12737
- ) }),
12738
- /* @__PURE__ */ jsx("g", { clipPath: "url(#clip3_20915_38670)", children: /* @__PURE__ */ jsx(
12739
- "path",
12740
- {
12741
- d: "M126.114 89.1912L118.729 89.1486L118.705 93.3584",
12742
- stroke: "#A1A1AA",
12743
- strokeWidth: "1.5",
12744
- strokeLinecap: "round",
12745
- strokeLinejoin: "round"
12208
+ )
12209
+ ] })
12210
+ ] }),
12211
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
12212
+ Form$2.Field,
12213
+ {
12214
+ control: form.control,
12215
+ name: "quantity",
12216
+ render: ({ field }) => {
12217
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
12218
+ }
12219
+ }
12220
+ ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
12221
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
12222
+ Form$2.Field,
12223
+ {
12224
+ control: form.control,
12225
+ name: "unit_price",
12226
+ render: ({ field: { onChange, ...field } }) => {
12227
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12228
+ CurrencyInput,
12229
+ {
12230
+ ...field,
12231
+ symbol: getNativeSymbol(currencyCode),
12232
+ code: currencyCode,
12233
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12234
+ }
12235
+ ) }) });
12236
+ }
12237
+ }
12238
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
12239
+ /* @__PURE__ */ jsx(
12240
+ IconButton,
12241
+ {
12242
+ type: "button",
12243
+ size: "small",
12244
+ onClick: editing ? onSubmit : () => {
12245
+ setEditing(true);
12246
+ },
12247
+ disabled: isPending,
12248
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
12249
+ }
12250
+ )
12251
+ ] }) }) });
12252
+ };
12253
+ const variantItemSchema = objectType({
12254
+ quantity: numberType(),
12255
+ unit_price: unionType([numberType(), stringType()])
12256
+ });
12257
+ const CustomItem = ({ item, preview, currencyCode }) => {
12258
+ const [editing, setEditing] = useState(false);
12259
+ const { quantity, unit_price, title } = item;
12260
+ const form = useForm({
12261
+ defaultValues: {
12262
+ title,
12263
+ quantity,
12264
+ unit_price
12265
+ },
12266
+ resolver: zodResolver(customItemSchema)
12267
+ });
12268
+ useEffect(() => {
12269
+ form.reset({
12270
+ title,
12271
+ quantity,
12272
+ unit_price
12273
+ });
12274
+ }, [form, title, quantity, unit_price]);
12275
+ const actionId = useMemo(() => {
12276
+ var _a, _b;
12277
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12278
+ }, [item]);
12279
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12280
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
12281
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12282
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12283
+ const onSubmit = form.handleSubmit(async (data) => {
12284
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
12285
+ setEditing(false);
12286
+ return;
12287
+ }
12288
+ if (!actionId) {
12289
+ await updateOriginalItem(
12290
+ {
12291
+ item_id: item.id,
12292
+ quantity: data.quantity,
12293
+ unit_price: convertNumber(data.unit_price)
12294
+ },
12295
+ {
12296
+ onSuccess: () => {
12297
+ setEditing(false);
12298
+ },
12299
+ onError: (e) => {
12300
+ toast.error(e.message);
12746
12301
  }
12747
- ) }),
12748
- /* @__PURE__ */ jsx("g", { clipPath: "url(#clip4_20915_38670)", children: /* @__PURE__ */ jsx(
12749
- "path",
12750
- {
12751
- d: "M136.504 95.1945L129.12 95.1519L129.095 99.3617",
12752
- stroke: "#A1A1AA",
12753
- strokeWidth: "1.5",
12754
- strokeLinecap: "round",
12755
- strokeLinejoin: "round"
12302
+ }
12303
+ );
12304
+ return;
12305
+ }
12306
+ if (data.quantity === 0) {
12307
+ await removeActionItem(actionId, {
12308
+ onSuccess: () => {
12309
+ setEditing(false);
12310
+ },
12311
+ onError: (e) => {
12312
+ toast.error(e.message);
12313
+ }
12314
+ });
12315
+ return;
12316
+ }
12317
+ await updateActionItem(
12318
+ {
12319
+ action_id: actionId,
12320
+ quantity: data.quantity,
12321
+ unit_price: convertNumber(data.unit_price)
12322
+ },
12323
+ {
12324
+ onSuccess: () => {
12325
+ setEditing(false);
12326
+ },
12327
+ onError: (e) => {
12328
+ toast.error(e.message);
12329
+ }
12330
+ }
12331
+ );
12332
+ });
12333
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ 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: [
12334
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
12335
+ /* @__PURE__ */ jsx(
12336
+ Thumbnail,
12337
+ {
12338
+ thumbnail: item.thumbnail,
12339
+ alt: item.title ?? void 0
12340
+ }
12341
+ ),
12342
+ editing ? /* @__PURE__ */ jsx(
12343
+ Form$2.Field,
12344
+ {
12345
+ control: form.control,
12346
+ name: "title",
12347
+ render: ({ field }) => {
12348
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
12756
12349
  }
12757
- ) }),
12758
- /* @__PURE__ */ jsx("g", { clipPath: "url(#clip5_20915_38670)", children: /* @__PURE__ */ jsx(
12759
- "path",
12350
+ }
12351
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
12352
+ ] }),
12353
+ editing ? /* @__PURE__ */ jsx(
12354
+ Form$2.Field,
12355
+ {
12356
+ control: form.control,
12357
+ name: "quantity",
12358
+ render: ({ field }) => {
12359
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
12360
+ }
12361
+ }
12362
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
12363
+ editing ? /* @__PURE__ */ jsx(
12364
+ Form$2.Field,
12365
+ {
12366
+ control: form.control,
12367
+ name: "unit_price",
12368
+ render: ({ field: { onChange, ...field } }) => {
12369
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12370
+ CurrencyInput,
12371
+ {
12372
+ ...field,
12373
+ symbol: getNativeSymbol(currencyCode),
12374
+ code: currencyCode,
12375
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12376
+ }
12377
+ ) }) });
12378
+ }
12379
+ }
12380
+ ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
12381
+ /* @__PURE__ */ jsx(
12382
+ IconButton,
12383
+ {
12384
+ type: "button",
12385
+ size: "small",
12386
+ onClick: editing ? onSubmit : () => {
12387
+ setEditing(true);
12388
+ },
12389
+ disabled: isPending,
12390
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
12391
+ }
12392
+ )
12393
+ ] }) }) });
12394
+ };
12395
+ const StackedModalTrigger = ({
12396
+ type,
12397
+ setModalContent
12398
+ }) => {
12399
+ const { setIsOpen } = useStackedModal();
12400
+ const onClick = useCallback(() => {
12401
+ setModalContent(type);
12402
+ setIsOpen(STACKED_MODAL_ID, true);
12403
+ }, [setModalContent, setIsOpen, type]);
12404
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
12405
+ };
12406
+ const VARIANT_PREFIX = "items";
12407
+ const LIMIT = 50;
12408
+ const ExistingItemsForm = ({ orderId, items }) => {
12409
+ const { setIsOpen } = useStackedModal();
12410
+ const [rowSelection, setRowSelection] = useState(
12411
+ items.reduce((acc, item) => {
12412
+ acc[item.variant_id] = true;
12413
+ return acc;
12414
+ }, {})
12415
+ );
12416
+ useEffect(() => {
12417
+ setRowSelection(
12418
+ items.reduce((acc, item) => {
12419
+ if (item.variant_id) {
12420
+ acc[item.variant_id] = true;
12421
+ }
12422
+ return acc;
12423
+ }, {})
12424
+ );
12425
+ }, [items]);
12426
+ const { q, order, offset } = useQueryParams(
12427
+ ["q", "order", "offset"],
12428
+ VARIANT_PREFIX
12429
+ );
12430
+ const { variants, count, isPending, isError, error } = useProductVariants(
12431
+ {
12432
+ q,
12433
+ order,
12434
+ offset: offset ? parseInt(offset) : void 0,
12435
+ limit: LIMIT
12436
+ },
12437
+ {
12438
+ placeholderData: keepPreviousData
12439
+ }
12440
+ );
12441
+ const columns = useColumns();
12442
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
12443
+ const onSubmit = async () => {
12444
+ const ids = Object.keys(rowSelection).filter(
12445
+ (id) => !items.find((i) => i.variant_id === id)
12446
+ );
12447
+ await mutateAsync(
12448
+ {
12449
+ items: ids.map((id) => ({
12450
+ variant_id: id,
12451
+ quantity: 1
12452
+ }))
12453
+ },
12454
+ {
12455
+ onSuccess: () => {
12456
+ setRowSelection({});
12457
+ setIsOpen(STACKED_MODAL_ID, false);
12458
+ },
12459
+ onError: (e) => {
12460
+ toast.error(e.message);
12461
+ }
12462
+ }
12463
+ );
12464
+ };
12465
+ if (isError) {
12466
+ throw error;
12467
+ }
12468
+ return /* @__PURE__ */ jsxs(
12469
+ StackedFocusModal.Content,
12470
+ {
12471
+ onOpenAutoFocus: (e) => {
12472
+ e.preventDefault();
12473
+ const searchInput = document.querySelector(
12474
+ "[data-modal-id='modal-search-input']"
12475
+ );
12476
+ if (searchInput) {
12477
+ searchInput.focus();
12478
+ }
12479
+ },
12480
+ children: [
12481
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
12482
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
12483
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
12484
+ ] }),
12485
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
12486
+ DataTable,
12760
12487
  {
12761
- d: "M146.894 101.198L139.51 101.155L139.486 105.365",
12762
- stroke: "#A1A1AA",
12763
- strokeWidth: "1.5",
12764
- strokeLinecap: "round",
12765
- strokeLinejoin: "round"
12488
+ data: variants,
12489
+ columns,
12490
+ isLoading: isPending,
12491
+ getRowId: (row) => row.id,
12492
+ rowCount: count,
12493
+ prefix: VARIANT_PREFIX,
12494
+ layout: "fill",
12495
+ rowSelection: {
12496
+ state: rowSelection,
12497
+ onRowSelectionChange: setRowSelection,
12498
+ enableRowSelection: (row) => {
12499
+ return !items.find((i) => i.variant_id === row.original.id);
12500
+ }
12501
+ },
12502
+ autoFocusSearch: true
12766
12503
  }
12767
12504
  ) }),
12768
- /* @__PURE__ */ jsxs("defs", { children: [
12769
- /* @__PURE__ */ jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsx(
12770
- "rect",
12771
- {
12772
- width: "12",
12773
- height: "12",
12774
- fill: "white",
12775
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
12776
- }
12777
- ) }),
12778
- /* @__PURE__ */ jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsx(
12779
- "rect",
12780
- {
12781
- width: "12",
12782
- height: "12",
12783
- fill: "white",
12784
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12785
- }
12786
- ) }),
12787
- /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12788
- "rect",
12789
- {
12790
- width: "12",
12791
- height: "12",
12792
- fill: "white",
12793
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12794
- }
12795
- ) }),
12796
- /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12797
- "rect",
12505
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12506
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12507
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
12508
+ ] }) })
12509
+ ]
12510
+ }
12511
+ );
12512
+ };
12513
+ const columnHelper = createDataTableColumnHelper();
12514
+ const useColumns = () => {
12515
+ return useMemo(() => {
12516
+ return [
12517
+ columnHelper.select(),
12518
+ columnHelper.accessor("product.title", {
12519
+ header: "Product",
12520
+ cell: ({ row }) => {
12521
+ var _a, _b, _c;
12522
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
12523
+ /* @__PURE__ */ jsx(
12524
+ Thumbnail,
12525
+ {
12526
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
12527
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
12528
+ }
12529
+ ),
12530
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
12531
+ ] });
12532
+ },
12533
+ enableSorting: true
12534
+ }),
12535
+ columnHelper.accessor("title", {
12536
+ header: "Variant",
12537
+ enableSorting: true
12538
+ }),
12539
+ columnHelper.accessor("sku", {
12540
+ header: "SKU",
12541
+ cell: ({ getValue }) => {
12542
+ return getValue() ?? "-";
12543
+ },
12544
+ enableSorting: true
12545
+ }),
12546
+ columnHelper.accessor("updated_at", {
12547
+ header: "Updated",
12548
+ cell: ({ getValue }) => {
12549
+ return /* @__PURE__ */ jsx(
12550
+ Tooltip,
12798
12551
  {
12799
- width: "12",
12800
- height: "12",
12801
- fill: "white",
12802
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12552
+ content: getFullDate({ date: getValue(), includeTime: true }),
12553
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
12803
12554
  }
12804
- ) }),
12805
- /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
12806
- "rect",
12555
+ );
12556
+ },
12557
+ enableSorting: true,
12558
+ sortAscLabel: "Oldest first",
12559
+ sortDescLabel: "Newest first"
12560
+ }),
12561
+ columnHelper.accessor("created_at", {
12562
+ header: "Created",
12563
+ cell: ({ getValue }) => {
12564
+ return /* @__PURE__ */ jsx(
12565
+ Tooltip,
12807
12566
  {
12808
- width: "12",
12809
- height: "12",
12810
- fill: "white",
12811
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12567
+ content: getFullDate({ date: getValue(), includeTime: true }),
12568
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
12812
12569
  }
12813
- ) }),
12814
- /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
12815
- "rect",
12570
+ );
12571
+ },
12572
+ enableSorting: true,
12573
+ sortAscLabel: "Oldest first",
12574
+ sortDescLabel: "Newest first"
12575
+ })
12576
+ ];
12577
+ }, []);
12578
+ };
12579
+ const CustomItemForm = ({ orderId, currencyCode }) => {
12580
+ const { setIsOpen } = useStackedModal();
12581
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
12582
+ const form = useForm({
12583
+ defaultValues: {
12584
+ title: "",
12585
+ quantity: 1,
12586
+ unit_price: ""
12587
+ },
12588
+ resolver: zodResolver(customItemSchema)
12589
+ });
12590
+ const onSubmit = form.handleSubmit(async (data) => {
12591
+ await addItems(
12592
+ {
12593
+ items: [
12594
+ {
12595
+ title: data.title,
12596
+ quantity: data.quantity,
12597
+ unit_price: convertNumber(data.unit_price)
12598
+ }
12599
+ ]
12600
+ },
12601
+ {
12602
+ onSuccess: () => {
12603
+ setIsOpen(STACKED_MODAL_ID, false);
12604
+ },
12605
+ onError: (e) => {
12606
+ toast.error(e.message);
12607
+ }
12608
+ }
12609
+ );
12610
+ });
12611
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
12612
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
12613
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-2 py-16", children: [
12614
+ /* @__PURE__ */ jsxs("div", { children: [
12615
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
12616
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(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." }) })
12617
+ ] }),
12618
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12619
+ /* @__PURE__ */ jsx(
12620
+ Form$2.Field,
12621
+ {
12622
+ control: form.control,
12623
+ name: "title",
12624
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12625
+ /* @__PURE__ */ jsxs("div", { children: [
12626
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
12627
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
12628
+ ] }),
12629
+ /* @__PURE__ */ jsxs("div", { children: [
12630
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12631
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12632
+ ] })
12633
+ ] }) })
12634
+ }
12635
+ ),
12636
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12637
+ /* @__PURE__ */ jsx(
12638
+ Form$2.Field,
12639
+ {
12640
+ control: form.control,
12641
+ name: "unit_price",
12642
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12643
+ /* @__PURE__ */ jsxs("div", { children: [
12644
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
12645
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
12646
+ ] }),
12647
+ /* @__PURE__ */ jsxs("div", { children: [
12648
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12649
+ CurrencyInput,
12650
+ {
12651
+ symbol: getNativeSymbol(currencyCode),
12652
+ code: currencyCode,
12653
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
12654
+ ...field
12655
+ }
12656
+ ) }),
12657
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12658
+ ] })
12659
+ ] }) })
12660
+ }
12661
+ ),
12662
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12663
+ /* @__PURE__ */ jsx(
12664
+ Form$2.Field,
12665
+ {
12666
+ control: form.control,
12667
+ name: "quantity",
12668
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12669
+ /* @__PURE__ */ jsxs("div", { children: [
12670
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
12671
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
12672
+ ] }),
12673
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
12674
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
12675
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12676
+ ] })
12677
+ ] }) })
12678
+ }
12679
+ )
12680
+ ] }) }) }),
12681
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12682
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12683
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
12684
+ ] }) })
12685
+ ] }) }) });
12686
+ };
12687
+ const customItemSchema = objectType({
12688
+ title: stringType().min(1),
12689
+ quantity: numberType(),
12690
+ unit_price: unionType([numberType(), stringType()])
12691
+ });
12692
+ const InlineTip = forwardRef(
12693
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
12694
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
12695
+ return /* @__PURE__ */ jsxs(
12696
+ "div",
12697
+ {
12698
+ ref,
12699
+ className: clx(
12700
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
12701
+ className
12702
+ ),
12703
+ ...props,
12704
+ children: [
12705
+ /* @__PURE__ */ jsx(
12706
+ "div",
12816
12707
  {
12817
- width: "12",
12818
- height: "12",
12819
- fill: "white",
12820
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
12708
+ role: "presentation",
12709
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
12710
+ "bg-ui-tag-orange-icon": variant === "warning"
12711
+ })
12821
12712
  }
12822
- ) })
12823
- ] })
12824
- ]
12825
- }
12826
- );
12827
- };
12828
- const schema$2 = objectType({
12829
- customer_id: stringType().min(1)
12713
+ ),
12714
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
12715
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
12716
+ labelValue,
12717
+ ":"
12718
+ ] }),
12719
+ " ",
12720
+ children
12721
+ ] })
12722
+ ]
12723
+ }
12724
+ );
12725
+ }
12726
+ );
12727
+ InlineTip.displayName = "InlineTip";
12728
+ const MetadataFieldSchema = objectType({
12729
+ key: stringType(),
12730
+ disabled: booleanType().optional(),
12731
+ value: anyType()
12830
12732
  });
12831
- const BillingAddress = () => {
12733
+ const MetadataSchema = objectType({
12734
+ metadata: arrayType(MetadataFieldSchema)
12735
+ });
12736
+ const Metadata = () => {
12832
12737
  const { id } = useParams();
12833
12738
  const { order, isPending, isError, error } = useOrder(id, {
12834
- fields: "+billing_address"
12739
+ fields: "metadata"
12835
12740
  });
12836
12741
  if (isError) {
12837
12742
  throw error;
@@ -12839,36 +12744,33 @@ const BillingAddress = () => {
12839
12744
  const isReady = !isPending && !!order;
12840
12745
  return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12841
12746
  /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12842
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Billing Address" }) }),
12843
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the billing address for the draft order" }) })
12747
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
12748
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
12844
12749
  ] }),
12845
- isReady && /* @__PURE__ */ jsx(BillingAddressForm, { order })
12750
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
12846
12751
  ] });
12847
12752
  };
12848
- const BillingAddressForm = ({ order }) => {
12849
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
12753
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
12754
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
12755
+ const MetadataForm = ({ orderId, metadata }) => {
12756
+ const { handleSuccess } = useRouteModal();
12757
+ const hasUneditableRows = getHasUneditableRows(metadata);
12758
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
12850
12759
  const form = useForm({
12851
12760
  defaultValues: {
12852
- first_name: ((_a = order.billing_address) == null ? void 0 : _a.first_name) ?? "",
12853
- last_name: ((_b = order.billing_address) == null ? void 0 : _b.last_name) ?? "",
12854
- company: ((_c = order.billing_address) == null ? void 0 : _c.company) ?? "",
12855
- address_1: ((_d = order.billing_address) == null ? void 0 : _d.address_1) ?? "",
12856
- address_2: ((_e = order.billing_address) == null ? void 0 : _e.address_2) ?? "",
12857
- city: ((_f = order.billing_address) == null ? void 0 : _f.city) ?? "",
12858
- province: ((_g = order.billing_address) == null ? void 0 : _g.province) ?? "",
12859
- country_code: ((_h = order.billing_address) == null ? void 0 : _h.country_code) ?? "",
12860
- postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
12861
- phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
12761
+ metadata: getDefaultValues(metadata)
12862
12762
  },
12863
- resolver: zodResolver(schema$1)
12763
+ resolver: zodResolver(MetadataSchema)
12864
12764
  });
12865
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12866
- const { handleSuccess } = useRouteModal();
12867
- const onSubmit = form.handleSubmit(async (data) => {
12765
+ const handleSubmit = form.handleSubmit(async (data) => {
12766
+ const parsedData = parseValues(data);
12868
12767
  await mutateAsync(
12869
- { billing_address: data },
12768
+ {
12769
+ metadata: parsedData
12770
+ },
12870
12771
  {
12871
12772
  onSuccess: () => {
12773
+ toast.success("Metadata updated");
12872
12774
  handleSuccess();
12873
12775
  },
12874
12776
  onError: (error) => {
@@ -12877,168 +12779,266 @@ const BillingAddressForm = ({ order }) => {
12877
12779
  }
12878
12780
  );
12879
12781
  });
12782
+ const { fields, insert, remove } = useFieldArray({
12783
+ control: form.control,
12784
+ name: "metadata"
12785
+ });
12786
+ function deleteRow(index) {
12787
+ remove(index);
12788
+ if (fields.length === 1) {
12789
+ insert(0, {
12790
+ key: "",
12791
+ value: "",
12792
+ disabled: false
12793
+ });
12794
+ }
12795
+ }
12796
+ function insertRow(index, position) {
12797
+ insert(index + (position === "above" ? 0 : 1), {
12798
+ key: "",
12799
+ value: "",
12800
+ disabled: false
12801
+ });
12802
+ }
12880
12803
  return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12881
12804
  KeyboundForm,
12882
12805
  {
12806
+ onSubmit: handleSubmit,
12883
12807
  className: "flex flex-1 flex-col overflow-hidden",
12884
- onSubmit,
12885
12808
  children: [
12886
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
12887
- /* @__PURE__ */ jsx(
12888
- Form$2.Field,
12889
- {
12890
- control: form.control,
12891
- name: "country_code",
12892
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12893
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
12894
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
12895
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12896
- ] })
12897
- }
12898
- ),
12899
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12900
- /* @__PURE__ */ jsx(
12901
- Form$2.Field,
12902
- {
12903
- control: form.control,
12904
- name: "first_name",
12905
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12906
- /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
12907
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12908
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12909
- ] })
12910
- }
12911
- ),
12912
- /* @__PURE__ */ jsx(
12913
- Form$2.Field,
12914
- {
12915
- control: form.control,
12916
- name: "last_name",
12917
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12918
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
12919
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12920
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12921
- ] })
12922
- }
12923
- )
12924
- ] }),
12925
- /* @__PURE__ */ jsx(
12926
- Form$2.Field,
12927
- {
12928
- control: form.control,
12929
- name: "company",
12930
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12931
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
12932
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12933
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12934
- ] })
12935
- }
12936
- ),
12937
- /* @__PURE__ */ jsx(
12938
- Form$2.Field,
12939
- {
12940
- control: form.control,
12941
- name: "address_1",
12942
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12943
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
12944
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12945
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12946
- ] })
12947
- }
12948
- ),
12949
- /* @__PURE__ */ jsx(
12950
- Form$2.Field,
12951
- {
12952
- control: form.control,
12953
- name: "address_2",
12954
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12955
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
12956
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12957
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12958
- ] })
12959
- }
12960
- ),
12961
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12962
- /* @__PURE__ */ jsx(
12963
- Form$2.Field,
12964
- {
12965
- control: form.control,
12966
- name: "postal_code",
12967
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12968
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
12969
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12970
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12971
- ] })
12809
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
12810
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
12811
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
12812
+ /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_KEY_LABEL_ID, children: "Key" }) }),
12813
+ /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_VALUE_LABEL_ID, children: "Value" }) })
12814
+ ] }),
12815
+ fields.map((field, index) => {
12816
+ const isDisabled = field.disabled || false;
12817
+ let placeholder = "-";
12818
+ if (typeof field.value === "object") {
12819
+ placeholder = "{ ... }";
12972
12820
  }
12973
- ),
12974
- /* @__PURE__ */ jsx(
12975
- Form$2.Field,
12976
- {
12977
- control: form.control,
12978
- name: "city",
12979
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12980
- /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
12981
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12982
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12983
- ] })
12821
+ if (Array.isArray(field.value)) {
12822
+ placeholder = "[ ... ]";
12984
12823
  }
12985
- )
12824
+ return /* @__PURE__ */ jsx(
12825
+ ConditionalTooltip,
12826
+ {
12827
+ showTooltip: isDisabled,
12828
+ content: "This row is disabled because it contains non-primitive data.",
12829
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
12830
+ /* @__PURE__ */ jsxs(
12831
+ "div",
12832
+ {
12833
+ className: clx("grid grid-cols-2 divide-x", {
12834
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
12835
+ }),
12836
+ children: [
12837
+ /* @__PURE__ */ jsx(
12838
+ Form$2.Field,
12839
+ {
12840
+ control: form.control,
12841
+ name: `metadata.${index}.key`,
12842
+ render: ({ field: field2 }) => {
12843
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12844
+ GridInput,
12845
+ {
12846
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
12847
+ ...field2,
12848
+ disabled: isDisabled,
12849
+ placeholder: "Key"
12850
+ }
12851
+ ) }) });
12852
+ }
12853
+ }
12854
+ ),
12855
+ /* @__PURE__ */ jsx(
12856
+ Form$2.Field,
12857
+ {
12858
+ control: form.control,
12859
+ name: `metadata.${index}.value`,
12860
+ render: ({ field: { value, ...field2 } }) => {
12861
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12862
+ GridInput,
12863
+ {
12864
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
12865
+ ...field2,
12866
+ value: isDisabled ? placeholder : value,
12867
+ disabled: isDisabled,
12868
+ placeholder: "Value"
12869
+ }
12870
+ ) }) });
12871
+ }
12872
+ }
12873
+ )
12874
+ ]
12875
+ }
12876
+ ),
12877
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
12878
+ /* @__PURE__ */ jsx(
12879
+ DropdownMenu.Trigger,
12880
+ {
12881
+ className: clx(
12882
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
12883
+ {
12884
+ hidden: isDisabled
12885
+ }
12886
+ ),
12887
+ disabled: isDisabled,
12888
+ asChild: true,
12889
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
12890
+ }
12891
+ ),
12892
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
12893
+ /* @__PURE__ */ jsxs(
12894
+ DropdownMenu.Item,
12895
+ {
12896
+ className: "gap-x-2",
12897
+ onClick: () => insertRow(index, "above"),
12898
+ children: [
12899
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
12900
+ "Insert row above"
12901
+ ]
12902
+ }
12903
+ ),
12904
+ /* @__PURE__ */ jsxs(
12905
+ DropdownMenu.Item,
12906
+ {
12907
+ className: "gap-x-2",
12908
+ onClick: () => insertRow(index, "below"),
12909
+ children: [
12910
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
12911
+ "Insert row below"
12912
+ ]
12913
+ }
12914
+ ),
12915
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
12916
+ /* @__PURE__ */ jsxs(
12917
+ DropdownMenu.Item,
12918
+ {
12919
+ className: "gap-x-2",
12920
+ onClick: () => deleteRow(index),
12921
+ children: [
12922
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
12923
+ "Delete row"
12924
+ ]
12925
+ }
12926
+ )
12927
+ ] })
12928
+ ] })
12929
+ ] })
12930
+ },
12931
+ field.id
12932
+ );
12933
+ })
12986
12934
  ] }),
12987
- /* @__PURE__ */ jsx(
12988
- Form$2.Field,
12989
- {
12990
- control: form.control,
12991
- name: "province",
12992
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12993
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
12994
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12995
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12996
- ] })
12997
- }
12998
- ),
12999
- /* @__PURE__ */ jsx(
13000
- Form$2.Field,
13001
- {
13002
- control: form.control,
13003
- name: "phone",
13004
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13005
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
13006
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13007
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13008
- ] })
13009
- }
13010
- )
13011
- ] }) }),
13012
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13013
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
12935
+ hasUneditableRows && /* @__PURE__ */ 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." })
12936
+ ] }),
12937
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12938
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
13014
12939
  /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
13015
12940
  ] }) })
13016
12941
  ]
13017
12942
  }
13018
12943
  ) });
13019
12944
  };
13020
- const schema$1 = addressSchema;
13021
- const CustomItems = () => {
13022
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
13023
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
13024
- /* @__PURE__ */ jsx(CustomItemsForm, {})
12945
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
12946
+ return /* @__PURE__ */ jsx(
12947
+ "input",
12948
+ {
12949
+ ref,
12950
+ ...props,
12951
+ autoComplete: "off",
12952
+ className: clx(
12953
+ "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",
12954
+ className
12955
+ )
12956
+ }
12957
+ );
12958
+ });
12959
+ GridInput.displayName = "MetadataForm.GridInput";
12960
+ const PlaceholderInner = () => {
12961
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
12962
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
12963
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12964
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
12965
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
12966
+ ] }) })
13025
12967
  ] });
13026
12968
  };
13027
- const CustomItemsForm = () => {
13028
- const form = useForm({
13029
- resolver: zodResolver(schema)
12969
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
12970
+ function getDefaultValues(metadata) {
12971
+ if (!metadata || !Object.keys(metadata).length) {
12972
+ return [
12973
+ {
12974
+ key: "",
12975
+ value: "",
12976
+ disabled: false
12977
+ }
12978
+ ];
12979
+ }
12980
+ return Object.entries(metadata).map(([key, value]) => {
12981
+ if (!EDITABLE_TYPES.includes(typeof value)) {
12982
+ return {
12983
+ key,
12984
+ value,
12985
+ disabled: true
12986
+ };
12987
+ }
12988
+ let stringValue = value;
12989
+ if (typeof value !== "string") {
12990
+ stringValue = JSON.stringify(value);
12991
+ }
12992
+ return {
12993
+ key,
12994
+ value: stringValue,
12995
+ original_key: key
12996
+ };
13030
12997
  });
13031
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
13032
- /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
13033
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13034
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
13035
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
13036
- ] }) })
13037
- ] }) });
13038
- };
13039
- const schema = objectType({
13040
- email: stringType().email()
13041
- });
12998
+ }
12999
+ function parseValues(values) {
13000
+ const metadata = values.metadata;
13001
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
13002
+ if (isEmpty) {
13003
+ return null;
13004
+ }
13005
+ const update = {};
13006
+ metadata.forEach((field) => {
13007
+ let key = field.key;
13008
+ let value = field.value;
13009
+ const disabled = field.disabled;
13010
+ if (!key || !value) {
13011
+ return;
13012
+ }
13013
+ if (disabled) {
13014
+ update[key] = value;
13015
+ return;
13016
+ }
13017
+ key = key.trim();
13018
+ value = value.trim();
13019
+ if (value === "true") {
13020
+ update[key] = true;
13021
+ } else if (value === "false") {
13022
+ update[key] = false;
13023
+ } else {
13024
+ const parsedNumber = parseFloat(value);
13025
+ if (!isNaN(parsedNumber)) {
13026
+ update[key] = parsedNumber;
13027
+ } else {
13028
+ update[key] = value;
13029
+ }
13030
+ }
13031
+ });
13032
+ return update;
13033
+ }
13034
+ function getHasUneditableRows(metadata) {
13035
+ if (!metadata) {
13036
+ return false;
13037
+ }
13038
+ return Object.values(metadata).some(
13039
+ (value) => !EDITABLE_TYPES.includes(typeof value)
13040
+ );
13041
+ }
13042
13042
  const widgetModule = { widgets: [] };
13043
13043
  const routeModule = {
13044
13044
  routes: [
@@ -13060,16 +13060,16 @@ const routeModule = {
13060
13060
  loader,
13061
13061
  children: [
13062
13062
  {
13063
- Component: Email,
13064
- path: "/draft-orders/:id/email"
13063
+ Component: CustomItems,
13064
+ path: "/draft-orders/:id/custom-items"
13065
13065
  },
13066
13066
  {
13067
- Component: Items,
13068
- path: "/draft-orders/:id/items"
13067
+ Component: BillingAddress,
13068
+ path: "/draft-orders/:id/billing-address"
13069
13069
  },
13070
13070
  {
13071
- Component: Metadata,
13072
- path: "/draft-orders/:id/metadata"
13071
+ Component: Email,
13072
+ path: "/draft-orders/:id/email"
13073
13073
  },
13074
13074
  {
13075
13075
  Component: Promotions,
@@ -13092,12 +13092,12 @@ const routeModule = {
13092
13092
  path: "/draft-orders/:id/transfer-ownership"
13093
13093
  },
13094
13094
  {
13095
- Component: BillingAddress,
13096
- path: "/draft-orders/:id/billing-address"
13095
+ Component: Items,
13096
+ path: "/draft-orders/:id/items"
13097
13097
  },
13098
13098
  {
13099
- Component: CustomItems,
13100
- path: "/draft-orders/:id/custom-items"
13099
+ Component: Metadata,
13100
+ path: "/draft-orders/:id/metadata"
13101
13101
  }
13102
13102
  ]
13103
13103
  }