@medusajs/draft-order 2.10.1 → 2.10.2-preview-20250829180153

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.
@@ -4,7 +4,7 @@ import { Tooltip, DropdownMenu, clx, IconButton, useDataTable, DataTable as Data
4
4
  import { useQuery, useQueryClient, useMutation, keepPreviousData, useInfiniteQuery } from "@tanstack/react-query";
5
5
  import React, { useState, useCallback, useMemo, Fragment, createContext, forwardRef, useId, useContext, useTransition, useRef, useImperativeHandle, useDeferredValue, useEffect, Suspense } from "react";
6
6
  import { useSearchParams, Link, useNavigate, Outlet, useBlocker, useLocation, useParams } from "react-router-dom";
7
- import { EllipsisHorizontal, XMark, InformationCircleSolid, XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini, ExclamationCircleSolid, ArrowPath, FlyingBox, CurrencyDollar, Envelope, Channels, Trash, ArrowUpRightOnBox, TriangleDownMini, Check, SquareTwoStack, Photo, TriangleRightMini, Shopping, Buildings, TruckFast, Plus, ReceiptPercent, EllipsisVertical, ArrowUpMini, ArrowDownMini, Minus, PencilSquare } from "@medusajs/icons";
7
+ import { EllipsisHorizontal, XMark, InformationCircleSolid, XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini, ExclamationCircleSolid, ArrowPath, FlyingBox, CurrencyDollar, Envelope, Channels, Trash, ArrowUpRightOnBox, TriangleDownMini, Check, SquareTwoStack, Photo, TriangleRightMini, Shopping, Buildings, TruckFast, Plus, ReceiptPercent, Minus, PencilSquare, EllipsisVertical, ArrowUpMini, ArrowDownMini } from "@medusajs/icons";
8
8
  import Medusa from "@medusajs/js-sdk";
9
9
  import { format, formatDistance, sub, subDays, subMonths } from "date-fns";
10
10
  import { enUS } from "date-fns/locale";
@@ -9554,196 +9554,6 @@ const ID = () => {
9554
9554
  /* @__PURE__ */ jsx(Outlet, {})
9555
9555
  ] });
9556
9556
  };
9557
- const BillingAddress = () => {
9558
- const { id } = useParams();
9559
- const { order, isPending, isError, error } = useOrder(id, {
9560
- fields: "+billing_address"
9561
- });
9562
- if (isError) {
9563
- throw error;
9564
- }
9565
- const isReady = !isPending && !!order;
9566
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9567
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9568
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Billing Address" }) }),
9569
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the billing address for the draft order" }) })
9570
- ] }),
9571
- isReady && /* @__PURE__ */ jsx(BillingAddressForm, { order })
9572
- ] });
9573
- };
9574
- const BillingAddressForm = ({ order }) => {
9575
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
9576
- const form = useForm({
9577
- defaultValues: {
9578
- first_name: ((_a = order.billing_address) == null ? void 0 : _a.first_name) ?? "",
9579
- last_name: ((_b = order.billing_address) == null ? void 0 : _b.last_name) ?? "",
9580
- company: ((_c = order.billing_address) == null ? void 0 : _c.company) ?? "",
9581
- address_1: ((_d = order.billing_address) == null ? void 0 : _d.address_1) ?? "",
9582
- address_2: ((_e = order.billing_address) == null ? void 0 : _e.address_2) ?? "",
9583
- city: ((_f = order.billing_address) == null ? void 0 : _f.city) ?? "",
9584
- province: ((_g = order.billing_address) == null ? void 0 : _g.province) ?? "",
9585
- country_code: ((_h = order.billing_address) == null ? void 0 : _h.country_code) ?? "",
9586
- postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
9587
- phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
9588
- },
9589
- resolver: zodResolver(schema$5)
9590
- });
9591
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9592
- const { handleSuccess } = useRouteModal();
9593
- const onSubmit = form.handleSubmit(async (data) => {
9594
- await mutateAsync(
9595
- { billing_address: data },
9596
- {
9597
- onSuccess: () => {
9598
- handleSuccess();
9599
- },
9600
- onError: (error) => {
9601
- toast.error(error.message);
9602
- }
9603
- }
9604
- );
9605
- });
9606
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9607
- KeyboundForm,
9608
- {
9609
- className: "flex flex-1 flex-col overflow-hidden",
9610
- onSubmit,
9611
- children: [
9612
- /* @__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: [
9613
- /* @__PURE__ */ jsx(
9614
- Form$2.Field,
9615
- {
9616
- control: form.control,
9617
- name: "country_code",
9618
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9619
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
9620
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
9621
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9622
- ] })
9623
- }
9624
- ),
9625
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
9626
- /* @__PURE__ */ jsx(
9627
- Form$2.Field,
9628
- {
9629
- control: form.control,
9630
- name: "first_name",
9631
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9632
- /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
9633
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9634
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9635
- ] })
9636
- }
9637
- ),
9638
- /* @__PURE__ */ jsx(
9639
- Form$2.Field,
9640
- {
9641
- control: form.control,
9642
- name: "last_name",
9643
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9644
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
9645
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9646
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9647
- ] })
9648
- }
9649
- )
9650
- ] }),
9651
- /* @__PURE__ */ jsx(
9652
- Form$2.Field,
9653
- {
9654
- control: form.control,
9655
- name: "company",
9656
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9657
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
9658
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9659
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9660
- ] })
9661
- }
9662
- ),
9663
- /* @__PURE__ */ jsx(
9664
- Form$2.Field,
9665
- {
9666
- control: form.control,
9667
- name: "address_1",
9668
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9669
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
9670
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9671
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9672
- ] })
9673
- }
9674
- ),
9675
- /* @__PURE__ */ jsx(
9676
- Form$2.Field,
9677
- {
9678
- control: form.control,
9679
- name: "address_2",
9680
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9681
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
9682
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9683
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9684
- ] })
9685
- }
9686
- ),
9687
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
9688
- /* @__PURE__ */ jsx(
9689
- Form$2.Field,
9690
- {
9691
- control: form.control,
9692
- name: "postal_code",
9693
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9694
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
9695
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9696
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9697
- ] })
9698
- }
9699
- ),
9700
- /* @__PURE__ */ jsx(
9701
- Form$2.Field,
9702
- {
9703
- control: form.control,
9704
- name: "city",
9705
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9706
- /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
9707
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9708
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9709
- ] })
9710
- }
9711
- )
9712
- ] }),
9713
- /* @__PURE__ */ jsx(
9714
- Form$2.Field,
9715
- {
9716
- control: form.control,
9717
- name: "province",
9718
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9719
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
9720
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9721
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9722
- ] })
9723
- }
9724
- ),
9725
- /* @__PURE__ */ jsx(
9726
- Form$2.Field,
9727
- {
9728
- control: form.control,
9729
- name: "phone",
9730
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9731
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
9732
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9733
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9734
- ] })
9735
- }
9736
- )
9737
- ] }) }),
9738
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9739
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9740
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9741
- ] }) })
9742
- ]
9743
- }
9744
- ) });
9745
- };
9746
- const schema$5 = addressSchema;
9747
9557
  const CustomItems = () => {
9748
9558
  return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9749
9559
  /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
@@ -9752,7 +9562,7 @@ const CustomItems = () => {
9752
9562
  };
9753
9563
  const CustomItemsForm = () => {
9754
9564
  const form = useForm({
9755
- resolver: zodResolver(schema$4)
9565
+ resolver: zodResolver(schema$5)
9756
9566
  });
9757
9567
  return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9758
9568
  /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
@@ -9762,7 +9572,7 @@ const CustomItemsForm = () => {
9762
9572
  ] }) })
9763
9573
  ] }) });
9764
9574
  };
9765
- const schema$4 = objectType({
9575
+ const schema$5 = objectType({
9766
9576
  email: stringType().email()
9767
9577
  });
9768
9578
  const Email = () => {
@@ -9787,7 +9597,7 @@ const EmailForm = ({ order }) => {
9787
9597
  defaultValues: {
9788
9598
  email: order.email ?? ""
9789
9599
  },
9790
- resolver: zodResolver(schema$3)
9600
+ resolver: zodResolver(schema$4)
9791
9601
  });
9792
9602
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9793
9603
  const { handleSuccess } = useRouteModal();
@@ -9830,1716 +9640,1610 @@ const EmailForm = ({ order }) => {
9830
9640
  }
9831
9641
  ) });
9832
9642
  };
9833
- const schema$3 = objectType({
9643
+ const schema$4 = objectType({
9834
9644
  email: stringType().email()
9835
9645
  });
9836
- const InlineTip = forwardRef(
9837
- ({ variant = "tip", label, className, children, ...props }, ref) => {
9838
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
9646
+ const NumberInput = forwardRef(
9647
+ ({
9648
+ value,
9649
+ onChange,
9650
+ size = "base",
9651
+ min = 0,
9652
+ max = 100,
9653
+ step = 1,
9654
+ className,
9655
+ disabled,
9656
+ ...props
9657
+ }, ref) => {
9658
+ const handleChange = (event) => {
9659
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
9660
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9661
+ onChange(newValue);
9662
+ }
9663
+ };
9664
+ const handleIncrement = () => {
9665
+ const newValue = value + step;
9666
+ if (max === void 0 || newValue <= max) {
9667
+ onChange(newValue);
9668
+ }
9669
+ };
9670
+ const handleDecrement = () => {
9671
+ const newValue = value - step;
9672
+ if (min === void 0 || newValue >= min) {
9673
+ onChange(newValue);
9674
+ }
9675
+ };
9839
9676
  return /* @__PURE__ */ jsxs(
9840
9677
  "div",
9841
9678
  {
9842
- ref,
9843
9679
  className: clx(
9844
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
9680
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9681
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9682
+ {
9683
+ "h-7": size === "small",
9684
+ "h-8": size === "base"
9685
+ },
9845
9686
  className
9846
9687
  ),
9847
- ...props,
9848
9688
  children: [
9849
9689
  /* @__PURE__ */ jsx(
9850
- "div",
9690
+ "input",
9851
9691
  {
9852
- role: "presentation",
9853
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
9854
- "bg-ui-tag-orange-icon": variant === "warning"
9855
- })
9692
+ ref,
9693
+ type: "number",
9694
+ value,
9695
+ onChange: handleChange,
9696
+ min,
9697
+ max,
9698
+ step,
9699
+ className: clx(
9700
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9701
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9702
+ "placeholder:text-ui-fg-muted"
9703
+ ),
9704
+ ...props
9856
9705
  }
9857
9706
  ),
9858
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
9859
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
9860
- labelValue,
9861
- ":"
9862
- ] }),
9863
- " ",
9864
- children
9865
- ] })
9707
+ /* @__PURE__ */ jsxs(
9708
+ "button",
9709
+ {
9710
+ className: clx(
9711
+ "flex items-center justify-center outline-none transition-fg",
9712
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9713
+ "focus:bg-ui-bg-field-component-hover",
9714
+ "hover:bg-ui-bg-field-component-hover",
9715
+ {
9716
+ "size-7": size === "small",
9717
+ "size-8": size === "base"
9718
+ }
9719
+ ),
9720
+ type: "button",
9721
+ onClick: handleDecrement,
9722
+ disabled: min !== void 0 && value <= min || disabled,
9723
+ children: [
9724
+ /* @__PURE__ */ jsx(Minus, {}),
9725
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9726
+ ]
9727
+ }
9728
+ ),
9729
+ /* @__PURE__ */ jsxs(
9730
+ "button",
9731
+ {
9732
+ className: clx(
9733
+ "flex items-center justify-center outline-none transition-fg",
9734
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9735
+ "focus:bg-ui-bg-field-hover",
9736
+ "hover:bg-ui-bg-field-hover",
9737
+ {
9738
+ "size-7": size === "small",
9739
+ "size-8": size === "base"
9740
+ }
9741
+ ),
9742
+ type: "button",
9743
+ onClick: handleIncrement,
9744
+ disabled: max !== void 0 && value >= max || disabled,
9745
+ children: [
9746
+ /* @__PURE__ */ jsx(Plus, {}),
9747
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9748
+ ]
9749
+ }
9750
+ )
9866
9751
  ]
9867
9752
  }
9868
9753
  );
9869
9754
  }
9870
9755
  );
9871
- InlineTip.displayName = "InlineTip";
9872
- const MetadataFieldSchema = objectType({
9873
- key: stringType(),
9874
- disabled: booleanType().optional(),
9875
- value: anyType()
9876
- });
9877
- const MetadataSchema = objectType({
9878
- metadata: arrayType(MetadataFieldSchema)
9879
- });
9880
- const Metadata = () => {
9756
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9757
+ const productVariantsQueryKeys = {
9758
+ list: (query2) => [
9759
+ PRODUCT_VARIANTS_QUERY_KEY,
9760
+ query2 ? query2 : void 0
9761
+ ]
9762
+ };
9763
+ const useProductVariants = (query2, options) => {
9764
+ const { data, ...rest } = useQuery({
9765
+ queryKey: productVariantsQueryKeys.list(query2),
9766
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
9767
+ ...options
9768
+ });
9769
+ return { ...data, ...rest };
9770
+ };
9771
+ const useCancelOrderEdit = ({ preview }) => {
9772
+ const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
9773
+ const onCancel = useCallback(async () => {
9774
+ if (!preview) {
9775
+ return true;
9776
+ }
9777
+ let res = false;
9778
+ await cancelOrderEdit(void 0, {
9779
+ onError: (e) => {
9780
+ toast.error(e.message);
9781
+ },
9782
+ onSuccess: () => {
9783
+ res = true;
9784
+ }
9785
+ });
9786
+ return res;
9787
+ }, [preview, cancelOrderEdit]);
9788
+ return { onCancel };
9789
+ };
9790
+ let IS_REQUEST_RUNNING = false;
9791
+ const useInitiateOrderEdit = ({
9792
+ preview
9793
+ }) => {
9794
+ const navigate = useNavigate();
9795
+ const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
9796
+ useEffect(() => {
9797
+ async function run() {
9798
+ if (IS_REQUEST_RUNNING || !preview) {
9799
+ return;
9800
+ }
9801
+ if (preview.order_change) {
9802
+ return;
9803
+ }
9804
+ IS_REQUEST_RUNNING = true;
9805
+ await mutateAsync(void 0, {
9806
+ onError: (e) => {
9807
+ toast.error(e.message);
9808
+ navigate(`/draft-orders/${preview.id}`, { replace: true });
9809
+ return;
9810
+ }
9811
+ });
9812
+ IS_REQUEST_RUNNING = false;
9813
+ }
9814
+ run();
9815
+ }, [preview, navigate, mutateAsync]);
9816
+ };
9817
+ function convertNumber(value) {
9818
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
9819
+ }
9820
+ const STACKED_MODAL_ID = "items_stacked_modal";
9821
+ const Items = () => {
9881
9822
  const { id } = useParams();
9882
- const { order, isPending, isError, error } = useOrder(id, {
9883
- fields: "metadata"
9823
+ const {
9824
+ order: preview,
9825
+ isPending: isPreviewPending,
9826
+ isError: isPreviewError,
9827
+ error: previewError
9828
+ } = useOrderPreview(id, void 0, {
9829
+ placeholderData: keepPreviousData
9884
9830
  });
9831
+ useInitiateOrderEdit({ preview });
9832
+ const { draft_order, isPending, isError, error } = useDraftOrder(
9833
+ id,
9834
+ {
9835
+ fields: "currency_code"
9836
+ },
9837
+ {
9838
+ enabled: !!id
9839
+ }
9840
+ );
9841
+ const { onCancel } = useCancelOrderEdit({ preview });
9885
9842
  if (isError) {
9886
9843
  throw error;
9887
9844
  }
9888
- const isReady = !isPending && !!order;
9889
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9890
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9891
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
9892
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
9893
- ] }),
9894
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
9895
- ] });
9845
+ if (isPreviewError) {
9846
+ throw previewError;
9847
+ }
9848
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
9849
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
9850
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
9851
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
9852
+ ] }) });
9896
9853
  };
9897
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
9898
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
9899
- const MetadataForm = ({ orderId, metadata }) => {
9854
+ const ItemsForm = ({ preview, currencyCode }) => {
9855
+ var _a;
9856
+ const [isSubmitting, setIsSubmitting] = useState(false);
9857
+ const [modalContent, setModalContent] = useState(
9858
+ null
9859
+ );
9900
9860
  const { handleSuccess } = useRouteModal();
9901
- const hasUneditableRows = getHasUneditableRows(metadata);
9902
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
9903
- const form = useForm({
9904
- defaultValues: {
9905
- metadata: getDefaultValues(metadata)
9906
- },
9907
- resolver: zodResolver(MetadataSchema)
9908
- });
9909
- const handleSubmit = form.handleSubmit(async (data) => {
9910
- const parsedData = parseValues(data);
9911
- await mutateAsync(
9912
- {
9913
- metadata: parsedData
9861
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
9862
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
9863
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
9864
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
9865
+ const matches = useMemo(() => {
9866
+ return matchSorter(preview.items, query2, {
9867
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
9868
+ });
9869
+ }, [preview.items, query2]);
9870
+ const onSubmit = async () => {
9871
+ setIsSubmitting(true);
9872
+ let requestSucceeded = false;
9873
+ await requestOrderEdit(void 0, {
9874
+ onError: (e) => {
9875
+ toast.error(`Failed to request order edit: ${e.message}`);
9914
9876
  },
9915
- {
9916
- onSuccess: () => {
9917
- toast.success("Metadata updated");
9918
- handleSuccess();
9919
- },
9920
- onError: (error) => {
9921
- toast.error(error.message);
9922
- }
9877
+ onSuccess: () => {
9878
+ requestSucceeded = true;
9923
9879
  }
9924
- );
9925
- });
9926
- const { fields, insert, remove } = useFieldArray({
9927
- control: form.control,
9928
- name: "metadata"
9929
- });
9930
- function deleteRow(index) {
9931
- remove(index);
9932
- if (fields.length === 1) {
9933
- insert(0, {
9934
- key: "",
9935
- value: "",
9936
- disabled: false
9937
- });
9880
+ });
9881
+ if (!requestSucceeded) {
9882
+ setIsSubmitting(false);
9883
+ return;
9938
9884
  }
9939
- }
9940
- function insertRow(index, position) {
9941
- insert(index + (position === "above" ? 0 : 1), {
9942
- key: "",
9943
- value: "",
9944
- disabled: false
9885
+ await confirmOrderEdit(void 0, {
9886
+ onError: (e) => {
9887
+ toast.error(`Failed to confirm order edit: ${e.message}`);
9888
+ },
9889
+ onSuccess: () => {
9890
+ handleSuccess();
9891
+ },
9892
+ onSettled: () => {
9893
+ setIsSubmitting(false);
9894
+ }
9945
9895
  });
9946
- }
9947
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9948
- KeyboundForm,
9949
- {
9950
- onSubmit: handleSubmit,
9951
- className: "flex flex-1 flex-col overflow-hidden",
9952
- children: [
9953
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
9954
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
9955
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
9956
- /* @__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" }) }),
9957
- /* @__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" }) })
9896
+ };
9897
+ const onKeyDown = useCallback(
9898
+ (e) => {
9899
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
9900
+ if (modalContent || isSubmitting) {
9901
+ return;
9902
+ }
9903
+ onSubmit();
9904
+ }
9905
+ },
9906
+ [modalContent, isSubmitting, onSubmit]
9907
+ );
9908
+ useEffect(() => {
9909
+ document.addEventListener("keydown", onKeyDown);
9910
+ return () => {
9911
+ document.removeEventListener("keydown", onKeyDown);
9912
+ };
9913
+ }, [onKeyDown]);
9914
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
9915
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
9916
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
9917
+ StackedFocusModal,
9918
+ {
9919
+ id: STACKED_MODAL_ID,
9920
+ onOpenChangeCallback: (open) => {
9921
+ if (!open) {
9922
+ setModalContent(null);
9923
+ }
9924
+ },
9925
+ children: [
9926
+ /* @__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: [
9927
+ /* @__PURE__ */ jsxs("div", { children: [
9928
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
9929
+ /* @__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." }) })
9958
9930
  ] }),
9959
- fields.map((field, index) => {
9960
- const isDisabled = field.disabled || false;
9961
- let placeholder = "-";
9962
- if (typeof field.value === "object") {
9963
- placeholder = "{ ... }";
9964
- }
9965
- if (Array.isArray(field.value)) {
9966
- placeholder = "[ ... ]";
9967
- }
9968
- return /* @__PURE__ */ jsx(
9969
- ConditionalTooltip,
9970
- {
9971
- showTooltip: isDisabled,
9972
- content: "This row is disabled because it contains non-primitive data.",
9973
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
9974
- /* @__PURE__ */ jsxs(
9975
- "div",
9976
- {
9977
- className: clx("grid grid-cols-2 divide-x", {
9978
- "overflow-hidden rounded-b-lg": index === fields.length - 1
9979
- }),
9980
- children: [
9981
- /* @__PURE__ */ jsx(
9982
- Form$2.Field,
9983
- {
9984
- control: form.control,
9985
- name: `metadata.${index}.key`,
9986
- render: ({ field: field2 }) => {
9987
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
9988
- GridInput,
9989
- {
9990
- "aria-labelledby": METADATA_KEY_LABEL_ID,
9991
- ...field2,
9992
- disabled: isDisabled,
9993
- placeholder: "Key"
9994
- }
9995
- ) }) });
9996
- }
9997
- }
9998
- ),
9999
- /* @__PURE__ */ jsx(
10000
- Form$2.Field,
10001
- {
10002
- control: form.control,
10003
- name: `metadata.${index}.value`,
10004
- render: ({ field: { value, ...field2 } }) => {
10005
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10006
- GridInput,
10007
- {
10008
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10009
- ...field2,
10010
- value: isDisabled ? placeholder : value,
10011
- disabled: isDisabled,
10012
- placeholder: "Value"
10013
- }
10014
- ) }) });
10015
- }
10016
- }
10017
- )
10018
- ]
10019
- }
10020
- ),
10021
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
9931
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
9932
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
9933
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
9934
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
9935
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
9936
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
9937
+ ] }),
9938
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9939
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
9940
+ Input,
9941
+ {
9942
+ type: "search",
9943
+ placeholder: "Search items",
9944
+ value: searchValue,
9945
+ onChange: (e) => onSearchValueChange(e.target.value)
9946
+ }
9947
+ ) }),
9948
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
9949
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
9950
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10022
9951
  /* @__PURE__ */ jsx(
10023
- DropdownMenu.Trigger,
9952
+ StackedModalTrigger$1,
10024
9953
  {
10025
- className: clx(
10026
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10027
- {
10028
- hidden: isDisabled
10029
- }
10030
- ),
10031
- disabled: isDisabled,
10032
- asChild: true,
10033
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
9954
+ type: "add-items",
9955
+ setModalContent
10034
9956
  }
10035
9957
  ),
10036
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10037
- /* @__PURE__ */ jsxs(
10038
- DropdownMenu.Item,
10039
- {
10040
- className: "gap-x-2",
10041
- onClick: () => insertRow(index, "above"),
10042
- children: [
10043
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10044
- "Insert row above"
10045
- ]
10046
- }
10047
- ),
10048
- /* @__PURE__ */ jsxs(
10049
- DropdownMenu.Item,
10050
- {
10051
- className: "gap-x-2",
10052
- onClick: () => insertRow(index, "below"),
10053
- children: [
10054
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10055
- "Insert row below"
10056
- ]
10057
- }
10058
- ),
10059
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10060
- /* @__PURE__ */ jsxs(
10061
- DropdownMenu.Item,
10062
- {
10063
- className: "gap-x-2",
10064
- onClick: () => deleteRow(index),
10065
- children: [
10066
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10067
- "Delete row"
10068
- ]
10069
- }
10070
- )
10071
- ] })
9958
+ /* @__PURE__ */ jsx(
9959
+ StackedModalTrigger$1,
9960
+ {
9961
+ type: "add-custom-item",
9962
+ setModalContent
9963
+ }
9964
+ )
10072
9965
  ] })
10073
9966
  ] })
10074
- },
10075
- field.id
10076
- );
10077
- })
10078
- ] }),
10079
- 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." })
10080
- ] }),
10081
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10082
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10083
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10084
- ] }) })
10085
- ]
10086
- }
10087
- ) });
10088
- };
10089
- const GridInput = forwardRef(({ className, ...props }, ref) => {
10090
- return /* @__PURE__ */ jsx(
10091
- "input",
10092
- {
10093
- ref,
10094
- ...props,
10095
- autoComplete: "off",
10096
- className: clx(
10097
- "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",
10098
- className
10099
- )
10100
- }
10101
- );
10102
- });
10103
- GridInput.displayName = "MetadataForm.GridInput";
10104
- const PlaceholderInner = () => {
10105
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10106
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10107
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10108
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10109
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10110
- ] }) })
10111
- ] });
10112
- };
10113
- const EDITABLE_TYPES = ["string", "number", "boolean"];
10114
- function getDefaultValues(metadata) {
10115
- if (!metadata || !Object.keys(metadata).length) {
10116
- return [
10117
- {
10118
- key: "",
10119
- value: "",
10120
- disabled: false
10121
- }
10122
- ];
10123
- }
10124
- return Object.entries(metadata).map(([key, value]) => {
10125
- if (!EDITABLE_TYPES.includes(typeof value)) {
10126
- return {
10127
- key,
10128
- value,
10129
- disabled: true
10130
- };
10131
- }
10132
- let stringValue = value;
10133
- if (typeof value !== "string") {
10134
- stringValue = JSON.stringify(value);
10135
- }
10136
- return {
10137
- key,
10138
- value: stringValue,
10139
- original_key: key
10140
- };
10141
- });
10142
- }
10143
- function parseValues(values) {
10144
- const metadata = values.metadata;
10145
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10146
- if (isEmpty) {
10147
- return null;
10148
- }
10149
- const update = {};
10150
- metadata.forEach((field) => {
10151
- let key = field.key;
10152
- let value = field.value;
10153
- const disabled = field.disabled;
10154
- if (!key || !value) {
10155
- return;
10156
- }
10157
- if (disabled) {
10158
- update[key] = value;
10159
- return;
10160
- }
10161
- key = key.trim();
10162
- value = value.trim();
10163
- if (value === "true") {
10164
- update[key] = true;
10165
- } else if (value === "false") {
10166
- update[key] = false;
10167
- } else {
10168
- const parsedNumber = parseFloat(value);
10169
- if (!isNaN(parsedNumber)) {
10170
- update[key] = parsedNumber;
10171
- } else {
10172
- update[key] = value;
10173
- }
10174
- }
10175
- });
10176
- return update;
10177
- }
10178
- function getHasUneditableRows(metadata) {
10179
- if (!metadata) {
10180
- return false;
10181
- }
10182
- return Object.values(metadata).some(
10183
- (value) => !EDITABLE_TYPES.includes(typeof value)
10184
- );
10185
- }
10186
- const PROMOTION_QUERY_KEY = "promotions";
10187
- const promotionsQueryKeys = {
10188
- list: (query2) => [
10189
- PROMOTION_QUERY_KEY,
10190
- query2 ? query2 : void 0
10191
- ],
10192
- detail: (id, query2) => [
10193
- PROMOTION_QUERY_KEY,
10194
- id,
10195
- query2 ? query2 : void 0
10196
- ]
10197
- };
10198
- const usePromotions = (query2, options) => {
10199
- const { data, ...rest } = useQuery({
10200
- queryKey: promotionsQueryKeys.list(query2),
10201
- queryFn: async () => sdk.admin.promotion.list(query2),
10202
- ...options
10203
- });
10204
- return { ...data, ...rest };
10205
- };
10206
- const useCancelOrderEdit = ({ preview }) => {
10207
- const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
10208
- const onCancel = useCallback(async () => {
10209
- if (!preview) {
10210
- return true;
10211
- }
10212
- let res = false;
10213
- await cancelOrderEdit(void 0, {
10214
- onError: (e) => {
10215
- toast.error(e.message);
10216
- },
10217
- onSuccess: () => {
10218
- res = true;
10219
- }
10220
- });
10221
- return res;
10222
- }, [preview, cancelOrderEdit]);
10223
- return { onCancel };
10224
- };
10225
- let IS_REQUEST_RUNNING = false;
10226
- const useInitiateOrderEdit = ({
10227
- preview
10228
- }) => {
10229
- const navigate = useNavigate();
10230
- const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
10231
- useEffect(() => {
10232
- async function run() {
10233
- if (IS_REQUEST_RUNNING || !preview) {
10234
- return;
10235
- }
10236
- if (preview.order_change) {
10237
- return;
9967
+ ] })
9968
+ ] }),
9969
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
9970
+ /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
9971
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
9972
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
9973
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
9974
+ /* @__PURE__ */ jsx("div", {})
9975
+ ] }) }),
9976
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
9977
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
9978
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
9979
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
9980
+ Item,
9981
+ {
9982
+ item,
9983
+ preview,
9984
+ currencyCode
9985
+ },
9986
+ item.id
9987
+ )) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
9988
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
9989
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
9990
+ 'No items found for "',
9991
+ query2,
9992
+ '".'
9993
+ ] })
9994
+ ] }) })
9995
+ ] })
9996
+ ] }),
9997
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
9998
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
9999
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10000
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10001
+ Text,
10002
+ {
10003
+ size: "small",
10004
+ leading: "compact",
10005
+ className: "text-ui-fg-subtle",
10006
+ children: [
10007
+ itemCount,
10008
+ " ",
10009
+ itemCount === 1 ? "item" : "items"
10010
+ ]
10011
+ }
10012
+ ) }),
10013
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10014
+ ] })
10015
+ ] }) }),
10016
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10017
+ CustomItemForm,
10018
+ {
10019
+ orderId: preview.id,
10020
+ currencyCode
10021
+ }
10022
+ ) : null)
10023
+ ]
10238
10024
  }
10239
- IS_REQUEST_RUNNING = true;
10240
- await mutateAsync(void 0, {
10241
- onError: (e) => {
10242
- toast.error(e.message);
10243
- navigate(`/draft-orders/${preview.id}`, { replace: true });
10244
- return;
10025
+ ) }),
10026
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10027
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10028
+ /* @__PURE__ */ jsx(
10029
+ Button,
10030
+ {
10031
+ size: "small",
10032
+ type: "button",
10033
+ onClick: onSubmit,
10034
+ isLoading: isSubmitting,
10035
+ children: "Save"
10245
10036
  }
10246
- });
10247
- IS_REQUEST_RUNNING = false;
10248
- }
10249
- run();
10250
- }, [preview, navigate, mutateAsync]);
10037
+ )
10038
+ ] }) })
10039
+ ] });
10251
10040
  };
10252
- const Promotions = () => {
10253
- const { id } = useParams();
10254
- const {
10255
- order: preview,
10256
- isError: isPreviewError,
10257
- error: previewError
10258
- } = useOrderPreview(id, void 0);
10259
- useInitiateOrderEdit({ preview });
10260
- const { onCancel } = useCancelOrderEdit({ preview });
10261
- if (isPreviewError) {
10262
- throw previewError;
10041
+ const Item = ({ item, preview, currencyCode }) => {
10042
+ if (item.variant_id) {
10043
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10263
10044
  }
10264
- const isReady = !!preview;
10265
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10266
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10267
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10268
- ] });
10045
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10269
10046
  };
10270
- const PromotionForm = ({ preview }) => {
10271
- const { items, shipping_methods } = preview;
10272
- const [isSubmitting, setIsSubmitting] = useState(false);
10273
- const [comboboxValue, setComboboxValue] = useState("");
10274
- const { handleSuccess } = useRouteModal();
10275
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10276
- const promoCodes = getPromotionCodes(items, shipping_methods);
10277
- const { promotions, isPending, isError, error } = usePromotions(
10278
- {
10279
- code: promoCodes
10047
+ const VariantItem = ({ item, preview, currencyCode }) => {
10048
+ const [editing, setEditing] = useState(false);
10049
+ const form = useForm({
10050
+ defaultValues: {
10051
+ quantity: item.quantity,
10052
+ unit_price: item.unit_price
10280
10053
  },
10281
- {
10282
- enabled: !!promoCodes.length
10054
+ resolver: zodResolver(variantItemSchema)
10055
+ });
10056
+ const actionId = useMemo(() => {
10057
+ var _a, _b;
10058
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10059
+ }, [item]);
10060
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10061
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10062
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10063
+ const onSubmit = form.handleSubmit(async (data) => {
10064
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10065
+ setEditing(false);
10066
+ return;
10283
10067
  }
10284
- );
10285
- const comboboxData = useComboboxData({
10286
- queryKey: ["promotions", "combobox", promoCodes],
10287
- queryFn: async (params) => {
10288
- return await sdk.admin.promotion.list({
10289
- ...params,
10290
- code: {
10291
- $nin: promoCodes
10068
+ if (!actionId) {
10069
+ await updateOriginalItem(
10070
+ {
10071
+ item_id: item.id,
10072
+ quantity: data.quantity,
10073
+ unit_price: convertNumber(data.unit_price)
10074
+ },
10075
+ {
10076
+ onSuccess: () => {
10077
+ setEditing(false);
10078
+ },
10079
+ onError: (e) => {
10080
+ toast.error(e.message);
10081
+ }
10292
10082
  }
10293
- });
10294
- },
10295
- getOptions: (data) => {
10296
- return data.promotions.map((promotion) => ({
10297
- label: promotion.code,
10298
- value: promotion.code
10299
- }));
10300
- }
10301
- });
10302
- const add = async (value) => {
10303
- if (!value) {
10083
+ );
10304
10084
  return;
10305
10085
  }
10306
- addPromotions(
10086
+ await updateActionItem(
10307
10087
  {
10308
- promo_codes: [value]
10088
+ action_id: actionId,
10089
+ quantity: data.quantity,
10090
+ unit_price: convertNumber(data.unit_price)
10309
10091
  },
10310
10092
  {
10311
- onError: (e) => {
10312
- toast.error(e.message);
10313
- comboboxData.onSearchValueChange("");
10314
- setComboboxValue("");
10315
- },
10316
10093
  onSuccess: () => {
10317
- comboboxData.onSearchValueChange("");
10318
- setComboboxValue("");
10094
+ setEditing(false);
10095
+ },
10096
+ onError: (e) => {
10097
+ toast.error(e.message);
10319
10098
  }
10320
10099
  }
10321
10100
  );
10322
- };
10323
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10324
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10325
- const onSubmit = async () => {
10326
- setIsSubmitting(true);
10327
- let requestSucceeded = false;
10328
- await requestOrderEdit(void 0, {
10329
- onError: (e) => {
10330
- toast.error(e.message);
10331
- },
10332
- onSuccess: () => {
10333
- requestSucceeded = true;
10334
- }
10335
- });
10336
- if (!requestSucceeded) {
10337
- setIsSubmitting(false);
10338
- return;
10339
- }
10340
- await confirmOrderEdit(void 0, {
10341
- onError: (e) => {
10342
- toast.error(e.message);
10343
- },
10344
- onSuccess: () => {
10345
- handleSuccess();
10346
- },
10347
- onSettled: () => {
10348
- setIsSubmitting(false);
10349
- }
10350
- });
10351
- };
10352
- if (isError) {
10353
- throw error;
10354
- }
10355
- return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10356
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10357
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10358
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10359
- /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10360
- /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10101
+ });
10102
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10103
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
10104
+ /* @__PURE__ */ jsx(
10105
+ Thumbnail,
10106
+ {
10107
+ thumbnail: item.thumbnail,
10108
+ alt: item.product_title ?? void 0
10109
+ }
10110
+ ),
10111
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10112
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10113
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10114
+ /* @__PURE__ */ jsxs(
10115
+ Text,
10116
+ {
10117
+ size: "small",
10118
+ leading: "compact",
10119
+ className: "text-ui-fg-subtle",
10120
+ children: [
10121
+ "(",
10122
+ item.variant_title,
10123
+ ")"
10124
+ ]
10125
+ }
10126
+ )
10361
10127
  ] }),
10362
10128
  /* @__PURE__ */ jsx(
10363
- Combobox,
10129
+ Text,
10364
10130
  {
10365
- id: "promotion-combobox",
10366
- "aria-describedby": "promotion-combobox-hint",
10367
- isFetchingNextPage: comboboxData.isFetchingNextPage,
10368
- fetchNextPage: comboboxData.fetchNextPage,
10369
- options: comboboxData.options,
10370
- onSearchValueChange: comboboxData.onSearchValueChange,
10371
- searchValue: comboboxData.searchValue,
10372
- disabled: comboboxData.disabled || isAddingPromotions,
10373
- onChange: add,
10374
- value: comboboxValue
10131
+ size: "small",
10132
+ leading: "compact",
10133
+ className: "text-ui-fg-subtle",
10134
+ children: item.variant_sku
10375
10135
  }
10376
10136
  )
10377
- ] }),
10378
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10379
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10380
- PromotionItem,
10137
+ ] })
10138
+ ] }),
10139
+ editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
10140
+ Form$2.Field,
10141
+ {
10142
+ control: form.control,
10143
+ name: "quantity",
10144
+ render: ({ field }) => {
10145
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10146
+ }
10147
+ }
10148
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10149
+ editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
10150
+ Form$2.Field,
10151
+ {
10152
+ control: form.control,
10153
+ name: "unit_price",
10154
+ render: ({ field: { onChange, ...field } }) => {
10155
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10156
+ CurrencyInput,
10157
+ {
10158
+ ...field,
10159
+ symbol: getNativeSymbol(currencyCode),
10160
+ code: currencyCode,
10161
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10162
+ }
10163
+ ) }) });
10164
+ }
10165
+ }
10166
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10167
+ /* @__PURE__ */ jsx(
10168
+ IconButton,
10169
+ {
10170
+ type: "button",
10171
+ size: "small",
10172
+ onClick: editing ? onSubmit : () => {
10173
+ setEditing(true);
10174
+ },
10175
+ disabled: isPending,
10176
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10177
+ }
10178
+ )
10179
+ ] }) }) });
10180
+ };
10181
+ const variantItemSchema = objectType({
10182
+ quantity: numberType(),
10183
+ unit_price: unionType([numberType(), stringType()])
10184
+ });
10185
+ const CustomItem = ({ item, preview, currencyCode }) => {
10186
+ const [editing, setEditing] = useState(false);
10187
+ const { quantity, unit_price, title } = item;
10188
+ const form = useForm({
10189
+ defaultValues: {
10190
+ title,
10191
+ quantity,
10192
+ unit_price
10193
+ },
10194
+ resolver: zodResolver(customItemSchema)
10195
+ });
10196
+ useEffect(() => {
10197
+ form.reset({
10198
+ title,
10199
+ quantity,
10200
+ unit_price
10201
+ });
10202
+ }, [form, title, quantity, unit_price]);
10203
+ const actionId = useMemo(() => {
10204
+ var _a, _b;
10205
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10206
+ }, [item]);
10207
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10208
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10209
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10210
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10211
+ const onSubmit = form.handleSubmit(async (data) => {
10212
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10213
+ setEditing(false);
10214
+ return;
10215
+ }
10216
+ if (!actionId) {
10217
+ await updateOriginalItem(
10381
10218
  {
10382
- promotion,
10383
- orderId: preview.id,
10384
- isLoading: isPending
10219
+ item_id: item.id,
10220
+ quantity: data.quantity,
10221
+ unit_price: convertNumber(data.unit_price)
10385
10222
  },
10386
- promotion.id
10387
- )) })
10388
- ] }) }),
10389
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10390
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10391
- /* @__PURE__ */ jsx(
10392
- Button,
10393
10223
  {
10394
- size: "small",
10395
- type: "submit",
10396
- isLoading: isSubmitting || isAddingPromotions,
10397
- children: "Save"
10224
+ onSuccess: () => {
10225
+ setEditing(false);
10226
+ },
10227
+ onError: (e) => {
10228
+ toast.error(e.message);
10229
+ }
10398
10230
  }
10399
- )
10400
- ] }) })
10401
- ] });
10402
- };
10403
- const PromotionItem = ({
10404
- promotion,
10405
- orderId,
10406
- isLoading
10407
- }) => {
10408
- var _a;
10409
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10410
- const onRemove = async () => {
10411
- removePromotions(
10231
+ );
10232
+ return;
10233
+ }
10234
+ if (data.quantity === 0) {
10235
+ await removeActionItem(actionId, {
10236
+ onSuccess: () => {
10237
+ setEditing(false);
10238
+ },
10239
+ onError: (e) => {
10240
+ toast.error(e.message);
10241
+ }
10242
+ });
10243
+ return;
10244
+ }
10245
+ await updateActionItem(
10412
10246
  {
10413
- promo_codes: [promotion.code]
10247
+ action_id: actionId,
10248
+ quantity: data.quantity,
10249
+ unit_price: convertNumber(data.unit_price)
10414
10250
  },
10415
10251
  {
10252
+ onSuccess: () => {
10253
+ setEditing(false);
10254
+ },
10416
10255
  onError: (e) => {
10417
10256
  toast.error(e.message);
10418
10257
  }
10419
10258
  }
10420
10259
  );
10421
- };
10422
- const displayValue = getDisplayValue(promotion);
10423
- return /* @__PURE__ */ jsxs(
10424
- "div",
10425
- {
10426
- className: clx(
10427
- "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
10260
+ });
10261
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10262
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10263
+ /* @__PURE__ */ jsx(
10264
+ Thumbnail,
10428
10265
  {
10429
- "animate-pulse": isLoading
10266
+ thumbnail: item.thumbnail,
10267
+ alt: item.title ?? void 0
10430
10268
  }
10431
10269
  ),
10432
- children: [
10433
- /* @__PURE__ */ jsxs("div", { children: [
10434
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10435
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
10436
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
10437
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
10438
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
10439
- ] }),
10440
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10441
- ] })
10442
- ] }),
10443
- /* @__PURE__ */ jsx(
10444
- IconButton,
10445
- {
10446
- size: "small",
10447
- type: "button",
10448
- variant: "transparent",
10449
- onClick: onRemove,
10450
- isLoading: isPending || isLoading,
10451
- children: /* @__PURE__ */ jsx(XMark, {})
10270
+ editing ? /* @__PURE__ */ jsx(
10271
+ Form$2.Field,
10272
+ {
10273
+ control: form.control,
10274
+ name: "title",
10275
+ render: ({ field }) => {
10276
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10452
10277
  }
10453
- )
10454
- ]
10455
- },
10456
- promotion.id
10457
- );
10458
- };
10459
- function getDisplayValue(promotion) {
10460
- var _a, _b, _c, _d;
10461
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10462
- if (!value) {
10463
- return null;
10464
- }
10465
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10466
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10467
- if (!currency) {
10468
- return null;
10469
- }
10470
- return getLocaleAmount(value, currency);
10471
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10472
- return formatPercentage(value);
10473
- }
10474
- return null;
10475
- }
10476
- const formatter = new Intl.NumberFormat([], {
10477
- style: "percent",
10478
- minimumFractionDigits: 2
10479
- });
10480
- const formatPercentage = (value, isPercentageValue = false) => {
10481
- let val = value || 0;
10482
- if (!isPercentageValue) {
10483
- val = val / 100;
10484
- }
10485
- return formatter.format(val);
10486
- };
10487
- function getPromotionCodes(items, shippingMethods) {
10488
- const codes = /* @__PURE__ */ new Set();
10489
- for (const item of items) {
10490
- if (item.adjustments) {
10491
- for (const adjustment of item.adjustments) {
10492
- if (adjustment.code) {
10493
- codes.add(adjustment.code);
10278
+ }
10279
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10280
+ ] }),
10281
+ editing ? /* @__PURE__ */ jsx(
10282
+ Form$2.Field,
10283
+ {
10284
+ control: form.control,
10285
+ name: "quantity",
10286
+ render: ({ field }) => {
10287
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10494
10288
  }
10495
10289
  }
10496
- }
10497
- }
10498
- for (const shippingMethod of shippingMethods) {
10499
- if (shippingMethod.adjustments) {
10500
- for (const adjustment of shippingMethod.adjustments) {
10501
- if (adjustment.code) {
10502
- codes.add(adjustment.code);
10290
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10291
+ editing ? /* @__PURE__ */ jsx(
10292
+ Form$2.Field,
10293
+ {
10294
+ control: form.control,
10295
+ name: "unit_price",
10296
+ render: ({ field: { onChange, ...field } }) => {
10297
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10298
+ CurrencyInput,
10299
+ {
10300
+ ...field,
10301
+ symbol: getNativeSymbol(currencyCode),
10302
+ code: currencyCode,
10303
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10304
+ }
10305
+ ) }) });
10503
10306
  }
10504
10307
  }
10505
- }
10506
- }
10507
- return Array.from(codes);
10508
- }
10509
- const SalesChannel = () => {
10510
- const { id } = useParams();
10511
- const { draft_order, isPending, isError, error } = useDraftOrder(
10512
- id,
10308
+ ) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10309
+ /* @__PURE__ */ jsx(
10310
+ IconButton,
10311
+ {
10312
+ type: "button",
10313
+ size: "small",
10314
+ onClick: editing ? onSubmit : () => {
10315
+ setEditing(true);
10316
+ },
10317
+ disabled: isPending,
10318
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10319
+ }
10320
+ )
10321
+ ] }) }) });
10322
+ };
10323
+ const StackedModalTrigger$1 = ({
10324
+ type,
10325
+ setModalContent
10326
+ }) => {
10327
+ const { setIsOpen } = useStackedModal();
10328
+ const onClick = useCallback(() => {
10329
+ setModalContent(type);
10330
+ setIsOpen(STACKED_MODAL_ID, true);
10331
+ }, [setModalContent, setIsOpen, type]);
10332
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10333
+ };
10334
+ const VARIANT_PREFIX = "items";
10335
+ const LIMIT = 50;
10336
+ const ExistingItemsForm = ({ orderId, items }) => {
10337
+ const { setIsOpen } = useStackedModal();
10338
+ const [rowSelection, setRowSelection] = useState(
10339
+ items.reduce((acc, item) => {
10340
+ acc[item.variant_id] = true;
10341
+ return acc;
10342
+ }, {})
10343
+ );
10344
+ useEffect(() => {
10345
+ setRowSelection(
10346
+ items.reduce((acc, item) => {
10347
+ if (item.variant_id) {
10348
+ acc[item.variant_id] = true;
10349
+ }
10350
+ return acc;
10351
+ }, {})
10352
+ );
10353
+ }, [items]);
10354
+ const { q, order, offset } = useQueryParams(
10355
+ ["q", "order", "offset"],
10356
+ VARIANT_PREFIX
10357
+ );
10358
+ const { variants, count, isPending, isError, error } = useProductVariants(
10513
10359
  {
10514
- fields: "+sales_channel_id"
10360
+ q,
10361
+ order,
10362
+ offset: offset ? parseInt(offset) : void 0,
10363
+ limit: LIMIT
10515
10364
  },
10516
10365
  {
10517
- enabled: !!id
10366
+ placeholderData: keepPreviousData
10518
10367
  }
10519
10368
  );
10520
- if (isError) {
10521
- throw error;
10522
- }
10523
- const ISrEADY = !!draft_order && !isPending;
10524
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10525
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10526
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
10527
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
10528
- ] }),
10529
- ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
10530
- ] });
10531
- };
10532
- const SalesChannelForm = ({ order }) => {
10533
- const form = useForm({
10534
- defaultValues: {
10535
- sales_channel_id: order.sales_channel_id || ""
10536
- },
10537
- resolver: zodResolver(schema$2)
10538
- });
10539
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10540
- const { handleSuccess } = useRouteModal();
10541
- const onSubmit = form.handleSubmit(async (data) => {
10369
+ const columns = useColumns();
10370
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10371
+ const onSubmit = async () => {
10372
+ const ids = Object.keys(rowSelection).filter(
10373
+ (id) => !items.find((i) => i.variant_id === id)
10374
+ );
10542
10375
  await mutateAsync(
10543
10376
  {
10544
- sales_channel_id: data.sales_channel_id
10377
+ items: ids.map((id) => ({
10378
+ variant_id: id,
10379
+ quantity: 1
10380
+ }))
10545
10381
  },
10546
10382
  {
10547
10383
  onSuccess: () => {
10548
- toast.success("Sales channel updated");
10549
- handleSuccess();
10384
+ setRowSelection({});
10385
+ setIsOpen(STACKED_MODAL_ID, false);
10550
10386
  },
10551
- onError: (error) => {
10552
- toast.error(error.message);
10387
+ onError: (e) => {
10388
+ toast.error(e.message);
10553
10389
  }
10554
10390
  }
10555
10391
  );
10556
- });
10557
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10558
- KeyboundForm,
10392
+ };
10393
+ if (isError) {
10394
+ throw error;
10395
+ }
10396
+ return /* @__PURE__ */ jsxs(
10397
+ StackedFocusModal.Content,
10559
10398
  {
10560
- className: "flex flex-1 flex-col overflow-hidden",
10561
- onSubmit,
10399
+ onOpenAutoFocus: (e) => {
10400
+ e.preventDefault();
10401
+ const searchInput = document.querySelector(
10402
+ "[data-modal-id='modal-search-input']"
10403
+ );
10404
+ if (searchInput) {
10405
+ searchInput.focus();
10406
+ }
10407
+ },
10562
10408
  children: [
10563
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
10564
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10565
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10566
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10409
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10410
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10411
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10412
+ ] }),
10413
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10414
+ DataTable,
10415
+ {
10416
+ data: variants,
10417
+ columns,
10418
+ isLoading: isPending,
10419
+ getRowId: (row) => row.id,
10420
+ rowCount: count,
10421
+ prefix: VARIANT_PREFIX,
10422
+ layout: "fill",
10423
+ rowSelection: {
10424
+ state: rowSelection,
10425
+ onRowSelectionChange: setRowSelection,
10426
+ enableRowSelection: (row) => {
10427
+ return !items.find((i) => i.variant_id === row.original.id);
10428
+ }
10429
+ },
10430
+ autoFocusSearch: true
10431
+ }
10432
+ ) }),
10433
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10434
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10435
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10567
10436
  ] }) })
10568
10437
  ]
10569
10438
  }
10570
- ) });
10439
+ );
10571
10440
  };
10572
- const SalesChannelField = ({ control, order }) => {
10573
- const salesChannels = useComboboxData({
10574
- queryFn: async (params) => {
10575
- return await sdk.admin.salesChannel.list(params);
10576
- },
10577
- queryKey: ["sales-channels"],
10578
- getOptions: (data) => {
10579
- return data.sales_channels.map((salesChannel) => ({
10580
- label: salesChannel.name,
10581
- value: salesChannel.id
10582
- }));
10583
- },
10584
- defaultValue: order.sales_channel_id || void 0
10585
- });
10586
- return /* @__PURE__ */ jsx(
10587
- Form$2.Field,
10588
- {
10589
- control,
10590
- name: "sales_channel_id",
10591
- render: ({ field }) => {
10592
- return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
10593
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
10594
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10595
- Combobox,
10441
+ const columnHelper = createDataTableColumnHelper();
10442
+ const useColumns = () => {
10443
+ return useMemo(() => {
10444
+ return [
10445
+ columnHelper.select(),
10446
+ columnHelper.accessor("product.title", {
10447
+ header: "Product",
10448
+ cell: ({ row }) => {
10449
+ var _a, _b, _c;
10450
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10451
+ /* @__PURE__ */ jsx(
10452
+ Thumbnail,
10453
+ {
10454
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10455
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
10456
+ }
10457
+ ),
10458
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10459
+ ] });
10460
+ },
10461
+ enableSorting: true
10462
+ }),
10463
+ columnHelper.accessor("title", {
10464
+ header: "Variant",
10465
+ enableSorting: true
10466
+ }),
10467
+ columnHelper.accessor("sku", {
10468
+ header: "SKU",
10469
+ cell: ({ getValue }) => {
10470
+ return getValue() ?? "-";
10471
+ },
10472
+ enableSorting: true
10473
+ }),
10474
+ columnHelper.accessor("updated_at", {
10475
+ header: "Updated",
10476
+ cell: ({ getValue }) => {
10477
+ return /* @__PURE__ */ jsx(
10478
+ Tooltip,
10596
10479
  {
10597
- options: salesChannels.options,
10598
- fetchNextPage: salesChannels.fetchNextPage,
10599
- isFetchingNextPage: salesChannels.isFetchingNextPage,
10600
- searchValue: salesChannels.searchValue,
10601
- onSearchValueChange: salesChannels.onSearchValueChange,
10602
- placeholder: "Select sales channel",
10603
- ...field
10480
+ content: getFullDate({ date: getValue(), includeTime: true }),
10481
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10604
10482
  }
10605
- ) }),
10606
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10607
- ] });
10483
+ );
10484
+ },
10485
+ enableSorting: true,
10486
+ sortAscLabel: "Oldest first",
10487
+ sortDescLabel: "Newest first"
10488
+ }),
10489
+ columnHelper.accessor("created_at", {
10490
+ header: "Created",
10491
+ cell: ({ getValue }) => {
10492
+ return /* @__PURE__ */ jsx(
10493
+ Tooltip,
10494
+ {
10495
+ content: getFullDate({ date: getValue(), includeTime: true }),
10496
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10497
+ }
10498
+ );
10499
+ },
10500
+ enableSorting: true,
10501
+ sortAscLabel: "Oldest first",
10502
+ sortDescLabel: "Newest first"
10503
+ })
10504
+ ];
10505
+ }, []);
10506
+ };
10507
+ const CustomItemForm = ({ orderId, currencyCode }) => {
10508
+ const { setIsOpen } = useStackedModal();
10509
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10510
+ const form = useForm({
10511
+ defaultValues: {
10512
+ title: "",
10513
+ quantity: 1,
10514
+ unit_price: ""
10515
+ },
10516
+ resolver: zodResolver(customItemSchema)
10517
+ });
10518
+ const onSubmit = form.handleSubmit(async (data) => {
10519
+ await addItems(
10520
+ {
10521
+ items: [
10522
+ {
10523
+ title: data.title,
10524
+ quantity: data.quantity,
10525
+ unit_price: convertNumber(data.unit_price)
10526
+ }
10527
+ ]
10528
+ },
10529
+ {
10530
+ onSuccess: () => {
10531
+ setIsOpen(STACKED_MODAL_ID, false);
10532
+ },
10533
+ onError: (e) => {
10534
+ toast.error(e.message);
10535
+ }
10608
10536
  }
10609
- }
10610
- );
10537
+ );
10538
+ });
10539
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10540
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10541
+ /* @__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: [
10542
+ /* @__PURE__ */ jsxs("div", { children: [
10543
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10544
+ /* @__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." }) })
10545
+ ] }),
10546
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10547
+ /* @__PURE__ */ jsx(
10548
+ Form$2.Field,
10549
+ {
10550
+ control: form.control,
10551
+ name: "title",
10552
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10553
+ /* @__PURE__ */ jsxs("div", { children: [
10554
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10555
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10556
+ ] }),
10557
+ /* @__PURE__ */ jsxs("div", { children: [
10558
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10559
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10560
+ ] })
10561
+ ] }) })
10562
+ }
10563
+ ),
10564
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10565
+ /* @__PURE__ */ jsx(
10566
+ Form$2.Field,
10567
+ {
10568
+ control: form.control,
10569
+ name: "unit_price",
10570
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10571
+ /* @__PURE__ */ jsxs("div", { children: [
10572
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10573
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10574
+ ] }),
10575
+ /* @__PURE__ */ jsxs("div", { children: [
10576
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10577
+ CurrencyInput,
10578
+ {
10579
+ symbol: getNativeSymbol(currencyCode),
10580
+ code: currencyCode,
10581
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10582
+ ...field
10583
+ }
10584
+ ) }),
10585
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10586
+ ] })
10587
+ ] }) })
10588
+ }
10589
+ ),
10590
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10591
+ /* @__PURE__ */ jsx(
10592
+ Form$2.Field,
10593
+ {
10594
+ control: form.control,
10595
+ name: "quantity",
10596
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10597
+ /* @__PURE__ */ jsxs("div", { children: [
10598
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10599
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10600
+ ] }),
10601
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 w-full", children: [
10602
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10603
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10604
+ ] })
10605
+ ] }) })
10606
+ }
10607
+ )
10608
+ ] }) }) }),
10609
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10610
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10611
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10612
+ ] }) })
10613
+ ] }) }) });
10611
10614
  };
10612
- const schema$2 = objectType({
10613
- sales_channel_id: stringType().min(1)
10615
+ const customItemSchema = objectType({
10616
+ title: stringType().min(1),
10617
+ quantity: numberType(),
10618
+ unit_price: unionType([numberType(), stringType()])
10614
10619
  });
10615
- const NumberInput = forwardRef(
10616
- ({
10617
- value,
10618
- onChange,
10619
- size = "base",
10620
- min = 0,
10621
- max = 100,
10622
- step = 1,
10623
- className,
10624
- disabled,
10625
- ...props
10626
- }, ref) => {
10627
- const handleChange = (event) => {
10628
- const newValue = event.target.value === "" ? min : Number(event.target.value);
10629
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
10630
- onChange(newValue);
10631
- }
10632
- };
10633
- const handleIncrement = () => {
10634
- const newValue = value + step;
10635
- if (max === void 0 || newValue <= max) {
10636
- onChange(newValue);
10637
- }
10638
- };
10639
- const handleDecrement = () => {
10640
- const newValue = value - step;
10641
- if (min === void 0 || newValue >= min) {
10642
- onChange(newValue);
10643
- }
10644
- };
10620
+ const InlineTip = forwardRef(
10621
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
10622
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10645
10623
  return /* @__PURE__ */ jsxs(
10646
10624
  "div",
10647
10625
  {
10626
+ ref,
10648
10627
  className: clx(
10649
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
10650
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
10651
- {
10652
- "h-7": size === "small",
10653
- "h-8": size === "base"
10654
- },
10628
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10655
10629
  className
10656
10630
  ),
10631
+ ...props,
10657
10632
  children: [
10658
10633
  /* @__PURE__ */ jsx(
10659
- "input",
10634
+ "div",
10660
10635
  {
10661
- ref,
10662
- type: "number",
10663
- value,
10664
- onChange: handleChange,
10665
- min,
10666
- max,
10667
- step,
10668
- className: clx(
10669
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
10670
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
10671
- "placeholder:text-ui-fg-muted"
10672
- ),
10673
- ...props
10674
- }
10675
- ),
10676
- /* @__PURE__ */ jsxs(
10677
- "button",
10678
- {
10679
- className: clx(
10680
- "flex items-center justify-center outline-none transition-fg",
10681
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10682
- "focus:bg-ui-bg-field-component-hover",
10683
- "hover:bg-ui-bg-field-component-hover",
10684
- {
10685
- "size-7": size === "small",
10686
- "size-8": size === "base"
10687
- }
10688
- ),
10689
- type: "button",
10690
- onClick: handleDecrement,
10691
- disabled: min !== void 0 && value <= min || disabled,
10692
- children: [
10693
- /* @__PURE__ */ jsx(Minus, {}),
10694
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
10695
- ]
10636
+ role: "presentation",
10637
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10638
+ "bg-ui-tag-orange-icon": variant === "warning"
10639
+ })
10696
10640
  }
10697
10641
  ),
10698
- /* @__PURE__ */ jsxs(
10699
- "button",
10700
- {
10701
- className: clx(
10702
- "flex items-center justify-center outline-none transition-fg",
10703
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10704
- "focus:bg-ui-bg-field-hover",
10705
- "hover:bg-ui-bg-field-hover",
10706
- {
10707
- "size-7": size === "small",
10708
- "size-8": size === "base"
10709
- }
10710
- ),
10711
- type: "button",
10712
- onClick: handleIncrement,
10713
- disabled: max !== void 0 && value >= max || disabled,
10714
- children: [
10715
- /* @__PURE__ */ jsx(Plus, {}),
10716
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
10717
- ]
10718
- }
10719
- )
10642
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10643
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10644
+ labelValue,
10645
+ ":"
10646
+ ] }),
10647
+ " ",
10648
+ children
10649
+ ] })
10720
10650
  ]
10721
10651
  }
10722
10652
  );
10723
10653
  }
10724
10654
  );
10725
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
10726
- const productVariantsQueryKeys = {
10727
- list: (query2) => [
10728
- PRODUCT_VARIANTS_QUERY_KEY,
10729
- query2 ? query2 : void 0
10730
- ]
10731
- };
10732
- const useProductVariants = (query2, options) => {
10733
- const { data, ...rest } = useQuery({
10734
- queryKey: productVariantsQueryKeys.list(query2),
10735
- queryFn: async () => await sdk.admin.productVariant.list(query2),
10736
- ...options
10737
- });
10738
- return { ...data, ...rest };
10739
- };
10740
- function convertNumber(value) {
10741
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10742
- }
10743
- const STACKED_MODAL_ID = "items_stacked_modal";
10744
- const Items = () => {
10655
+ InlineTip.displayName = "InlineTip";
10656
+ const MetadataFieldSchema = objectType({
10657
+ key: stringType(),
10658
+ disabled: booleanType().optional(),
10659
+ value: anyType()
10660
+ });
10661
+ const MetadataSchema = objectType({
10662
+ metadata: arrayType(MetadataFieldSchema)
10663
+ });
10664
+ const Metadata = () => {
10745
10665
  const { id } = useParams();
10746
- const {
10747
- order: preview,
10748
- isPending: isPreviewPending,
10749
- isError: isPreviewError,
10750
- error: previewError
10751
- } = useOrderPreview(id, void 0, {
10752
- placeholderData: keepPreviousData
10666
+ const { order, isPending, isError, error } = useOrder(id, {
10667
+ fields: "metadata"
10753
10668
  });
10754
- useInitiateOrderEdit({ preview });
10755
- const { draft_order, isPending, isError, error } = useDraftOrder(
10756
- id,
10757
- {
10758
- fields: "currency_code"
10759
- },
10760
- {
10761
- enabled: !!id
10762
- }
10763
- );
10764
- const { onCancel } = useCancelOrderEdit({ preview });
10765
10669
  if (isError) {
10766
10670
  throw error;
10767
10671
  }
10768
- if (isPreviewError) {
10769
- throw previewError;
10770
- }
10771
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10772
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10773
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10774
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10775
- ] }) });
10672
+ const isReady = !isPending && !!order;
10673
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10674
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10675
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10676
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10677
+ ] }),
10678
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10679
+ ] });
10776
10680
  };
10777
- const ItemsForm = ({ preview, currencyCode }) => {
10778
- var _a;
10779
- const [isSubmitting, setIsSubmitting] = useState(false);
10780
- const [modalContent, setModalContent] = useState(
10781
- null
10782
- );
10681
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10682
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10683
+ const MetadataForm = ({ orderId, metadata }) => {
10783
10684
  const { handleSuccess } = useRouteModal();
10784
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10785
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10786
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10787
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10788
- const matches = useMemo(() => {
10789
- return matchSorter(preview.items, query2, {
10790
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10791
- });
10792
- }, [preview.items, query2]);
10793
- const onSubmit = async () => {
10794
- setIsSubmitting(true);
10795
- let requestSucceeded = false;
10796
- await requestOrderEdit(void 0, {
10797
- onError: (e) => {
10798
- toast.error(`Failed to request order edit: ${e.message}`);
10685
+ const hasUneditableRows = getHasUneditableRows(metadata);
10686
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10687
+ const form = useForm({
10688
+ defaultValues: {
10689
+ metadata: getDefaultValues(metadata)
10690
+ },
10691
+ resolver: zodResolver(MetadataSchema)
10692
+ });
10693
+ const handleSubmit = form.handleSubmit(async (data) => {
10694
+ const parsedData = parseValues(data);
10695
+ await mutateAsync(
10696
+ {
10697
+ metadata: parsedData
10799
10698
  },
10800
- onSuccess: () => {
10801
- requestSucceeded = true;
10699
+ {
10700
+ onSuccess: () => {
10701
+ toast.success("Metadata updated");
10702
+ handleSuccess();
10703
+ },
10704
+ onError: (error) => {
10705
+ toast.error(error.message);
10706
+ }
10802
10707
  }
10803
- });
10804
- if (!requestSucceeded) {
10805
- setIsSubmitting(false);
10806
- return;
10708
+ );
10709
+ });
10710
+ const { fields, insert, remove } = useFieldArray({
10711
+ control: form.control,
10712
+ name: "metadata"
10713
+ });
10714
+ function deleteRow(index) {
10715
+ remove(index);
10716
+ if (fields.length === 1) {
10717
+ insert(0, {
10718
+ key: "",
10719
+ value: "",
10720
+ disabled: false
10721
+ });
10807
10722
  }
10808
- await confirmOrderEdit(void 0, {
10809
- onError: (e) => {
10810
- toast.error(`Failed to confirm order edit: ${e.message}`);
10811
- },
10812
- onSuccess: () => {
10813
- handleSuccess();
10814
- },
10815
- onSettled: () => {
10816
- setIsSubmitting(false);
10817
- }
10723
+ }
10724
+ function insertRow(index, position) {
10725
+ insert(index + (position === "above" ? 0 : 1), {
10726
+ key: "",
10727
+ value: "",
10728
+ disabled: false
10818
10729
  });
10819
- };
10820
- const onKeyDown = useCallback(
10821
- (e) => {
10822
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10823
- if (modalContent || isSubmitting) {
10824
- return;
10825
- }
10826
- onSubmit();
10827
- }
10828
- },
10829
- [modalContent, isSubmitting, onSubmit]
10830
- );
10831
- useEffect(() => {
10832
- document.addEventListener("keydown", onKeyDown);
10833
- return () => {
10834
- document.removeEventListener("keydown", onKeyDown);
10835
- };
10836
- }, [onKeyDown]);
10837
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10838
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10839
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10840
- StackedFocusModal,
10841
- {
10842
- id: STACKED_MODAL_ID,
10843
- onOpenChangeCallback: (open) => {
10844
- if (!open) {
10845
- setModalContent(null);
10846
- }
10847
- },
10848
- children: [
10849
- /* @__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: [
10850
- /* @__PURE__ */ jsxs("div", { children: [
10851
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10852
- /* @__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." }) })
10730
+ }
10731
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10732
+ KeyboundForm,
10733
+ {
10734
+ onSubmit: handleSubmit,
10735
+ className: "flex flex-1 flex-col overflow-hidden",
10736
+ children: [
10737
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10738
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10739
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10740
+ /* @__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" }) }),
10741
+ /* @__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" }) })
10853
10742
  ] }),
10854
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10855
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10856
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10857
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10858
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10859
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10860
- ] }),
10861
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10862
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10863
- Input,
10864
- {
10865
- type: "search",
10866
- placeholder: "Search items",
10867
- value: searchValue,
10868
- onChange: (e) => onSearchValueChange(e.target.value)
10869
- }
10870
- ) }),
10871
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10872
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10873
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10743
+ fields.map((field, index) => {
10744
+ const isDisabled = field.disabled || false;
10745
+ let placeholder = "-";
10746
+ if (typeof field.value === "object") {
10747
+ placeholder = "{ ... }";
10748
+ }
10749
+ if (Array.isArray(field.value)) {
10750
+ placeholder = "[ ... ]";
10751
+ }
10752
+ return /* @__PURE__ */ jsx(
10753
+ ConditionalTooltip,
10754
+ {
10755
+ showTooltip: isDisabled,
10756
+ content: "This row is disabled because it contains non-primitive data.",
10757
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10758
+ /* @__PURE__ */ jsxs(
10759
+ "div",
10760
+ {
10761
+ className: clx("grid grid-cols-2 divide-x", {
10762
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
10763
+ }),
10764
+ children: [
10765
+ /* @__PURE__ */ jsx(
10766
+ Form$2.Field,
10767
+ {
10768
+ control: form.control,
10769
+ name: `metadata.${index}.key`,
10770
+ render: ({ field: field2 }) => {
10771
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10772
+ GridInput,
10773
+ {
10774
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
10775
+ ...field2,
10776
+ disabled: isDisabled,
10777
+ placeholder: "Key"
10778
+ }
10779
+ ) }) });
10780
+ }
10781
+ }
10782
+ ),
10783
+ /* @__PURE__ */ jsx(
10784
+ Form$2.Field,
10785
+ {
10786
+ control: form.control,
10787
+ name: `metadata.${index}.value`,
10788
+ render: ({ field: { value, ...field2 } }) => {
10789
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10790
+ GridInput,
10791
+ {
10792
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
10793
+ ...field2,
10794
+ value: isDisabled ? placeholder : value,
10795
+ disabled: isDisabled,
10796
+ placeholder: "Value"
10797
+ }
10798
+ ) }) });
10799
+ }
10800
+ }
10801
+ )
10802
+ ]
10803
+ }
10804
+ ),
10805
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10874
10806
  /* @__PURE__ */ jsx(
10875
- StackedModalTrigger$1,
10807
+ DropdownMenu.Trigger,
10876
10808
  {
10877
- type: "add-items",
10878
- setModalContent
10809
+ className: clx(
10810
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10811
+ {
10812
+ hidden: isDisabled
10813
+ }
10814
+ ),
10815
+ disabled: isDisabled,
10816
+ asChild: true,
10817
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10879
10818
  }
10880
10819
  ),
10881
- /* @__PURE__ */ jsx(
10882
- StackedModalTrigger$1,
10883
- {
10884
- type: "add-custom-item",
10885
- setModalContent
10886
- }
10887
- )
10888
- ] })
10889
- ] })
10890
- ] })
10891
- ] }),
10892
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10893
- /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
10894
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10895
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10896
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10897
- /* @__PURE__ */ jsx("div", {})
10898
- ] }) }),
10899
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10900
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10901
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10902
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10903
- Item,
10904
- {
10905
- item,
10906
- preview,
10907
- currencyCode
10908
- },
10909
- item.id
10910
- )) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10911
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10912
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10913
- 'No items found for "',
10914
- query2,
10915
- '".'
10916
- ] })
10917
- ] }) })
10918
- ] })
10919
- ] }),
10920
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10921
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10922
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10923
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10924
- Text,
10925
- {
10926
- size: "small",
10927
- leading: "compact",
10928
- className: "text-ui-fg-subtle",
10929
- children: [
10930
- itemCount,
10931
- " ",
10932
- itemCount === 1 ? "item" : "items"
10933
- ]
10934
- }
10935
- ) }),
10936
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10937
- ] })
10938
- ] }) }),
10939
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10940
- CustomItemForm,
10941
- {
10942
- orderId: preview.id,
10943
- currencyCode
10944
- }
10945
- ) : null)
10946
- ]
10947
- }
10948
- ) }),
10949
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10950
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10951
- /* @__PURE__ */ jsx(
10952
- Button,
10953
- {
10954
- size: "small",
10955
- type: "button",
10956
- onClick: onSubmit,
10957
- isLoading: isSubmitting,
10958
- children: "Save"
10959
- }
10820
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10821
+ /* @__PURE__ */ jsxs(
10822
+ DropdownMenu.Item,
10823
+ {
10824
+ className: "gap-x-2",
10825
+ onClick: () => insertRow(index, "above"),
10826
+ children: [
10827
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10828
+ "Insert row above"
10829
+ ]
10830
+ }
10831
+ ),
10832
+ /* @__PURE__ */ jsxs(
10833
+ DropdownMenu.Item,
10834
+ {
10835
+ className: "gap-x-2",
10836
+ onClick: () => insertRow(index, "below"),
10837
+ children: [
10838
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10839
+ "Insert row below"
10840
+ ]
10841
+ }
10842
+ ),
10843
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10844
+ /* @__PURE__ */ jsxs(
10845
+ DropdownMenu.Item,
10846
+ {
10847
+ className: "gap-x-2",
10848
+ onClick: () => deleteRow(index),
10849
+ children: [
10850
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10851
+ "Delete row"
10852
+ ]
10853
+ }
10854
+ )
10855
+ ] })
10856
+ ] })
10857
+ ] })
10858
+ },
10859
+ field.id
10860
+ );
10861
+ })
10862
+ ] }),
10863
+ 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." })
10864
+ ] }),
10865
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10866
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10867
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10868
+ ] }) })
10869
+ ]
10870
+ }
10871
+ ) });
10872
+ };
10873
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
10874
+ return /* @__PURE__ */ jsx(
10875
+ "input",
10876
+ {
10877
+ ref,
10878
+ ...props,
10879
+ autoComplete: "off",
10880
+ className: clx(
10881
+ "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",
10882
+ className
10960
10883
  )
10884
+ }
10885
+ );
10886
+ });
10887
+ GridInput.displayName = "MetadataForm.GridInput";
10888
+ const PlaceholderInner = () => {
10889
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10890
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10891
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10892
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10893
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10961
10894
  ] }) })
10962
10895
  ] });
10963
10896
  };
10964
- const Item = ({ item, preview, currencyCode }) => {
10965
- if (item.variant_id) {
10966
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10897
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
10898
+ function getDefaultValues(metadata) {
10899
+ if (!metadata || !Object.keys(metadata).length) {
10900
+ return [
10901
+ {
10902
+ key: "",
10903
+ value: "",
10904
+ disabled: false
10905
+ }
10906
+ ];
10967
10907
  }
10968
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10969
- };
10970
- const VariantItem = ({ item, preview, currencyCode }) => {
10971
- const [editing, setEditing] = useState(false);
10972
- const form = useForm({
10973
- defaultValues: {
10974
- quantity: item.quantity,
10975
- unit_price: item.unit_price
10976
- },
10977
- resolver: zodResolver(variantItemSchema)
10908
+ return Object.entries(metadata).map(([key, value]) => {
10909
+ if (!EDITABLE_TYPES.includes(typeof value)) {
10910
+ return {
10911
+ key,
10912
+ value,
10913
+ disabled: true
10914
+ };
10915
+ }
10916
+ let stringValue = value;
10917
+ if (typeof value !== "string") {
10918
+ stringValue = JSON.stringify(value);
10919
+ }
10920
+ return {
10921
+ key,
10922
+ value: stringValue,
10923
+ original_key: key
10924
+ };
10978
10925
  });
10979
- const actionId = useMemo(() => {
10980
- var _a, _b;
10981
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10982
- }, [item]);
10983
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10984
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10985
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10986
- const onSubmit = form.handleSubmit(async (data) => {
10987
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10988
- setEditing(false);
10926
+ }
10927
+ function parseValues(values) {
10928
+ const metadata = values.metadata;
10929
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10930
+ if (isEmpty) {
10931
+ return null;
10932
+ }
10933
+ const update = {};
10934
+ metadata.forEach((field) => {
10935
+ let key = field.key;
10936
+ let value = field.value;
10937
+ const disabled = field.disabled;
10938
+ if (!key || !value) {
10989
10939
  return;
10990
10940
  }
10991
- if (!actionId) {
10992
- await updateOriginalItem(
10993
- {
10994
- item_id: item.id,
10995
- quantity: data.quantity,
10996
- unit_price: convertNumber(data.unit_price)
10997
- },
10998
- {
10999
- onSuccess: () => {
11000
- setEditing(false);
11001
- },
11002
- onError: (e) => {
11003
- toast.error(e.message);
11004
- }
11005
- }
11006
- );
10941
+ if (disabled) {
10942
+ update[key] = value;
11007
10943
  return;
11008
10944
  }
11009
- await updateActionItem(
11010
- {
11011
- action_id: actionId,
11012
- quantity: data.quantity,
11013
- unit_price: convertNumber(data.unit_price)
11014
- },
11015
- {
11016
- onSuccess: () => {
11017
- setEditing(false);
11018
- },
11019
- onError: (e) => {
11020
- toast.error(e.message);
11021
- }
10945
+ key = key.trim();
10946
+ value = value.trim();
10947
+ if (value === "true") {
10948
+ update[key] = true;
10949
+ } else if (value === "false") {
10950
+ update[key] = false;
10951
+ } else {
10952
+ const parsedNumber = parseFloat(value);
10953
+ if (!isNaN(parsedNumber)) {
10954
+ update[key] = parsedNumber;
10955
+ } else {
10956
+ update[key] = value;
11022
10957
  }
11023
- );
10958
+ }
11024
10959
  });
11025
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
11026
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
11027
- /* @__PURE__ */ jsx(
11028
- Thumbnail,
11029
- {
11030
- thumbnail: item.thumbnail,
11031
- alt: item.product_title ?? void 0
11032
- }
11033
- ),
11034
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11035
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
11036
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
11037
- /* @__PURE__ */ jsxs(
11038
- Text,
11039
- {
11040
- size: "small",
11041
- leading: "compact",
11042
- className: "text-ui-fg-subtle",
11043
- children: [
11044
- "(",
11045
- item.variant_title,
11046
- ")"
11047
- ]
11048
- }
11049
- )
11050
- ] }),
11051
- /* @__PURE__ */ jsx(
11052
- Text,
11053
- {
11054
- size: "small",
11055
- leading: "compact",
11056
- className: "text-ui-fg-subtle",
11057
- children: item.variant_sku
11058
- }
11059
- )
11060
- ] })
11061
- ] }),
11062
- editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
11063
- Form$2.Field,
11064
- {
11065
- control: form.control,
11066
- name: "quantity",
11067
- render: ({ field }) => {
11068
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
11069
- }
11070
- }
11071
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
11072
- editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
11073
- Form$2.Field,
11074
- {
11075
- control: form.control,
11076
- name: "unit_price",
11077
- render: ({ field: { onChange, ...field } }) => {
11078
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11079
- CurrencyInput,
11080
- {
11081
- ...field,
11082
- symbol: getNativeSymbol(currencyCode),
11083
- code: currencyCode,
11084
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
11085
- }
11086
- ) }) });
11087
- }
11088
- }
11089
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
11090
- /* @__PURE__ */ jsx(
11091
- IconButton,
11092
- {
11093
- type: "button",
11094
- size: "small",
11095
- onClick: editing ? onSubmit : () => {
11096
- setEditing(true);
11097
- },
11098
- disabled: isPending,
11099
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
11100
- }
11101
- )
11102
- ] }) }) });
10960
+ return update;
10961
+ }
10962
+ function getHasUneditableRows(metadata) {
10963
+ if (!metadata) {
10964
+ return false;
10965
+ }
10966
+ return Object.values(metadata).some(
10967
+ (value) => !EDITABLE_TYPES.includes(typeof value)
10968
+ );
10969
+ }
10970
+ const PROMOTION_QUERY_KEY = "promotions";
10971
+ const promotionsQueryKeys = {
10972
+ list: (query2) => [
10973
+ PROMOTION_QUERY_KEY,
10974
+ query2 ? query2 : void 0
10975
+ ],
10976
+ detail: (id, query2) => [
10977
+ PROMOTION_QUERY_KEY,
10978
+ id,
10979
+ query2 ? query2 : void 0
10980
+ ]
10981
+ };
10982
+ const usePromotions = (query2, options) => {
10983
+ const { data, ...rest } = useQuery({
10984
+ queryKey: promotionsQueryKeys.list(query2),
10985
+ queryFn: async () => sdk.admin.promotion.list(query2),
10986
+ ...options
10987
+ });
10988
+ return { ...data, ...rest };
10989
+ };
10990
+ const Promotions = () => {
10991
+ const { id } = useParams();
10992
+ const {
10993
+ order: preview,
10994
+ isError: isPreviewError,
10995
+ error: previewError
10996
+ } = useOrderPreview(id, void 0);
10997
+ useInitiateOrderEdit({ preview });
10998
+ const { onCancel } = useCancelOrderEdit({ preview });
10999
+ if (isPreviewError) {
11000
+ throw previewError;
11001
+ }
11002
+ const isReady = !!preview;
11003
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
11004
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
11005
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
11006
+ ] });
11103
11007
  };
11104
- const variantItemSchema = objectType({
11105
- quantity: numberType(),
11106
- unit_price: unionType([numberType(), stringType()])
11107
- });
11108
- const CustomItem = ({ item, preview, currencyCode }) => {
11109
- const [editing, setEditing] = useState(false);
11110
- const { quantity, unit_price, title } = item;
11111
- const form = useForm({
11112
- defaultValues: {
11113
- title,
11114
- quantity,
11115
- unit_price
11008
+ const PromotionForm = ({ preview }) => {
11009
+ const { items, shipping_methods } = preview;
11010
+ const [isSubmitting, setIsSubmitting] = useState(false);
11011
+ const [comboboxValue, setComboboxValue] = useState("");
11012
+ const { handleSuccess } = useRouteModal();
11013
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11014
+ const promoCodes = getPromotionCodes(items, shipping_methods);
11015
+ const { promotions, isPending, isError, error } = usePromotions(
11016
+ {
11017
+ code: promoCodes
11116
11018
  },
11117
- resolver: zodResolver(customItemSchema)
11118
- });
11119
- useEffect(() => {
11120
- form.reset({
11121
- title,
11122
- quantity,
11123
- unit_price
11124
- });
11125
- }, [form, title, quantity, unit_price]);
11126
- const actionId = useMemo(() => {
11127
- var _a, _b;
11128
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
11129
- }, [item]);
11130
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
11131
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
11132
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
11133
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
11134
- const onSubmit = form.handleSubmit(async (data) => {
11135
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
11136
- setEditing(false);
11137
- return;
11138
- }
11139
- if (!actionId) {
11140
- await updateOriginalItem(
11141
- {
11142
- item_id: item.id,
11143
- quantity: data.quantity,
11144
- unit_price: convertNumber(data.unit_price)
11145
- },
11146
- {
11147
- onSuccess: () => {
11148
- setEditing(false);
11149
- },
11150
- onError: (e) => {
11151
- toast.error(e.message);
11152
- }
11153
- }
11154
- );
11155
- return;
11019
+ {
11020
+ enabled: !!promoCodes.length
11156
11021
  }
11157
- if (data.quantity === 0) {
11158
- await removeActionItem(actionId, {
11159
- onSuccess: () => {
11160
- setEditing(false);
11161
- },
11162
- onError: (e) => {
11163
- toast.error(e.message);
11022
+ );
11023
+ const comboboxData = useComboboxData({
11024
+ queryKey: ["promotions", "combobox", promoCodes],
11025
+ queryFn: async (params) => {
11026
+ return await sdk.admin.promotion.list({
11027
+ ...params,
11028
+ code: {
11029
+ $nin: promoCodes
11164
11030
  }
11165
11031
  });
11032
+ },
11033
+ getOptions: (data) => {
11034
+ return data.promotions.map((promotion) => ({
11035
+ label: promotion.code,
11036
+ value: promotion.code
11037
+ }));
11038
+ }
11039
+ });
11040
+ const add = async (value) => {
11041
+ if (!value) {
11166
11042
  return;
11167
11043
  }
11168
- await updateActionItem(
11044
+ addPromotions(
11169
11045
  {
11170
- action_id: actionId,
11171
- quantity: data.quantity,
11172
- unit_price: convertNumber(data.unit_price)
11046
+ promo_codes: [value]
11173
11047
  },
11174
11048
  {
11175
- onSuccess: () => {
11176
- setEditing(false);
11177
- },
11178
11049
  onError: (e) => {
11179
11050
  toast.error(e.message);
11051
+ comboboxData.onSearchValueChange("");
11052
+ setComboboxValue("");
11053
+ },
11054
+ onSuccess: () => {
11055
+ comboboxData.onSearchValueChange("");
11056
+ setComboboxValue("");
11180
11057
  }
11181
11058
  }
11182
11059
  );
11183
- });
11184
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
11185
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
11186
- /* @__PURE__ */ jsx(
11187
- Thumbnail,
11188
- {
11189
- thumbnail: item.thumbnail,
11190
- alt: item.title ?? void 0
11191
- }
11192
- ),
11193
- editing ? /* @__PURE__ */ jsx(
11194
- Form$2.Field,
11195
- {
11196
- control: form.control,
11197
- name: "title",
11198
- render: ({ field }) => {
11199
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
11200
- }
11201
- }
11202
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
11203
- ] }),
11204
- editing ? /* @__PURE__ */ jsx(
11205
- Form$2.Field,
11206
- {
11207
- control: form.control,
11208
- name: "quantity",
11209
- render: ({ field }) => {
11210
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
11211
- }
11212
- }
11213
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
11214
- editing ? /* @__PURE__ */ jsx(
11215
- Form$2.Field,
11216
- {
11217
- control: form.control,
11218
- name: "unit_price",
11219
- render: ({ field: { onChange, ...field } }) => {
11220
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11221
- CurrencyInput,
11222
- {
11223
- ...field,
11224
- symbol: getNativeSymbol(currencyCode),
11225
- code: currencyCode,
11226
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
11227
- }
11228
- ) }) });
11229
- }
11230
- }
11231
- ) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
11232
- /* @__PURE__ */ jsx(
11233
- IconButton,
11234
- {
11235
- type: "button",
11236
- size: "small",
11237
- onClick: editing ? onSubmit : () => {
11238
- setEditing(true);
11239
- },
11240
- disabled: isPending,
11241
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
11060
+ };
11061
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11062
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
11063
+ const onSubmit = async () => {
11064
+ setIsSubmitting(true);
11065
+ let requestSucceeded = false;
11066
+ await requestOrderEdit(void 0, {
11067
+ onError: (e) => {
11068
+ toast.error(e.message);
11069
+ },
11070
+ onSuccess: () => {
11071
+ requestSucceeded = true;
11242
11072
  }
11243
- )
11244
- ] }) }) });
11245
- };
11246
- const StackedModalTrigger$1 = ({
11247
- type,
11248
- setModalContent
11249
- }) => {
11250
- const { setIsOpen } = useStackedModal();
11251
- const onClick = useCallback(() => {
11252
- setModalContent(type);
11253
- setIsOpen(STACKED_MODAL_ID, true);
11254
- }, [setModalContent, setIsOpen, type]);
11255
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
11256
- };
11257
- const VARIANT_PREFIX = "items";
11258
- const LIMIT = 50;
11259
- const ExistingItemsForm = ({ orderId, items }) => {
11260
- const { setIsOpen } = useStackedModal();
11261
- const [rowSelection, setRowSelection] = useState(
11262
- items.reduce((acc, item) => {
11263
- acc[item.variant_id] = true;
11264
- return acc;
11265
- }, {})
11266
- );
11267
- useEffect(() => {
11268
- setRowSelection(
11269
- items.reduce((acc, item) => {
11270
- if (item.variant_id) {
11271
- acc[item.variant_id] = true;
11272
- }
11273
- return acc;
11274
- }, {})
11275
- );
11276
- }, [items]);
11277
- const { q, order, offset } = useQueryParams(
11278
- ["q", "order", "offset"],
11279
- VARIANT_PREFIX
11280
- );
11281
- const { variants, count, isPending, isError, error } = useProductVariants(
11282
- {
11283
- q,
11284
- order,
11285
- offset: offset ? parseInt(offset) : void 0,
11286
- limit: LIMIT
11287
- },
11288
- {
11289
- placeholderData: keepPreviousData
11073
+ });
11074
+ if (!requestSucceeded) {
11075
+ setIsSubmitting(false);
11076
+ return;
11290
11077
  }
11291
- );
11292
- const columns = useColumns();
11293
- const { mutateAsync } = useDraftOrderAddItems(orderId);
11294
- const onSubmit = async () => {
11295
- const ids = Object.keys(rowSelection).filter(
11296
- (id) => !items.find((i) => i.variant_id === id)
11297
- );
11298
- await mutateAsync(
11299
- {
11300
- items: ids.map((id) => ({
11301
- variant_id: id,
11302
- quantity: 1
11303
- }))
11078
+ await confirmOrderEdit(void 0, {
11079
+ onError: (e) => {
11080
+ toast.error(e.message);
11304
11081
  },
11305
- {
11306
- onSuccess: () => {
11307
- setRowSelection({});
11308
- setIsOpen(STACKED_MODAL_ID, false);
11309
- },
11310
- onError: (e) => {
11311
- toast.error(e.message);
11312
- }
11082
+ onSuccess: () => {
11083
+ handleSuccess();
11084
+ },
11085
+ onSettled: () => {
11086
+ setIsSubmitting(false);
11313
11087
  }
11314
- );
11088
+ });
11315
11089
  };
11316
11090
  if (isError) {
11317
11091
  throw error;
11318
11092
  }
11319
- return /* @__PURE__ */ jsxs(
11320
- StackedFocusModal.Content,
11321
- {
11322
- onOpenAutoFocus: (e) => {
11323
- e.preventDefault();
11324
- const searchInput = document.querySelector(
11325
- "[data-modal-id='modal-search-input']"
11326
- );
11327
- if (searchInput) {
11328
- searchInput.focus();
11329
- }
11330
- },
11331
- children: [
11332
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
11333
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
11334
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
11093
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11094
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
11095
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
11096
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11097
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
11098
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11335
11099
  ] }),
11336
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
11337
- DataTable,
11100
+ /* @__PURE__ */ jsx(
11101
+ Combobox,
11338
11102
  {
11339
- data: variants,
11340
- columns,
11341
- isLoading: isPending,
11342
- getRowId: (row) => row.id,
11343
- rowCount: count,
11344
- prefix: VARIANT_PREFIX,
11345
- layout: "fill",
11346
- rowSelection: {
11347
- state: rowSelection,
11348
- onRowSelectionChange: setRowSelection,
11349
- enableRowSelection: (row) => {
11350
- return !items.find((i) => i.variant_id === row.original.id);
11351
- }
11352
- },
11353
- autoFocusSearch: true
11103
+ id: "promotion-combobox",
11104
+ "aria-describedby": "promotion-combobox-hint",
11105
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
11106
+ fetchNextPage: comboboxData.fetchNextPage,
11107
+ options: comboboxData.options,
11108
+ onSearchValueChange: comboboxData.onSearchValueChange,
11109
+ searchValue: comboboxData.searchValue,
11110
+ disabled: comboboxData.disabled || isAddingPromotions,
11111
+ onChange: add,
11112
+ value: comboboxValue
11354
11113
  }
11355
- ) }),
11356
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11357
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11358
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
11359
- ] }) })
11360
- ]
11361
- }
11362
- );
11363
- };
11364
- const columnHelper = createDataTableColumnHelper();
11365
- const useColumns = () => {
11366
- return useMemo(() => {
11367
- return [
11368
- columnHelper.select(),
11369
- columnHelper.accessor("product.title", {
11370
- header: "Product",
11371
- cell: ({ row }) => {
11372
- var _a, _b, _c;
11373
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
11374
- /* @__PURE__ */ jsx(
11375
- Thumbnail,
11376
- {
11377
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
11378
- alt: (_b = row.original.product) == null ? void 0 : _b.title
11379
- }
11380
- ),
11381
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
11382
- ] });
11383
- },
11384
- enableSorting: true
11385
- }),
11386
- columnHelper.accessor("title", {
11387
- header: "Variant",
11388
- enableSorting: true
11389
- }),
11390
- columnHelper.accessor("sku", {
11391
- header: "SKU",
11392
- cell: ({ getValue }) => {
11393
- return getValue() ?? "-";
11394
- },
11395
- enableSorting: true
11396
- }),
11397
- columnHelper.accessor("updated_at", {
11398
- header: "Updated",
11399
- cell: ({ getValue }) => {
11400
- return /* @__PURE__ */ jsx(
11401
- Tooltip,
11402
- {
11403
- content: getFullDate({ date: getValue(), includeTime: true }),
11404
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
11405
- }
11406
- );
11407
- },
11408
- enableSorting: true,
11409
- sortAscLabel: "Oldest first",
11410
- sortDescLabel: "Newest first"
11411
- }),
11412
- columnHelper.accessor("created_at", {
11413
- header: "Created",
11414
- cell: ({ getValue }) => {
11415
- return /* @__PURE__ */ jsx(
11416
- Tooltip,
11417
- {
11418
- content: getFullDate({ date: getValue(), includeTime: true }),
11419
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
11420
- }
11421
- );
11114
+ )
11115
+ ] }),
11116
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11117
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
11118
+ PromotionItem,
11119
+ {
11120
+ promotion,
11121
+ orderId: preview.id,
11122
+ isLoading: isPending
11422
11123
  },
11423
- enableSorting: true,
11424
- sortAscLabel: "Oldest first",
11425
- sortDescLabel: "Newest first"
11426
- })
11427
- ];
11428
- }, []);
11124
+ promotion.id
11125
+ )) })
11126
+ ] }) }),
11127
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11128
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11129
+ /* @__PURE__ */ jsx(
11130
+ Button,
11131
+ {
11132
+ size: "small",
11133
+ type: "submit",
11134
+ isLoading: isSubmitting || isAddingPromotions,
11135
+ children: "Save"
11136
+ }
11137
+ )
11138
+ ] }) })
11139
+ ] });
11429
11140
  };
11430
- const CustomItemForm = ({ orderId, currencyCode }) => {
11431
- const { setIsOpen } = useStackedModal();
11432
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
11433
- const form = useForm({
11434
- defaultValues: {
11435
- title: "",
11436
- quantity: 1,
11437
- unit_price: ""
11438
- },
11439
- resolver: zodResolver(customItemSchema)
11440
- });
11441
- const onSubmit = form.handleSubmit(async (data) => {
11442
- await addItems(
11141
+ const PromotionItem = ({
11142
+ promotion,
11143
+ orderId,
11144
+ isLoading
11145
+ }) => {
11146
+ var _a;
11147
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
11148
+ const onRemove = async () => {
11149
+ removePromotions(
11443
11150
  {
11444
- items: [
11445
- {
11446
- title: data.title,
11447
- quantity: data.quantity,
11448
- unit_price: convertNumber(data.unit_price)
11449
- }
11450
- ]
11151
+ promo_codes: [promotion.code]
11451
11152
  },
11452
11153
  {
11453
- onSuccess: () => {
11454
- setIsOpen(STACKED_MODAL_ID, false);
11455
- },
11456
11154
  onError: (e) => {
11457
11155
  toast.error(e.message);
11458
11156
  }
11459
11157
  }
11460
11158
  );
11461
- });
11462
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
11463
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
11464
- /* @__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: [
11465
- /* @__PURE__ */ jsxs("div", { children: [
11466
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
11467
- /* @__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." }) })
11468
- ] }),
11469
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11470
- /* @__PURE__ */ jsx(
11471
- Form$2.Field,
11472
- {
11473
- control: form.control,
11474
- name: "title",
11475
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11476
- /* @__PURE__ */ jsxs("div", { children: [
11477
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
11478
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
11479
- ] }),
11480
- /* @__PURE__ */ jsxs("div", { children: [
11481
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11482
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11483
- ] })
11484
- ] }) })
11485
- }
11486
- ),
11487
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11488
- /* @__PURE__ */ jsx(
11489
- Form$2.Field,
11159
+ };
11160
+ const displayValue = getDisplayValue(promotion);
11161
+ return /* @__PURE__ */ jsxs(
11162
+ "div",
11163
+ {
11164
+ className: clx(
11165
+ "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
11490
11166
  {
11491
- control: form.control,
11492
- name: "unit_price",
11493
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11494
- /* @__PURE__ */ jsxs("div", { children: [
11495
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
11496
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
11497
- ] }),
11498
- /* @__PURE__ */ jsxs("div", { children: [
11499
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11500
- CurrencyInput,
11501
- {
11502
- symbol: getNativeSymbol(currencyCode),
11503
- code: currencyCode,
11504
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
11505
- ...field
11506
- }
11507
- ) }),
11508
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11509
- ] })
11510
- ] }) })
11167
+ "animate-pulse": isLoading
11511
11168
  }
11512
11169
  ),
11513
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11514
- /* @__PURE__ */ jsx(
11515
- Form$2.Field,
11516
- {
11517
- control: form.control,
11518
- name: "quantity",
11519
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11520
- /* @__PURE__ */ jsxs("div", { children: [
11521
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
11522
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
11170
+ children: [
11171
+ /* @__PURE__ */ jsxs("div", { children: [
11172
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11173
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
11174
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11175
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11176
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11523
11177
  ] }),
11524
- /* @__PURE__ */ jsxs("div", { className: "flex-1 w-full", children: [
11525
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
11526
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11527
- ] })
11528
- ] }) })
11529
- }
11530
- )
11531
- ] }) }) }),
11532
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11533
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11534
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
11535
- ] }) })
11536
- ] }) }) });
11178
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11179
+ ] })
11180
+ ] }),
11181
+ /* @__PURE__ */ jsx(
11182
+ IconButton,
11183
+ {
11184
+ size: "small",
11185
+ type: "button",
11186
+ variant: "transparent",
11187
+ onClick: onRemove,
11188
+ isLoading: isPending || isLoading,
11189
+ children: /* @__PURE__ */ jsx(XMark, {})
11190
+ }
11191
+ )
11192
+ ]
11193
+ },
11194
+ promotion.id
11195
+ );
11537
11196
  };
11538
- const customItemSchema = objectType({
11539
- title: stringType().min(1),
11540
- quantity: numberType(),
11541
- unit_price: unionType([numberType(), stringType()])
11197
+ function getDisplayValue(promotion) {
11198
+ var _a, _b, _c, _d;
11199
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11200
+ if (!value) {
11201
+ return null;
11202
+ }
11203
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11204
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11205
+ if (!currency) {
11206
+ return null;
11207
+ }
11208
+ return getLocaleAmount(value, currency);
11209
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11210
+ return formatPercentage(value);
11211
+ }
11212
+ return null;
11213
+ }
11214
+ const formatter = new Intl.NumberFormat([], {
11215
+ style: "percent",
11216
+ minimumFractionDigits: 2
11542
11217
  });
11218
+ const formatPercentage = (value, isPercentageValue = false) => {
11219
+ let val = value || 0;
11220
+ if (!isPercentageValue) {
11221
+ val = val / 100;
11222
+ }
11223
+ return formatter.format(val);
11224
+ };
11225
+ function getPromotionCodes(items, shippingMethods) {
11226
+ const codes = /* @__PURE__ */ new Set();
11227
+ for (const item of items) {
11228
+ if (item.adjustments) {
11229
+ for (const adjustment of item.adjustments) {
11230
+ if (adjustment.code) {
11231
+ codes.add(adjustment.code);
11232
+ }
11233
+ }
11234
+ }
11235
+ }
11236
+ for (const shippingMethod of shippingMethods) {
11237
+ if (shippingMethod.adjustments) {
11238
+ for (const adjustment of shippingMethod.adjustments) {
11239
+ if (adjustment.code) {
11240
+ codes.add(adjustment.code);
11241
+ }
11242
+ }
11243
+ }
11244
+ }
11245
+ return Array.from(codes);
11246
+ }
11543
11247
  const STACKED_FOCUS_MODAL_ID = "shipping-form";
11544
11248
  const Shipping = () => {
11545
11249
  var _a;
@@ -12379,7 +12083,7 @@ const ShippingAddressForm = ({ order }) => {
12379
12083
  postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12380
12084
  phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12381
12085
  },
12382
- resolver: zodResolver(schema$1)
12086
+ resolver: zodResolver(schema$3)
12383
12087
  });
12384
12088
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12385
12089
  const { handleSuccess } = useRouteModal();
@@ -12549,7 +12253,7 @@ const ShippingAddressForm = ({ order }) => {
12549
12253
  }
12550
12254
  ) });
12551
12255
  };
12552
- const schema$1 = addressSchema;
12256
+ const schema$3 = addressSchema;
12553
12257
  const TransferOwnership = () => {
12554
12258
  const { id } = useParams();
12555
12259
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -12573,7 +12277,7 @@ const TransferOwnershipForm = ({ order }) => {
12573
12277
  defaultValues: {
12574
12278
  customer_id: order.customer_id || ""
12575
12279
  },
12576
- resolver: zodResolver(schema)
12280
+ resolver: zodResolver(schema$2)
12577
12281
  });
12578
12282
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12579
12283
  const { handleSuccess } = useRouteModal();
@@ -12967,64 +12671,360 @@ const Illustration = () => {
12967
12671
  /* @__PURE__ */ jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsx(
12968
12672
  "rect",
12969
12673
  {
12970
- width: "12",
12971
- height: "12",
12972
- fill: "white",
12973
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
12674
+ width: "12",
12675
+ height: "12",
12676
+ fill: "white",
12677
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
12678
+ }
12679
+ ) }),
12680
+ /* @__PURE__ */ jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsx(
12681
+ "rect",
12682
+ {
12683
+ width: "12",
12684
+ height: "12",
12685
+ fill: "white",
12686
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12687
+ }
12688
+ ) }),
12689
+ /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12690
+ "rect",
12691
+ {
12692
+ width: "12",
12693
+ height: "12",
12694
+ fill: "white",
12695
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12696
+ }
12697
+ ) }),
12698
+ /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12699
+ "rect",
12700
+ {
12701
+ width: "12",
12702
+ height: "12",
12703
+ fill: "white",
12704
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12705
+ }
12706
+ ) }),
12707
+ /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
12708
+ "rect",
12709
+ {
12710
+ width: "12",
12711
+ height: "12",
12712
+ fill: "white",
12713
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12714
+ }
12715
+ ) }),
12716
+ /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
12717
+ "rect",
12718
+ {
12719
+ width: "12",
12720
+ height: "12",
12721
+ fill: "white",
12722
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
12723
+ }
12724
+ ) })
12725
+ ] })
12726
+ ]
12727
+ }
12728
+ );
12729
+ };
12730
+ const schema$2 = objectType({
12731
+ customer_id: stringType().min(1)
12732
+ });
12733
+ const BillingAddress = () => {
12734
+ const { id } = useParams();
12735
+ const { order, isPending, isError, error } = useOrder(id, {
12736
+ fields: "+billing_address"
12737
+ });
12738
+ if (isError) {
12739
+ throw error;
12740
+ }
12741
+ const isReady = !isPending && !!order;
12742
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12743
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12744
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Billing Address" }) }),
12745
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the billing address for the draft order" }) })
12746
+ ] }),
12747
+ isReady && /* @__PURE__ */ jsx(BillingAddressForm, { order })
12748
+ ] });
12749
+ };
12750
+ const BillingAddressForm = ({ order }) => {
12751
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
12752
+ const form = useForm({
12753
+ defaultValues: {
12754
+ first_name: ((_a = order.billing_address) == null ? void 0 : _a.first_name) ?? "",
12755
+ last_name: ((_b = order.billing_address) == null ? void 0 : _b.last_name) ?? "",
12756
+ company: ((_c = order.billing_address) == null ? void 0 : _c.company) ?? "",
12757
+ address_1: ((_d = order.billing_address) == null ? void 0 : _d.address_1) ?? "",
12758
+ address_2: ((_e = order.billing_address) == null ? void 0 : _e.address_2) ?? "",
12759
+ city: ((_f = order.billing_address) == null ? void 0 : _f.city) ?? "",
12760
+ province: ((_g = order.billing_address) == null ? void 0 : _g.province) ?? "",
12761
+ country_code: ((_h = order.billing_address) == null ? void 0 : _h.country_code) ?? "",
12762
+ postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
12763
+ phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
12764
+ },
12765
+ resolver: zodResolver(schema$1)
12766
+ });
12767
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12768
+ const { handleSuccess } = useRouteModal();
12769
+ const onSubmit = form.handleSubmit(async (data) => {
12770
+ await mutateAsync(
12771
+ { billing_address: data },
12772
+ {
12773
+ onSuccess: () => {
12774
+ handleSuccess();
12775
+ },
12776
+ onError: (error) => {
12777
+ toast.error(error.message);
12778
+ }
12779
+ }
12780
+ );
12781
+ });
12782
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12783
+ KeyboundForm,
12784
+ {
12785
+ className: "flex flex-1 flex-col overflow-hidden",
12786
+ onSubmit,
12787
+ children: [
12788
+ /* @__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: [
12789
+ /* @__PURE__ */ jsx(
12790
+ Form$2.Field,
12791
+ {
12792
+ control: form.control,
12793
+ name: "country_code",
12794
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12795
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
12796
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
12797
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12798
+ ] })
12799
+ }
12800
+ ),
12801
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12802
+ /* @__PURE__ */ jsx(
12803
+ Form$2.Field,
12804
+ {
12805
+ control: form.control,
12806
+ name: "first_name",
12807
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12808
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
12809
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12810
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12811
+ ] })
12812
+ }
12813
+ ),
12814
+ /* @__PURE__ */ jsx(
12815
+ Form$2.Field,
12816
+ {
12817
+ control: form.control,
12818
+ name: "last_name",
12819
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12820
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
12821
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12822
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12823
+ ] })
12824
+ }
12825
+ )
12826
+ ] }),
12827
+ /* @__PURE__ */ jsx(
12828
+ Form$2.Field,
12829
+ {
12830
+ control: form.control,
12831
+ name: "company",
12832
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12833
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
12834
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12835
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12836
+ ] })
12974
12837
  }
12975
- ) }),
12976
- /* @__PURE__ */ jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsx(
12977
- "rect",
12838
+ ),
12839
+ /* @__PURE__ */ jsx(
12840
+ Form$2.Field,
12978
12841
  {
12979
- width: "12",
12980
- height: "12",
12981
- fill: "white",
12982
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12842
+ control: form.control,
12843
+ name: "address_1",
12844
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12845
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
12846
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12847
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12848
+ ] })
12983
12849
  }
12984
- ) }),
12985
- /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12986
- "rect",
12850
+ ),
12851
+ /* @__PURE__ */ jsx(
12852
+ Form$2.Field,
12987
12853
  {
12988
- width: "12",
12989
- height: "12",
12990
- fill: "white",
12991
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12854
+ control: form.control,
12855
+ name: "address_2",
12856
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12857
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
12858
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12859
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12860
+ ] })
12992
12861
  }
12993
- ) }),
12994
- /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12995
- "rect",
12862
+ ),
12863
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12864
+ /* @__PURE__ */ jsx(
12865
+ Form$2.Field,
12866
+ {
12867
+ control: form.control,
12868
+ name: "postal_code",
12869
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12870
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
12871
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12872
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12873
+ ] })
12874
+ }
12875
+ ),
12876
+ /* @__PURE__ */ jsx(
12877
+ Form$2.Field,
12878
+ {
12879
+ control: form.control,
12880
+ name: "city",
12881
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12882
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
12883
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12884
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12885
+ ] })
12886
+ }
12887
+ )
12888
+ ] }),
12889
+ /* @__PURE__ */ jsx(
12890
+ Form$2.Field,
12996
12891
  {
12997
- width: "12",
12998
- height: "12",
12999
- fill: "white",
13000
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12892
+ control: form.control,
12893
+ name: "province",
12894
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12895
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
12896
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12897
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12898
+ ] })
13001
12899
  }
13002
- ) }),
13003
- /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
13004
- "rect",
12900
+ ),
12901
+ /* @__PURE__ */ jsx(
12902
+ Form$2.Field,
13005
12903
  {
13006
- width: "12",
13007
- height: "12",
13008
- fill: "white",
13009
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12904
+ control: form.control,
12905
+ name: "phone",
12906
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12907
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
12908
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12909
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12910
+ ] })
13010
12911
  }
13011
- ) }),
13012
- /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
13013
- "rect",
12912
+ )
12913
+ ] }) }),
12914
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
12915
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
12916
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
12917
+ ] }) })
12918
+ ]
12919
+ }
12920
+ ) });
12921
+ };
12922
+ const schema$1 = addressSchema;
12923
+ const SalesChannel = () => {
12924
+ const { id } = useParams();
12925
+ const { draft_order, isPending, isError, error } = useDraftOrder(
12926
+ id,
12927
+ {
12928
+ fields: "+sales_channel_id"
12929
+ },
12930
+ {
12931
+ enabled: !!id
12932
+ }
12933
+ );
12934
+ if (isError) {
12935
+ throw error;
12936
+ }
12937
+ const ISrEADY = !!draft_order && !isPending;
12938
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12939
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12940
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
12941
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
12942
+ ] }),
12943
+ ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
12944
+ ] });
12945
+ };
12946
+ const SalesChannelForm = ({ order }) => {
12947
+ const form = useForm({
12948
+ defaultValues: {
12949
+ sales_channel_id: order.sales_channel_id || ""
12950
+ },
12951
+ resolver: zodResolver(schema)
12952
+ });
12953
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12954
+ const { handleSuccess } = useRouteModal();
12955
+ const onSubmit = form.handleSubmit(async (data) => {
12956
+ await mutateAsync(
12957
+ {
12958
+ sales_channel_id: data.sales_channel_id
12959
+ },
12960
+ {
12961
+ onSuccess: () => {
12962
+ toast.success("Sales channel updated");
12963
+ handleSuccess();
12964
+ },
12965
+ onError: (error) => {
12966
+ toast.error(error.message);
12967
+ }
12968
+ }
12969
+ );
12970
+ });
12971
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12972
+ KeyboundForm,
12973
+ {
12974
+ className: "flex flex-1 flex-col overflow-hidden",
12975
+ onSubmit,
12976
+ children: [
12977
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
12978
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
12979
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
12980
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
12981
+ ] }) })
12982
+ ]
12983
+ }
12984
+ ) });
12985
+ };
12986
+ const SalesChannelField = ({ control, order }) => {
12987
+ const salesChannels = useComboboxData({
12988
+ queryFn: async (params) => {
12989
+ return await sdk.admin.salesChannel.list(params);
12990
+ },
12991
+ queryKey: ["sales-channels"],
12992
+ getOptions: (data) => {
12993
+ return data.sales_channels.map((salesChannel) => ({
12994
+ label: salesChannel.name,
12995
+ value: salesChannel.id
12996
+ }));
12997
+ },
12998
+ defaultValue: order.sales_channel_id || void 0
12999
+ });
13000
+ return /* @__PURE__ */ jsx(
13001
+ Form$2.Field,
13002
+ {
13003
+ control,
13004
+ name: "sales_channel_id",
13005
+ render: ({ field }) => {
13006
+ return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13007
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
13008
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
13009
+ Combobox,
13014
13010
  {
13015
- width: "12",
13016
- height: "12",
13017
- fill: "white",
13018
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
13011
+ options: salesChannels.options,
13012
+ fetchNextPage: salesChannels.fetchNextPage,
13013
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
13014
+ searchValue: salesChannels.searchValue,
13015
+ onSearchValueChange: salesChannels.onSearchValueChange,
13016
+ placeholder: "Select sales channel",
13017
+ ...field
13019
13018
  }
13020
- ) })
13021
- ] })
13022
- ]
13019
+ ) }),
13020
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13021
+ ] });
13022
+ }
13023
13023
  }
13024
13024
  );
13025
13025
  };
13026
13026
  const schema = objectType({
13027
- customer_id: stringType().min(1)
13027
+ sales_channel_id: stringType().min(1)
13028
13028
  });
13029
13029
  const widgetModule = { widgets: [] };
13030
13030
  const routeModule = {
@@ -13046,10 +13046,6 @@ const routeModule = {
13046
13046
  handle,
13047
13047
  loader,
13048
13048
  children: [
13049
- {
13050
- Component: BillingAddress,
13051
- path: "/draft-orders/:id/billing-address"
13052
- },
13053
13049
  {
13054
13050
  Component: CustomItems,
13055
13051
  path: "/draft-orders/:id/custom-items"
@@ -13058,6 +13054,10 @@ const routeModule = {
13058
13054
  Component: Email,
13059
13055
  path: "/draft-orders/:id/email"
13060
13056
  },
13057
+ {
13058
+ Component: Items,
13059
+ path: "/draft-orders/:id/items"
13060
+ },
13061
13061
  {
13062
13062
  Component: Metadata,
13063
13063
  path: "/draft-orders/:id/metadata"
@@ -13066,14 +13066,6 @@ const routeModule = {
13066
13066
  Component: Promotions,
13067
13067
  path: "/draft-orders/:id/promotions"
13068
13068
  },
13069
- {
13070
- Component: SalesChannel,
13071
- path: "/draft-orders/:id/sales-channel"
13072
- },
13073
- {
13074
- Component: Items,
13075
- path: "/draft-orders/:id/items"
13076
- },
13077
13069
  {
13078
13070
  Component: Shipping,
13079
13071
  path: "/draft-orders/:id/shipping"
@@ -13085,6 +13077,14 @@ const routeModule = {
13085
13077
  {
13086
13078
  Component: TransferOwnership,
13087
13079
  path: "/draft-orders/:id/transfer-ownership"
13080
+ },
13081
+ {
13082
+ Component: BillingAddress,
13083
+ path: "/draft-orders/:id/billing-address"
13084
+ },
13085
+ {
13086
+ Component: SalesChannel,
13087
+ path: "/draft-orders/:id/sales-channel"
13088
13088
  }
13089
13089
  ]
13090
13090
  }