@medusajs/draft-order 3.0.0-preview-20251214180138 → 3.0.0-preview-20251215000314

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";
@@ -9755,27 +9755,6 @@ const BillingAddressForm = ({ order }) => {
9755
9755
  ) });
9756
9756
  };
9757
9757
  const schema$5 = addressSchema;
9758
- const CustomItems = () => {
9759
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9760
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
9761
- /* @__PURE__ */ jsx(CustomItemsForm, {})
9762
- ] });
9763
- };
9764
- const CustomItemsForm = () => {
9765
- const form = useForm({
9766
- resolver: zodResolver(schema$4)
9767
- });
9768
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9769
- /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
9770
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9771
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9772
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
9773
- ] }) })
9774
- ] }) });
9775
- };
9776
- const schema$4 = objectType({
9777
- email: stringType().email()
9778
- });
9779
9758
  const Email = () => {
9780
9759
  const { id } = useParams();
9781
9760
  const { order, isPending, isError, error } = useOrder(id, {
@@ -9798,7 +9777,7 @@ const EmailForm = ({ order }) => {
9798
9777
  defaultValues: {
9799
9778
  email: order.email ?? ""
9800
9779
  },
9801
- resolver: zodResolver(schema$3)
9780
+ resolver: zodResolver(schema$4)
9802
9781
  });
9803
9782
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9804
9783
  const { handleSuccess } = useRouteModal();
@@ -9841,25 +9820,151 @@ const EmailForm = ({ order }) => {
9841
9820
  }
9842
9821
  ) });
9843
9822
  };
9823
+ const schema$4 = objectType({
9824
+ email: stringType().email()
9825
+ });
9826
+ const CustomItems = () => {
9827
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9828
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
9829
+ /* @__PURE__ */ jsx(CustomItemsForm, {})
9830
+ ] });
9831
+ };
9832
+ const CustomItemsForm = () => {
9833
+ const form = useForm({
9834
+ resolver: zodResolver(schema$3)
9835
+ });
9836
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9837
+ /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
9838
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9839
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9840
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
9841
+ ] }) })
9842
+ ] }) });
9843
+ };
9844
9844
  const schema$3 = objectType({
9845
9845
  email: stringType().email()
9846
9846
  });
9847
- const PROMOTION_QUERY_KEY = "promotions";
9848
- const promotionsQueryKeys = {
9847
+ const NumberInput = forwardRef(
9848
+ ({
9849
+ value,
9850
+ onChange,
9851
+ size = "base",
9852
+ min = 0,
9853
+ max = 100,
9854
+ step = 1,
9855
+ className,
9856
+ disabled,
9857
+ ...props
9858
+ }, ref) => {
9859
+ const handleChange = (event) => {
9860
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
9861
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9862
+ onChange(newValue);
9863
+ }
9864
+ };
9865
+ const handleIncrement = () => {
9866
+ const newValue = value + step;
9867
+ if (max === void 0 || newValue <= max) {
9868
+ onChange(newValue);
9869
+ }
9870
+ };
9871
+ const handleDecrement = () => {
9872
+ const newValue = value - step;
9873
+ if (min === void 0 || newValue >= min) {
9874
+ onChange(newValue);
9875
+ }
9876
+ };
9877
+ return /* @__PURE__ */ jsxs(
9878
+ "div",
9879
+ {
9880
+ className: clx(
9881
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9882
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9883
+ {
9884
+ "h-7": size === "small",
9885
+ "h-8": size === "base"
9886
+ },
9887
+ className
9888
+ ),
9889
+ children: [
9890
+ /* @__PURE__ */ jsx(
9891
+ "input",
9892
+ {
9893
+ ref,
9894
+ type: "number",
9895
+ value,
9896
+ onChange: handleChange,
9897
+ min,
9898
+ max,
9899
+ step,
9900
+ className: clx(
9901
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9902
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9903
+ "placeholder:text-ui-fg-muted"
9904
+ ),
9905
+ ...props
9906
+ }
9907
+ ),
9908
+ /* @__PURE__ */ jsxs(
9909
+ "button",
9910
+ {
9911
+ className: clx(
9912
+ "flex items-center justify-center outline-none transition-fg",
9913
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9914
+ "focus:bg-ui-bg-field-component-hover",
9915
+ "hover:bg-ui-bg-field-component-hover",
9916
+ {
9917
+ "size-7": size === "small",
9918
+ "size-8": size === "base"
9919
+ }
9920
+ ),
9921
+ type: "button",
9922
+ onClick: handleDecrement,
9923
+ disabled: min !== void 0 && value <= min || disabled,
9924
+ children: [
9925
+ /* @__PURE__ */ jsx(Minus, {}),
9926
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9927
+ ]
9928
+ }
9929
+ ),
9930
+ /* @__PURE__ */ jsxs(
9931
+ "button",
9932
+ {
9933
+ className: clx(
9934
+ "flex items-center justify-center outline-none transition-fg",
9935
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9936
+ "focus:bg-ui-bg-field-hover",
9937
+ "hover:bg-ui-bg-field-hover",
9938
+ {
9939
+ "size-7": size === "small",
9940
+ "size-8": size === "base"
9941
+ }
9942
+ ),
9943
+ type: "button",
9944
+ onClick: handleIncrement,
9945
+ disabled: max !== void 0 && value >= max || disabled,
9946
+ children: [
9947
+ /* @__PURE__ */ jsx(Plus, {}),
9948
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9949
+ ]
9950
+ }
9951
+ )
9952
+ ]
9953
+ }
9954
+ );
9955
+ }
9956
+ );
9957
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9958
+ const productVariantsQueryKeys = {
9849
9959
  list: (query2) => [
9850
- PROMOTION_QUERY_KEY,
9851
- query2 ? query2 : void 0
9852
- ],
9853
- detail: (id, query2) => [
9854
- PROMOTION_QUERY_KEY,
9855
- id,
9960
+ PRODUCT_VARIANTS_QUERY_KEY,
9856
9961
  query2 ? query2 : void 0
9857
9962
  ]
9858
9963
  };
9859
- const usePromotions = (query2, options) => {
9964
+ const useProductVariants = (query2, options) => {
9860
9965
  const { data, ...rest } = useQuery({
9861
- queryKey: promotionsQueryKeys.list(query2),
9862
- queryFn: async () => sdk.admin.promotion.list(query2),
9966
+ queryKey: productVariantsQueryKeys.list(query2),
9967
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
9863
9968
  ...options
9864
9969
  });
9865
9970
  return { ...data, ...rest };
@@ -9910,97 +10015,77 @@ const useInitiateOrderEdit = ({
9910
10015
  run();
9911
10016
  }, [preview, navigate, mutateAsync]);
9912
10017
  };
9913
- const Promotions = () => {
10018
+ function convertNumber(value) {
10019
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10020
+ }
10021
+ const STACKED_MODAL_ID = "items_stacked_modal";
10022
+ const Items = () => {
9914
10023
  const { id } = useParams();
9915
10024
  const {
9916
10025
  order: preview,
10026
+ isPending: isPreviewPending,
9917
10027
  isError: isPreviewError,
9918
10028
  error: previewError
9919
- } = useOrderPreview(id, void 0);
10029
+ } = useOrderPreview(id, void 0, {
10030
+ placeholderData: keepPreviousData
10031
+ });
9920
10032
  useInitiateOrderEdit({ preview });
10033
+ const { draft_order, isPending, isError, error } = useDraftOrder(
10034
+ id,
10035
+ {
10036
+ fields: "currency_code"
10037
+ },
10038
+ {
10039
+ enabled: !!id
10040
+ }
10041
+ );
9921
10042
  const { onCancel } = useCancelOrderEdit({ preview });
10043
+ if (isError) {
10044
+ throw error;
10045
+ }
9922
10046
  if (isPreviewError) {
9923
10047
  throw previewError;
9924
10048
  }
9925
- const isReady = !!preview;
9926
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
9927
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
9928
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
9929
- ] });
10049
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10050
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10051
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10052
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10053
+ ] }) });
9930
10054
  };
9931
- const PromotionForm = ({ preview }) => {
9932
- const { items, shipping_methods } = preview;
10055
+ const ItemsForm = ({ preview, currencyCode }) => {
10056
+ var _a;
9933
10057
  const [isSubmitting, setIsSubmitting] = useState(false);
9934
- const [comboboxValue, setComboboxValue] = useState("");
10058
+ const [modalContent, setModalContent] = useState(
10059
+ null
10060
+ );
9935
10061
  const { handleSuccess } = useRouteModal();
9936
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
9937
- const promoIds = getPromotionIds(items, shipping_methods);
9938
- const { promotions, isPending, isError, error } = usePromotions(
9939
- {
9940
- id: promoIds
9941
- },
9942
- {
9943
- enabled: !!promoIds.length
9944
- }
9945
- );
9946
- const comboboxData = useComboboxData({
9947
- queryKey: ["promotions", "combobox", promoIds],
9948
- queryFn: async (params) => {
9949
- return await sdk.admin.promotion.list({
9950
- ...params,
9951
- id: {
9952
- $nin: promoIds
9953
- }
9954
- });
9955
- },
9956
- getOptions: (data) => {
9957
- return data.promotions.map((promotion) => ({
9958
- label: promotion.code,
9959
- value: promotion.code
9960
- }));
9961
- }
9962
- });
9963
- const add = async (value) => {
9964
- if (!value) {
9965
- return;
9966
- }
9967
- addPromotions(
9968
- {
9969
- promo_codes: [value]
9970
- },
9971
- {
9972
- onError: (e) => {
9973
- toast.error(e.message);
9974
- comboboxData.onSearchValueChange("");
9975
- setComboboxValue("");
9976
- },
9977
- onSuccess: () => {
9978
- comboboxData.onSearchValueChange("");
9979
- setComboboxValue("");
9980
- }
9981
- }
9982
- );
9983
- };
9984
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
9985
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
9986
- const onSubmit = async () => {
9987
- setIsSubmitting(true);
9988
- let requestSucceeded = false;
9989
- await requestOrderEdit(void 0, {
9990
- onError: (e) => {
9991
- toast.error(e.message);
9992
- },
9993
- onSuccess: () => {
9994
- requestSucceeded = true;
9995
- }
9996
- });
9997
- if (!requestSucceeded) {
9998
- setIsSubmitting(false);
9999
- return;
10062
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10063
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10064
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10065
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10066
+ const matches = useMemo(() => {
10067
+ return matchSorter(preview.items, query2, {
10068
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
10069
+ });
10070
+ }, [preview.items, query2]);
10071
+ const onSubmit = async () => {
10072
+ setIsSubmitting(true);
10073
+ let requestSucceeded = false;
10074
+ await requestOrderEdit(void 0, {
10075
+ onError: (e) => {
10076
+ toast.error(`Failed to request order edit: ${e.message}`);
10077
+ },
10078
+ onSuccess: () => {
10079
+ requestSucceeded = true;
10080
+ }
10081
+ });
10082
+ if (!requestSucceeded) {
10083
+ setIsSubmitting(false);
10084
+ return;
10000
10085
  }
10001
10086
  await confirmOrderEdit(void 0, {
10002
10087
  onError: (e) => {
10003
- toast.error(e.message);
10088
+ toast.error(`Failed to confirm order edit: ${e.message}`);
10004
10089
  },
10005
10090
  onSuccess: () => {
10006
10091
  handleSuccess();
@@ -10010,886 +10095,322 @@ const PromotionForm = ({ preview }) => {
10010
10095
  }
10011
10096
  });
10012
10097
  };
10013
- if (isError) {
10014
- throw error;
10015
- }
10016
- return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10017
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10018
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10019
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10020
- /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10021
- /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10022
- ] }),
10023
- /* @__PURE__ */ jsx(
10024
- Combobox,
10025
- {
10026
- id: "promotion-combobox",
10027
- "aria-describedby": "promotion-combobox-hint",
10028
- isFetchingNextPage: comboboxData.isFetchingNextPage,
10029
- fetchNextPage: comboboxData.fetchNextPage,
10030
- options: comboboxData.options,
10031
- onSearchValueChange: comboboxData.onSearchValueChange,
10032
- searchValue: comboboxData.searchValue,
10033
- disabled: comboboxData.disabled || isAddingPromotions,
10034
- onChange: add,
10035
- value: comboboxValue
10098
+ const onKeyDown = useCallback(
10099
+ (e) => {
10100
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10101
+ if (modalContent || isSubmitting) {
10102
+ return;
10103
+ }
10104
+ onSubmit();
10105
+ }
10106
+ },
10107
+ [modalContent, isSubmitting, onSubmit]
10108
+ );
10109
+ useEffect(() => {
10110
+ document.addEventListener("keydown", onKeyDown);
10111
+ return () => {
10112
+ document.removeEventListener("keydown", onKeyDown);
10113
+ };
10114
+ }, [onKeyDown]);
10115
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10116
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10117
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10118
+ StackedFocusModal,
10119
+ {
10120
+ id: STACKED_MODAL_ID,
10121
+ onOpenChangeCallback: (open) => {
10122
+ if (!open) {
10123
+ setModalContent(null);
10036
10124
  }
10037
- )
10038
- ] }),
10039
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10040
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10041
- PromotionItem,
10042
- {
10043
- promotion,
10044
- orderId: preview.id,
10045
- isLoading: isPending
10046
10125
  },
10047
- promotion.id
10048
- )) })
10049
- ] }) }),
10050
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10051
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10126
+ children: [
10127
+ /* @__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: [
10128
+ /* @__PURE__ */ jsxs("div", { children: [
10129
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10130
+ /* @__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" }) })
10131
+ ] }),
10132
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10133
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10134
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10135
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10136
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10137
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10138
+ ] }),
10139
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10140
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10141
+ Input,
10142
+ {
10143
+ type: "search",
10144
+ placeholder: "Search items",
10145
+ value: searchValue,
10146
+ onChange: (e) => onSearchValueChange(e.target.value)
10147
+ }
10148
+ ) }),
10149
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10150
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10151
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10152
+ /* @__PURE__ */ jsx(
10153
+ StackedModalTrigger$1,
10154
+ {
10155
+ type: "add-items",
10156
+ setModalContent
10157
+ }
10158
+ ),
10159
+ /* @__PURE__ */ jsx(
10160
+ StackedModalTrigger$1,
10161
+ {
10162
+ type: "add-custom-item",
10163
+ setModalContent
10164
+ }
10165
+ )
10166
+ ] })
10167
+ ] })
10168
+ ] })
10169
+ ] }),
10170
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10171
+ /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
10172
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10173
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10174
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10175
+ /* @__PURE__ */ jsx("div", {})
10176
+ ] }) }),
10177
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10178
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10179
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10180
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10181
+ Item,
10182
+ {
10183
+ item,
10184
+ preview,
10185
+ currencyCode
10186
+ },
10187
+ item.id
10188
+ )) : /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10189
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10190
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10191
+ 'No items found for "',
10192
+ query2,
10193
+ '".'
10194
+ ] })
10195
+ ] }) })
10196
+ ] })
10197
+ ] }),
10198
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10199
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10200
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10201
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10202
+ Text,
10203
+ {
10204
+ size: "small",
10205
+ leading: "compact",
10206
+ className: "text-ui-fg-subtle",
10207
+ children: [
10208
+ itemCount,
10209
+ " ",
10210
+ itemCount === 1 ? "item" : "items"
10211
+ ]
10212
+ }
10213
+ ) }),
10214
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10215
+ ] })
10216
+ ] }) }),
10217
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10218
+ CustomItemForm,
10219
+ {
10220
+ orderId: preview.id,
10221
+ currencyCode
10222
+ }
10223
+ ) : null)
10224
+ ]
10225
+ }
10226
+ ) }),
10227
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10228
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10052
10229
  /* @__PURE__ */ jsx(
10053
10230
  Button,
10054
10231
  {
10055
10232
  size: "small",
10056
- type: "submit",
10057
- isLoading: isSubmitting || isAddingPromotions,
10233
+ type: "button",
10234
+ onClick: onSubmit,
10235
+ isLoading: isSubmitting,
10058
10236
  children: "Save"
10059
10237
  }
10060
10238
  )
10061
10239
  ] }) })
10062
10240
  ] });
10063
10241
  };
10064
- const PromotionItem = ({
10065
- promotion,
10066
- orderId,
10067
- isLoading
10068
- }) => {
10069
- var _a;
10070
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10071
- const onRemove = async () => {
10072
- removePromotions(
10073
- {
10074
- promo_codes: [promotion.code]
10075
- },
10076
- {
10077
- onError: (e) => {
10078
- toast.error(e.message);
10079
- }
10080
- }
10081
- );
10082
- };
10083
- const displayValue = getDisplayValue(promotion);
10084
- return /* @__PURE__ */ jsxs(
10085
- "div",
10086
- {
10087
- className: clx(
10088
- "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
10089
- {
10090
- "animate-pulse": isLoading
10091
- }
10092
- ),
10093
- children: [
10094
- /* @__PURE__ */ jsxs("div", { children: [
10095
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10096
- /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
10097
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
10098
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
10099
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
10100
- ] }),
10101
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10102
- ] })
10103
- ] }),
10104
- /* @__PURE__ */ jsx(
10105
- IconButton,
10106
- {
10107
- size: "small",
10108
- type: "button",
10109
- variant: "transparent",
10110
- onClick: onRemove,
10111
- isLoading: isPending || isLoading,
10112
- children: /* @__PURE__ */ jsx(XMark, {})
10113
- }
10114
- )
10115
- ]
10116
- },
10117
- promotion.id
10118
- );
10119
- };
10120
- function getDisplayValue(promotion) {
10121
- var _a, _b, _c, _d;
10122
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10123
- if (!value) {
10124
- return null;
10125
- }
10126
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10127
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10128
- if (!currency) {
10129
- return null;
10130
- }
10131
- return getLocaleAmount(value, currency);
10132
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10133
- return formatPercentage(value);
10134
- }
10135
- return null;
10136
- }
10137
- const formatter = new Intl.NumberFormat([], {
10138
- style: "percent",
10139
- minimumFractionDigits: 2
10140
- });
10141
- const formatPercentage = (value, isPercentageValue = false) => {
10142
- let val = value || 0;
10143
- if (!isPercentageValue) {
10144
- val = val / 100;
10145
- }
10146
- return formatter.format(val);
10147
- };
10148
- function getPromotionIds(items, shippingMethods) {
10149
- const promotionIds = /* @__PURE__ */ new Set();
10150
- for (const item of items) {
10151
- if (item.adjustments) {
10152
- for (const adjustment of item.adjustments) {
10153
- if (adjustment.promotion_id) {
10154
- promotionIds.add(adjustment.promotion_id);
10155
- }
10156
- }
10157
- }
10158
- }
10159
- for (const shippingMethod of shippingMethods) {
10160
- if (shippingMethod.adjustments) {
10161
- for (const adjustment of shippingMethod.adjustments) {
10162
- if (adjustment.promotion_id) {
10163
- promotionIds.add(adjustment.promotion_id);
10164
- }
10165
- }
10166
- }
10167
- }
10168
- return Array.from(promotionIds);
10169
- }
10170
- const InlineTip = forwardRef(
10171
- ({ variant = "tip", label, className, children, ...props }, ref) => {
10172
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10173
- return /* @__PURE__ */ jsxs(
10174
- "div",
10175
- {
10176
- ref,
10177
- className: clx(
10178
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10179
- className
10180
- ),
10181
- ...props,
10182
- children: [
10183
- /* @__PURE__ */ jsx(
10184
- "div",
10185
- {
10186
- role: "presentation",
10187
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10188
- "bg-ui-tag-orange-icon": variant === "warning"
10189
- })
10190
- }
10191
- ),
10192
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10193
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10194
- labelValue,
10195
- ":"
10196
- ] }),
10197
- " ",
10198
- children
10199
- ] })
10200
- ]
10201
- }
10202
- );
10203
- }
10204
- );
10205
- InlineTip.displayName = "InlineTip";
10206
- const MetadataFieldSchema = objectType({
10207
- key: stringType(),
10208
- disabled: booleanType().optional(),
10209
- value: anyType()
10210
- });
10211
- const MetadataSchema = objectType({
10212
- metadata: arrayType(MetadataFieldSchema)
10213
- });
10214
- const Metadata = () => {
10215
- const { id } = useParams();
10216
- const { order, isPending, isError, error } = useOrder(id, {
10217
- fields: "metadata"
10218
- });
10219
- if (isError) {
10220
- throw error;
10242
+ const Item = ({ item, preview, currencyCode }) => {
10243
+ if (item.variant_id) {
10244
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10221
10245
  }
10222
- const isReady = !isPending && !!order;
10223
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10224
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10225
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10226
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10227
- ] }),
10228
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10229
- ] });
10246
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10230
10247
  };
10231
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10232
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10233
- const MetadataForm = ({ orderId, metadata }) => {
10234
- const { handleSuccess } = useRouteModal();
10235
- const hasUneditableRows = getHasUneditableRows(metadata);
10236
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10248
+ const VariantItem = ({ item, preview, currencyCode }) => {
10249
+ const [editing, setEditing] = useState(false);
10237
10250
  const form = useForm({
10238
10251
  defaultValues: {
10239
- metadata: getDefaultValues(metadata)
10252
+ quantity: item.quantity,
10253
+ unit_price: item.unit_price
10240
10254
  },
10241
- resolver: zodResolver(MetadataSchema)
10255
+ resolver: zodResolver(variantItemSchema)
10242
10256
  });
10243
- const handleSubmit = form.handleSubmit(async (data) => {
10244
- const parsedData = parseValues(data);
10245
- await mutateAsync(
10257
+ const actionId = useMemo(() => {
10258
+ var _a, _b;
10259
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10260
+ }, [item]);
10261
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10262
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10263
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10264
+ const onSubmit = form.handleSubmit(async (data) => {
10265
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10266
+ setEditing(false);
10267
+ return;
10268
+ }
10269
+ if (!actionId) {
10270
+ await updateOriginalItem(
10271
+ {
10272
+ item_id: item.id,
10273
+ quantity: data.quantity,
10274
+ unit_price: convertNumber(data.unit_price)
10275
+ },
10276
+ {
10277
+ onSuccess: () => {
10278
+ setEditing(false);
10279
+ },
10280
+ onError: (e) => {
10281
+ toast.error(e.message);
10282
+ }
10283
+ }
10284
+ );
10285
+ return;
10286
+ }
10287
+ await updateActionItem(
10246
10288
  {
10247
- metadata: parsedData
10289
+ action_id: actionId,
10290
+ quantity: data.quantity,
10291
+ unit_price: convertNumber(data.unit_price)
10248
10292
  },
10249
10293
  {
10250
10294
  onSuccess: () => {
10251
- toast.success("Metadata updated");
10252
- handleSuccess();
10295
+ setEditing(false);
10253
10296
  },
10254
- onError: (error) => {
10255
- toast.error(error.message);
10297
+ onError: (e) => {
10298
+ toast.error(e.message);
10256
10299
  }
10257
10300
  }
10258
10301
  );
10259
10302
  });
10260
- const { fields, insert, remove } = useFieldArray({
10261
- control: form.control,
10262
- name: "metadata"
10263
- });
10264
- function deleteRow(index) {
10265
- remove(index);
10266
- if (fields.length === 1) {
10267
- insert(0, {
10268
- key: "",
10269
- value: "",
10270
- disabled: false
10271
- });
10272
- }
10273
- }
10274
- function insertRow(index, position) {
10275
- insert(index + (position === "above" ? 0 : 1), {
10276
- key: "",
10277
- value: "",
10278
- disabled: false
10279
- });
10280
- }
10281
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10282
- KeyboundForm,
10283
- {
10284
- onSubmit: handleSubmit,
10285
- className: "flex flex-1 flex-col overflow-hidden",
10286
- children: [
10287
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10288
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10289
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10290
- /* @__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" }) }),
10291
- /* @__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" }) })
10292
- ] }),
10293
- fields.map((field, index) => {
10294
- const isDisabled = field.disabled || false;
10295
- let placeholder = "-";
10296
- if (typeof field.value === "object") {
10297
- placeholder = "{ ... }";
10298
- }
10299
- if (Array.isArray(field.value)) {
10300
- placeholder = "[ ... ]";
10301
- }
10302
- return /* @__PURE__ */ jsx(
10303
- ConditionalTooltip,
10304
- {
10305
- showTooltip: isDisabled,
10306
- content: "This row is disabled because it contains non-primitive data.",
10307
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10308
- /* @__PURE__ */ jsxs(
10309
- "div",
10310
- {
10311
- className: clx("grid grid-cols-2 divide-x", {
10312
- "overflow-hidden rounded-b-lg": index === fields.length - 1
10313
- }),
10314
- children: [
10315
- /* @__PURE__ */ jsx(
10316
- Form$2.Field,
10317
- {
10318
- control: form.control,
10319
- name: `metadata.${index}.key`,
10320
- render: ({ field: field2 }) => {
10321
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10322
- GridInput,
10323
- {
10324
- "aria-labelledby": METADATA_KEY_LABEL_ID,
10325
- ...field2,
10326
- disabled: isDisabled,
10327
- placeholder: "Key"
10328
- }
10329
- ) }) });
10330
- }
10331
- }
10332
- ),
10333
- /* @__PURE__ */ jsx(
10334
- Form$2.Field,
10335
- {
10336
- control: form.control,
10337
- name: `metadata.${index}.value`,
10338
- render: ({ field: { value, ...field2 } }) => {
10339
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10340
- GridInput,
10341
- {
10342
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10343
- ...field2,
10344
- value: isDisabled ? placeholder : value,
10345
- disabled: isDisabled,
10346
- placeholder: "Value"
10347
- }
10348
- ) }) });
10349
- }
10350
- }
10351
- )
10352
- ]
10353
- }
10354
- ),
10355
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10356
- /* @__PURE__ */ jsx(
10357
- DropdownMenu.Trigger,
10358
- {
10359
- className: clx(
10360
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10361
- {
10362
- hidden: isDisabled
10363
- }
10364
- ),
10365
- disabled: isDisabled,
10366
- asChild: true,
10367
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10368
- }
10369
- ),
10370
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10371
- /* @__PURE__ */ jsxs(
10372
- DropdownMenu.Item,
10373
- {
10374
- className: "gap-x-2",
10375
- onClick: () => insertRow(index, "above"),
10376
- children: [
10377
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10378
- "Insert row above"
10379
- ]
10380
- }
10381
- ),
10382
- /* @__PURE__ */ jsxs(
10383
- DropdownMenu.Item,
10384
- {
10385
- className: "gap-x-2",
10386
- onClick: () => insertRow(index, "below"),
10387
- children: [
10388
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10389
- "Insert row below"
10390
- ]
10391
- }
10392
- ),
10393
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10394
- /* @__PURE__ */ jsxs(
10395
- DropdownMenu.Item,
10396
- {
10397
- className: "gap-x-2",
10398
- onClick: () => deleteRow(index),
10399
- children: [
10400
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10401
- "Delete row"
10402
- ]
10403
- }
10404
- )
10405
- ] })
10406
- ] })
10407
- ] })
10408
- },
10409
- field.id
10410
- );
10411
- })
10412
- ] }),
10413
- 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." })
10414
- ] }),
10415
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10416
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10417
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10418
- ] }) })
10419
- ]
10420
- }
10421
- ) });
10422
- };
10423
- const GridInput = forwardRef(({ className, ...props }, ref) => {
10424
- return /* @__PURE__ */ jsx(
10425
- "input",
10426
- {
10427
- ref,
10428
- ...props,
10429
- autoComplete: "off",
10430
- className: clx(
10431
- "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",
10432
- className
10433
- )
10434
- }
10435
- );
10436
- });
10437
- GridInput.displayName = "MetadataForm.GridInput";
10438
- const PlaceholderInner = () => {
10439
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10440
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10441
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10442
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10443
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10444
- ] }) })
10445
- ] });
10446
- };
10447
- const EDITABLE_TYPES = ["string", "number", "boolean"];
10448
- function getDefaultValues(metadata) {
10449
- if (!metadata || !Object.keys(metadata).length) {
10450
- return [
10451
- {
10452
- key: "",
10453
- value: "",
10454
- disabled: false
10455
- }
10456
- ];
10457
- }
10458
- return Object.entries(metadata).map(([key, value]) => {
10459
- if (!EDITABLE_TYPES.includes(typeof value)) {
10460
- return {
10461
- key,
10462
- value,
10463
- disabled: true
10464
- };
10465
- }
10466
- let stringValue = value;
10467
- if (typeof value !== "string") {
10468
- stringValue = JSON.stringify(value);
10469
- }
10470
- return {
10471
- key,
10472
- value: stringValue,
10473
- original_key: key
10474
- };
10475
- });
10476
- }
10477
- function parseValues(values) {
10478
- const metadata = values.metadata;
10479
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10480
- if (isEmpty) {
10481
- return null;
10482
- }
10483
- const update = {};
10484
- metadata.forEach((field) => {
10485
- let key = field.key;
10486
- let value = field.value;
10487
- const disabled = field.disabled;
10488
- if (!key || !value) {
10489
- return;
10490
- }
10491
- if (disabled) {
10492
- update[key] = value;
10493
- return;
10494
- }
10495
- key = key.trim();
10496
- value = value.trim();
10497
- if (value === "true") {
10498
- update[key] = true;
10499
- } else if (value === "false") {
10500
- update[key] = false;
10501
- } else {
10502
- const parsedNumber = parseFloat(value);
10503
- if (!isNaN(parsedNumber)) {
10504
- update[key] = parsedNumber;
10505
- } else {
10506
- update[key] = value;
10507
- }
10508
- }
10509
- });
10510
- return update;
10511
- }
10512
- function getHasUneditableRows(metadata) {
10513
- if (!metadata) {
10514
- return false;
10515
- }
10516
- return Object.values(metadata).some(
10517
- (value) => !EDITABLE_TYPES.includes(typeof value)
10518
- );
10519
- }
10520
- const NumberInput = forwardRef(
10521
- ({
10522
- value,
10523
- onChange,
10524
- size = "base",
10525
- min = 0,
10526
- max = 100,
10527
- step = 1,
10528
- className,
10529
- disabled,
10530
- ...props
10531
- }, ref) => {
10532
- const handleChange = (event) => {
10533
- const newValue = event.target.value === "" ? min : Number(event.target.value);
10534
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
10535
- onChange(newValue);
10536
- }
10537
- };
10538
- const handleIncrement = () => {
10539
- const newValue = value + step;
10540
- if (max === void 0 || newValue <= max) {
10541
- onChange(newValue);
10542
- }
10543
- };
10544
- const handleDecrement = () => {
10545
- const newValue = value - step;
10546
- if (min === void 0 || newValue >= min) {
10547
- onChange(newValue);
10548
- }
10549
- };
10550
- return /* @__PURE__ */ jsxs(
10551
- "div",
10552
- {
10553
- className: clx(
10554
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
10555
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
10556
- {
10557
- "h-7": size === "small",
10558
- "h-8": size === "base"
10559
- },
10560
- className
10561
- ),
10562
- children: [
10563
- /* @__PURE__ */ jsx(
10564
- "input",
10565
- {
10566
- ref,
10567
- type: "number",
10568
- value,
10569
- onChange: handleChange,
10570
- min,
10571
- max,
10572
- step,
10573
- className: clx(
10574
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
10575
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
10576
- "placeholder:text-ui-fg-muted"
10577
- ),
10578
- ...props
10579
- }
10580
- ),
10581
- /* @__PURE__ */ jsxs(
10582
- "button",
10583
- {
10584
- className: clx(
10585
- "flex items-center justify-center outline-none transition-fg",
10586
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10587
- "focus:bg-ui-bg-field-component-hover",
10588
- "hover:bg-ui-bg-field-component-hover",
10589
- {
10590
- "size-7": size === "small",
10591
- "size-8": size === "base"
10592
- }
10593
- ),
10594
- type: "button",
10595
- onClick: handleDecrement,
10596
- disabled: min !== void 0 && value <= min || disabled,
10597
- children: [
10598
- /* @__PURE__ */ jsx(Minus, {}),
10599
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
10600
- ]
10601
- }
10602
- ),
10603
- /* @__PURE__ */ jsxs(
10604
- "button",
10605
- {
10606
- className: clx(
10607
- "flex items-center justify-center outline-none transition-fg",
10608
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10609
- "focus:bg-ui-bg-field-hover",
10610
- "hover:bg-ui-bg-field-hover",
10611
- {
10612
- "size-7": size === "small",
10613
- "size-8": size === "base"
10614
- }
10615
- ),
10616
- type: "button",
10617
- onClick: handleIncrement,
10618
- disabled: max !== void 0 && value >= max || disabled,
10619
- children: [
10620
- /* @__PURE__ */ jsx(Plus, {}),
10621
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
10622
- ]
10623
- }
10624
- )
10625
- ]
10626
- }
10627
- );
10628
- }
10629
- );
10630
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
10631
- const productVariantsQueryKeys = {
10632
- list: (query2) => [
10633
- PRODUCT_VARIANTS_QUERY_KEY,
10634
- query2 ? query2 : void 0
10635
- ]
10636
- };
10637
- const useProductVariants = (query2, options) => {
10638
- const { data, ...rest } = useQuery({
10639
- queryKey: productVariantsQueryKeys.list(query2),
10640
- queryFn: async () => await sdk.admin.productVariant.list(query2),
10641
- ...options
10642
- });
10643
- return { ...data, ...rest };
10644
- };
10645
- function convertNumber(value) {
10646
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10647
- }
10648
- const STACKED_MODAL_ID = "items_stacked_modal";
10649
- const Items = () => {
10650
- const { id } = useParams();
10651
- const {
10652
- order: preview,
10653
- isPending: isPreviewPending,
10654
- isError: isPreviewError,
10655
- error: previewError
10656
- } = useOrderPreview(id, void 0, {
10657
- placeholderData: keepPreviousData
10658
- });
10659
- useInitiateOrderEdit({ preview });
10660
- const { draft_order, isPending, isError, error } = useDraftOrder(
10661
- id,
10662
- {
10663
- fields: "currency_code"
10664
- },
10665
- {
10666
- enabled: !!id
10667
- }
10668
- );
10669
- const { onCancel } = useCancelOrderEdit({ preview });
10670
- if (isError) {
10671
- throw error;
10672
- }
10673
- if (isPreviewError) {
10674
- throw previewError;
10675
- }
10676
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10677
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10678
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10679
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10680
- ] }) });
10681
- };
10682
- const ItemsForm = ({ preview, currencyCode }) => {
10683
- var _a;
10684
- const [isSubmitting, setIsSubmitting] = useState(false);
10685
- const [modalContent, setModalContent] = useState(
10686
- null
10687
- );
10688
- const { handleSuccess } = useRouteModal();
10689
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10690
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10691
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10692
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10693
- const matches = useMemo(() => {
10694
- return matchSorter(preview.items, query2, {
10695
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10696
- });
10697
- }, [preview.items, query2]);
10698
- const onSubmit = async () => {
10699
- setIsSubmitting(true);
10700
- let requestSucceeded = false;
10701
- await requestOrderEdit(void 0, {
10702
- onError: (e) => {
10703
- toast.error(`Failed to request order edit: ${e.message}`);
10704
- },
10705
- onSuccess: () => {
10706
- requestSucceeded = true;
10707
- }
10708
- });
10709
- if (!requestSucceeded) {
10710
- setIsSubmitting(false);
10711
- return;
10712
- }
10713
- await confirmOrderEdit(void 0, {
10714
- onError: (e) => {
10715
- toast.error(`Failed to confirm order edit: ${e.message}`);
10716
- },
10717
- onSuccess: () => {
10718
- handleSuccess();
10719
- },
10720
- onSettled: () => {
10721
- setIsSubmitting(false);
10722
- }
10723
- });
10724
- };
10725
- const onKeyDown = useCallback(
10726
- (e) => {
10727
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10728
- if (modalContent || isSubmitting) {
10729
- return;
10303
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10304
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10305
+ /* @__PURE__ */ jsx(
10306
+ Thumbnail,
10307
+ {
10308
+ thumbnail: item.thumbnail,
10309
+ alt: item.product_title ?? void 0
10310
+ }
10311
+ ),
10312
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10313
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10314
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10315
+ /* @__PURE__ */ jsxs(
10316
+ Text,
10317
+ {
10318
+ size: "small",
10319
+ leading: "compact",
10320
+ className: "text-ui-fg-subtle",
10321
+ children: [
10322
+ "(",
10323
+ item.variant_title,
10324
+ ")"
10325
+ ]
10326
+ }
10327
+ )
10328
+ ] }),
10329
+ /* @__PURE__ */ jsx(
10330
+ Text,
10331
+ {
10332
+ size: "small",
10333
+ leading: "compact",
10334
+ className: "text-ui-fg-subtle",
10335
+ children: item.variant_sku
10336
+ }
10337
+ )
10338
+ ] })
10339
+ ] }),
10340
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10341
+ Form$2.Field,
10342
+ {
10343
+ control: form.control,
10344
+ name: "quantity",
10345
+ render: ({ field }) => {
10346
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10730
10347
  }
10731
- onSubmit();
10732
10348
  }
10733
- },
10734
- [modalContent, isSubmitting, onSubmit]
10735
- );
10736
- useEffect(() => {
10737
- document.addEventListener("keydown", onKeyDown);
10738
- return () => {
10739
- document.removeEventListener("keydown", onKeyDown);
10740
- };
10741
- }, [onKeyDown]);
10742
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10743
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10744
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10745
- StackedFocusModal,
10349
+ ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10350
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10351
+ Form$2.Field,
10746
10352
  {
10747
- id: STACKED_MODAL_ID,
10748
- onOpenChangeCallback: (open) => {
10749
- if (!open) {
10750
- setModalContent(null);
10751
- }
10752
- },
10753
- children: [
10754
- /* @__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: [
10755
- /* @__PURE__ */ jsxs("div", { children: [
10756
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10757
- /* @__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" }) })
10758
- ] }),
10759
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10760
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10761
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10762
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10763
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10764
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10765
- ] }),
10766
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10767
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10768
- Input,
10769
- {
10770
- type: "search",
10771
- placeholder: "Search items",
10772
- value: searchValue,
10773
- onChange: (e) => onSearchValueChange(e.target.value)
10774
- }
10775
- ) }),
10776
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10777
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10778
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10779
- /* @__PURE__ */ jsx(
10780
- StackedModalTrigger$1,
10781
- {
10782
- type: "add-items",
10783
- setModalContent
10784
- }
10785
- ),
10786
- /* @__PURE__ */ jsx(
10787
- StackedModalTrigger$1,
10788
- {
10789
- type: "add-custom-item",
10790
- setModalContent
10791
- }
10792
- )
10793
- ] })
10794
- ] })
10795
- ] })
10796
- ] }),
10797
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10798
- /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
10799
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10800
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10801
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10802
- /* @__PURE__ */ jsx("div", {})
10803
- ] }) }),
10804
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10805
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10806
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10807
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10808
- Item,
10809
- {
10810
- item,
10811
- preview,
10812
- currencyCode
10813
- },
10814
- item.id
10815
- )) : /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10816
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10817
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10818
- 'No items found for "',
10819
- query2,
10820
- '".'
10821
- ] })
10822
- ] }) })
10823
- ] })
10824
- ] }),
10825
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10826
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10827
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10828
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10829
- Text,
10830
- {
10831
- size: "small",
10832
- leading: "compact",
10833
- className: "text-ui-fg-subtle",
10834
- children: [
10835
- itemCount,
10836
- " ",
10837
- itemCount === 1 ? "item" : "items"
10838
- ]
10839
- }
10840
- ) }),
10841
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10842
- ] })
10843
- ] }) }),
10844
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10845
- CustomItemForm,
10353
+ control: form.control,
10354
+ name: "unit_price",
10355
+ render: ({ field: { onChange, ...field } }) => {
10356
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10357
+ CurrencyInput,
10846
10358
  {
10847
- orderId: preview.id,
10848
- currencyCode
10359
+ ...field,
10360
+ symbol: getNativeSymbol(currencyCode),
10361
+ code: currencyCode,
10362
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10849
10363
  }
10850
- ) : null)
10851
- ]
10852
- }
10853
- ) }),
10854
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10855
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10856
- /* @__PURE__ */ jsx(
10857
- Button,
10858
- {
10859
- size: "small",
10860
- type: "button",
10861
- onClick: onSubmit,
10862
- isLoading: isSubmitting,
10863
- children: "Save"
10364
+ ) }) });
10864
10365
  }
10865
- )
10866
- ] }) })
10867
- ] });
10868
- };
10869
- const Item = ({ item, preview, currencyCode }) => {
10870
- if (item.variant_id) {
10871
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10872
- }
10873
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10366
+ }
10367
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10368
+ /* @__PURE__ */ jsx(
10369
+ IconButton,
10370
+ {
10371
+ type: "button",
10372
+ size: "small",
10373
+ onClick: editing ? onSubmit : () => {
10374
+ setEditing(true);
10375
+ },
10376
+ disabled: isPending,
10377
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10378
+ }
10379
+ )
10380
+ ] }) }) });
10874
10381
  };
10875
- const VariantItem = ({ item, preview, currencyCode }) => {
10382
+ const variantItemSchema = objectType({
10383
+ quantity: numberType(),
10384
+ unit_price: unionType([numberType(), stringType()])
10385
+ });
10386
+ const CustomItem = ({ item, preview, currencyCode }) => {
10876
10387
  const [editing, setEditing] = useState(false);
10388
+ const { quantity, unit_price, title } = item;
10877
10389
  const form = useForm({
10878
10390
  defaultValues: {
10879
- quantity: item.quantity,
10880
- unit_price: item.unit_price
10391
+ title,
10392
+ quantity,
10393
+ unit_price
10881
10394
  },
10882
- resolver: zodResolver(variantItemSchema)
10395
+ resolver: zodResolver(customItemSchema)
10883
10396
  });
10397
+ useEffect(() => {
10398
+ form.reset({
10399
+ title,
10400
+ quantity,
10401
+ unit_price
10402
+ });
10403
+ }, [form, title, quantity, unit_price]);
10884
10404
  const actionId = useMemo(() => {
10885
10405
  var _a, _b;
10886
10406
  return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10887
10407
  }, [item]);
10888
10408
  const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10409
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10889
10410
  const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10890
10411
  const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10891
10412
  const onSubmit = form.handleSubmit(async (data) => {
10892
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10413
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10893
10414
  setEditing(false);
10894
10415
  return;
10895
10416
  }
@@ -10911,6 +10432,17 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10911
10432
  );
10912
10433
  return;
10913
10434
  }
10435
+ if (data.quantity === 0) {
10436
+ await removeActionItem(actionId, {
10437
+ onSuccess: () => {
10438
+ setEditing(false);
10439
+ },
10440
+ onError: (e) => {
10441
+ toast.error(e.message);
10442
+ }
10443
+ });
10444
+ return;
10445
+ }
10914
10446
  await updateActionItem(
10915
10447
  {
10916
10448
  action_id: actionId,
@@ -10928,43 +10460,26 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10928
10460
  );
10929
10461
  });
10930
10462
  return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10931
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10463
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10932
10464
  /* @__PURE__ */ jsx(
10933
10465
  Thumbnail,
10934
10466
  {
10935
10467
  thumbnail: item.thumbnail,
10936
- alt: item.product_title ?? void 0
10468
+ alt: item.title ?? void 0
10937
10469
  }
10938
10470
  ),
10939
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10940
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10941
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10942
- /* @__PURE__ */ jsxs(
10943
- Text,
10944
- {
10945
- size: "small",
10946
- leading: "compact",
10947
- className: "text-ui-fg-subtle",
10948
- children: [
10949
- "(",
10950
- item.variant_title,
10951
- ")"
10952
- ]
10953
- }
10954
- )
10955
- ] }),
10956
- /* @__PURE__ */ jsx(
10957
- Text,
10958
- {
10959
- size: "small",
10960
- leading: "compact",
10961
- className: "text-ui-fg-subtle",
10962
- children: item.variant_sku
10471
+ editing ? /* @__PURE__ */ jsx(
10472
+ Form$2.Field,
10473
+ {
10474
+ control: form.control,
10475
+ name: "title",
10476
+ render: ({ field }) => {
10477
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10963
10478
  }
10964
- )
10965
- ] })
10479
+ }
10480
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10966
10481
  ] }),
10967
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10482
+ editing ? /* @__PURE__ */ jsx(
10968
10483
  Form$2.Field,
10969
10484
  {
10970
10485
  control: form.control,
@@ -10973,8 +10488,8 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10973
10488
  return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10974
10489
  }
10975
10490
  }
10976
- ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10977
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10491
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10492
+ editing ? /* @__PURE__ */ jsx(
10978
10493
  Form$2.Field,
10979
10494
  {
10980
10495
  control: form.control,
@@ -10983,102 +10498,238 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10983
10498
  return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10984
10499
  CurrencyInput,
10985
10500
  {
10986
- ...field,
10987
- symbol: getNativeSymbol(currencyCode),
10988
- code: currencyCode,
10989
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10501
+ ...field,
10502
+ symbol: getNativeSymbol(currencyCode),
10503
+ code: currencyCode,
10504
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10505
+ }
10506
+ ) }) });
10507
+ }
10508
+ }
10509
+ ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10510
+ /* @__PURE__ */ jsx(
10511
+ IconButton,
10512
+ {
10513
+ type: "button",
10514
+ size: "small",
10515
+ onClick: editing ? onSubmit : () => {
10516
+ setEditing(true);
10517
+ },
10518
+ disabled: isPending,
10519
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10520
+ }
10521
+ )
10522
+ ] }) }) });
10523
+ };
10524
+ const StackedModalTrigger$1 = ({
10525
+ type,
10526
+ setModalContent
10527
+ }) => {
10528
+ const { setIsOpen } = useStackedModal();
10529
+ const onClick = useCallback(() => {
10530
+ setModalContent(type);
10531
+ setIsOpen(STACKED_MODAL_ID, true);
10532
+ }, [setModalContent, setIsOpen, type]);
10533
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10534
+ };
10535
+ const VARIANT_PREFIX = "items";
10536
+ const LIMIT = 50;
10537
+ const ExistingItemsForm = ({ orderId, items }) => {
10538
+ const { setIsOpen } = useStackedModal();
10539
+ const [rowSelection, setRowSelection] = useState(
10540
+ items.reduce((acc, item) => {
10541
+ acc[item.variant_id] = true;
10542
+ return acc;
10543
+ }, {})
10544
+ );
10545
+ useEffect(() => {
10546
+ setRowSelection(
10547
+ items.reduce((acc, item) => {
10548
+ if (item.variant_id) {
10549
+ acc[item.variant_id] = true;
10550
+ }
10551
+ return acc;
10552
+ }, {})
10553
+ );
10554
+ }, [items]);
10555
+ const { q, order, offset } = useQueryParams(
10556
+ ["q", "order", "offset"],
10557
+ VARIANT_PREFIX
10558
+ );
10559
+ const { variants, count, isPending, isError, error } = useProductVariants(
10560
+ {
10561
+ q,
10562
+ order,
10563
+ offset: offset ? parseInt(offset) : void 0,
10564
+ limit: LIMIT
10565
+ },
10566
+ {
10567
+ placeholderData: keepPreviousData
10568
+ }
10569
+ );
10570
+ const columns = useColumns();
10571
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10572
+ const onSubmit = async () => {
10573
+ const ids = Object.keys(rowSelection).filter(
10574
+ (id) => !items.find((i) => i.variant_id === id)
10575
+ );
10576
+ await mutateAsync(
10577
+ {
10578
+ items: ids.map((id) => ({
10579
+ variant_id: id,
10580
+ quantity: 1
10581
+ }))
10582
+ },
10583
+ {
10584
+ onSuccess: () => {
10585
+ setRowSelection({});
10586
+ setIsOpen(STACKED_MODAL_ID, false);
10587
+ },
10588
+ onError: (e) => {
10589
+ toast.error(e.message);
10590
+ }
10591
+ }
10592
+ );
10593
+ };
10594
+ if (isError) {
10595
+ throw error;
10596
+ }
10597
+ return /* @__PURE__ */ jsxs(
10598
+ StackedFocusModal.Content,
10599
+ {
10600
+ onOpenAutoFocus: (e) => {
10601
+ e.preventDefault();
10602
+ const searchInput = document.querySelector(
10603
+ "[data-modal-id='modal-search-input']"
10604
+ );
10605
+ if (searchInput) {
10606
+ searchInput.focus();
10607
+ }
10608
+ },
10609
+ children: [
10610
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10611
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10612
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10613
+ ] }),
10614
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10615
+ DataTable,
10616
+ {
10617
+ data: variants,
10618
+ columns,
10619
+ isLoading: isPending,
10620
+ getRowId: (row) => row.id,
10621
+ rowCount: count,
10622
+ prefix: VARIANT_PREFIX,
10623
+ layout: "fill",
10624
+ rowSelection: {
10625
+ state: rowSelection,
10626
+ onRowSelectionChange: setRowSelection,
10627
+ enableRowSelection: (row) => {
10628
+ return !items.find((i) => i.variant_id === row.original.id);
10629
+ }
10630
+ },
10631
+ autoFocusSearch: true
10632
+ }
10633
+ ) }),
10634
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10635
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10636
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10637
+ ] }) })
10638
+ ]
10639
+ }
10640
+ );
10641
+ };
10642
+ const columnHelper = createDataTableColumnHelper();
10643
+ const useColumns = () => {
10644
+ return useMemo(() => {
10645
+ return [
10646
+ columnHelper.select(),
10647
+ columnHelper.accessor("product.title", {
10648
+ header: "Product",
10649
+ cell: ({ row }) => {
10650
+ var _a, _b, _c;
10651
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10652
+ /* @__PURE__ */ jsx(
10653
+ Thumbnail,
10654
+ {
10655
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10656
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
10657
+ }
10658
+ ),
10659
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10660
+ ] });
10661
+ },
10662
+ enableSorting: true
10663
+ }),
10664
+ columnHelper.accessor("title", {
10665
+ header: "Variant",
10666
+ enableSorting: true
10667
+ }),
10668
+ columnHelper.accessor("sku", {
10669
+ header: "SKU",
10670
+ cell: ({ getValue }) => {
10671
+ return getValue() ?? "-";
10672
+ },
10673
+ enableSorting: true
10674
+ }),
10675
+ columnHelper.accessor("updated_at", {
10676
+ header: "Updated",
10677
+ cell: ({ getValue }) => {
10678
+ return /* @__PURE__ */ jsx(
10679
+ Tooltip,
10680
+ {
10681
+ content: getFullDate({ date: getValue(), includeTime: true }),
10682
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10683
+ }
10684
+ );
10685
+ },
10686
+ enableSorting: true,
10687
+ sortAscLabel: "Oldest first",
10688
+ sortDescLabel: "Newest first"
10689
+ }),
10690
+ columnHelper.accessor("created_at", {
10691
+ header: "Created",
10692
+ cell: ({ getValue }) => {
10693
+ return /* @__PURE__ */ jsx(
10694
+ Tooltip,
10695
+ {
10696
+ content: getFullDate({ date: getValue(), includeTime: true }),
10697
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10990
10698
  }
10991
- ) }) });
10992
- }
10993
- }
10994
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10995
- /* @__PURE__ */ jsx(
10996
- IconButton,
10997
- {
10998
- type: "button",
10999
- size: "small",
11000
- onClick: editing ? onSubmit : () => {
11001
- setEditing(true);
10699
+ );
11002
10700
  },
11003
- disabled: isPending,
11004
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
11005
- }
11006
- )
11007
- ] }) }) });
10701
+ enableSorting: true,
10702
+ sortAscLabel: "Oldest first",
10703
+ sortDescLabel: "Newest first"
10704
+ })
10705
+ ];
10706
+ }, []);
11008
10707
  };
11009
- const variantItemSchema = objectType({
11010
- quantity: numberType(),
11011
- unit_price: unionType([numberType(), stringType()])
11012
- });
11013
- const CustomItem = ({ item, preview, currencyCode }) => {
11014
- const [editing, setEditing] = useState(false);
11015
- const { quantity, unit_price, title } = item;
10708
+ const CustomItemForm = ({ orderId, currencyCode }) => {
10709
+ const { setIsOpen } = useStackedModal();
10710
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
11016
10711
  const form = useForm({
11017
10712
  defaultValues: {
11018
- title,
11019
- quantity,
11020
- unit_price
10713
+ title: "",
10714
+ quantity: 1,
10715
+ unit_price: ""
11021
10716
  },
11022
10717
  resolver: zodResolver(customItemSchema)
11023
10718
  });
11024
- useEffect(() => {
11025
- form.reset({
11026
- title,
11027
- quantity,
11028
- unit_price
11029
- });
11030
- }, [form, title, quantity, unit_price]);
11031
- const actionId = useMemo(() => {
11032
- var _a, _b;
11033
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
11034
- }, [item]);
11035
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
11036
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
11037
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
11038
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
11039
10719
  const onSubmit = form.handleSubmit(async (data) => {
11040
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
11041
- setEditing(false);
11042
- return;
11043
- }
11044
- if (!actionId) {
11045
- await updateOriginalItem(
11046
- {
11047
- item_id: item.id,
11048
- quantity: data.quantity,
11049
- unit_price: convertNumber(data.unit_price)
11050
- },
11051
- {
11052
- onSuccess: () => {
11053
- setEditing(false);
11054
- },
11055
- onError: (e) => {
11056
- toast.error(e.message);
11057
- }
11058
- }
11059
- );
11060
- return;
11061
- }
11062
- if (data.quantity === 0) {
11063
- await removeActionItem(actionId, {
11064
- onSuccess: () => {
11065
- setEditing(false);
11066
- },
11067
- onError: (e) => {
11068
- toast.error(e.message);
11069
- }
11070
- });
11071
- return;
11072
- }
11073
- await updateActionItem(
10720
+ await addItems(
11074
10721
  {
11075
- action_id: actionId,
11076
- quantity: data.quantity,
11077
- unit_price: convertNumber(data.unit_price)
10722
+ items: [
10723
+ {
10724
+ title: data.title,
10725
+ quantity: data.quantity,
10726
+ unit_price: convertNumber(data.unit_price)
10727
+ }
10728
+ ]
11078
10729
  },
11079
10730
  {
11080
10731
  onSuccess: () => {
11081
- setEditing(false);
10732
+ setIsOpen(STACKED_MODAL_ID, false);
11082
10733
  },
11083
10734
  onError: (e) => {
11084
10735
  toast.error(e.message);
@@ -11086,365 +10737,714 @@ const CustomItem = ({ item, preview, currencyCode }) => {
11086
10737
  }
11087
10738
  );
11088
10739
  });
11089
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
11090
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10740
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10741
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10742
+ /* @__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: [
10743
+ /* @__PURE__ */ jsxs("div", { children: [
10744
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10745
+ /* @__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." }) })
10746
+ ] }),
10747
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11091
10748
  /* @__PURE__ */ jsx(
11092
- Thumbnail,
10749
+ Form$2.Field,
11093
10750
  {
11094
- thumbnail: item.thumbnail,
11095
- alt: item.title ?? void 0
10751
+ control: form.control,
10752
+ name: "title",
10753
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10754
+ /* @__PURE__ */ jsxs("div", { children: [
10755
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10756
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10757
+ ] }),
10758
+ /* @__PURE__ */ jsxs("div", { children: [
10759
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10760
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10761
+ ] })
10762
+ ] }) })
11096
10763
  }
11097
10764
  ),
11098
- editing ? /* @__PURE__ */ jsx(
10765
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10766
+ /* @__PURE__ */ jsx(
11099
10767
  Form$2.Field,
11100
10768
  {
11101
10769
  control: form.control,
11102
- name: "title",
11103
- render: ({ field }) => {
11104
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
11105
- }
10770
+ name: "unit_price",
10771
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10772
+ /* @__PURE__ */ jsxs("div", { children: [
10773
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10774
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10775
+ ] }),
10776
+ /* @__PURE__ */ jsxs("div", { children: [
10777
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10778
+ CurrencyInput,
10779
+ {
10780
+ symbol: getNativeSymbol(currencyCode),
10781
+ code: currencyCode,
10782
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10783
+ ...field
10784
+ }
10785
+ ) }),
10786
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10787
+ ] })
10788
+ ] }) })
11106
10789
  }
11107
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10790
+ ),
10791
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10792
+ /* @__PURE__ */ jsx(
10793
+ Form$2.Field,
10794
+ {
10795
+ control: form.control,
10796
+ name: "quantity",
10797
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10798
+ /* @__PURE__ */ jsxs("div", { children: [
10799
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10800
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10801
+ ] }),
10802
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
10803
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10804
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10805
+ ] })
10806
+ ] }) })
10807
+ }
10808
+ )
10809
+ ] }) }) }),
10810
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10811
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10812
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10813
+ ] }) })
10814
+ ] }) }) });
10815
+ };
10816
+ const customItemSchema = objectType({
10817
+ title: stringType().min(1),
10818
+ quantity: numberType(),
10819
+ unit_price: unionType([numberType(), stringType()])
10820
+ });
10821
+ const InlineTip = forwardRef(
10822
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
10823
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10824
+ return /* @__PURE__ */ jsxs(
10825
+ "div",
10826
+ {
10827
+ ref,
10828
+ className: clx(
10829
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10830
+ className
10831
+ ),
10832
+ ...props,
10833
+ children: [
10834
+ /* @__PURE__ */ jsx(
10835
+ "div",
10836
+ {
10837
+ role: "presentation",
10838
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10839
+ "bg-ui-tag-orange-icon": variant === "warning"
10840
+ })
10841
+ }
10842
+ ),
10843
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10844
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10845
+ labelValue,
10846
+ ":"
10847
+ ] }),
10848
+ " ",
10849
+ children
10850
+ ] })
10851
+ ]
10852
+ }
10853
+ );
10854
+ }
10855
+ );
10856
+ InlineTip.displayName = "InlineTip";
10857
+ const MetadataFieldSchema = objectType({
10858
+ key: stringType(),
10859
+ disabled: booleanType().optional(),
10860
+ value: anyType()
10861
+ });
10862
+ const MetadataSchema = objectType({
10863
+ metadata: arrayType(MetadataFieldSchema)
10864
+ });
10865
+ const Metadata = () => {
10866
+ const { id } = useParams();
10867
+ const { order, isPending, isError, error } = useOrder(id, {
10868
+ fields: "metadata"
10869
+ });
10870
+ if (isError) {
10871
+ throw error;
10872
+ }
10873
+ const isReady = !isPending && !!order;
10874
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10875
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10876
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10877
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
11108
10878
  ] }),
11109
- editing ? /* @__PURE__ */ jsx(
11110
- Form$2.Field,
11111
- {
11112
- control: form.control,
11113
- name: "quantity",
11114
- render: ({ field }) => {
11115
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
11116
- }
11117
- }
11118
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
11119
- editing ? /* @__PURE__ */ jsx(
11120
- Form$2.Field,
10879
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10880
+ ] });
10881
+ };
10882
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10883
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10884
+ const MetadataForm = ({ orderId, metadata }) => {
10885
+ const { handleSuccess } = useRouteModal();
10886
+ const hasUneditableRows = getHasUneditableRows(metadata);
10887
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10888
+ const form = useForm({
10889
+ defaultValues: {
10890
+ metadata: getDefaultValues(metadata)
10891
+ },
10892
+ resolver: zodResolver(MetadataSchema)
10893
+ });
10894
+ const handleSubmit = form.handleSubmit(async (data) => {
10895
+ const parsedData = parseValues(data);
10896
+ await mutateAsync(
11121
10897
  {
11122
- control: form.control,
11123
- name: "unit_price",
11124
- render: ({ field: { onChange, ...field } }) => {
11125
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11126
- CurrencyInput,
11127
- {
11128
- ...field,
11129
- symbol: getNativeSymbol(currencyCode),
11130
- code: currencyCode,
11131
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
11132
- }
11133
- ) }) });
11134
- }
11135
- }
11136
- ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
11137
- /* @__PURE__ */ jsx(
11138
- IconButton,
10898
+ metadata: parsedData
10899
+ },
11139
10900
  {
11140
- type: "button",
11141
- size: "small",
11142
- onClick: editing ? onSubmit : () => {
11143
- setEditing(true);
10901
+ onSuccess: () => {
10902
+ toast.success("Metadata updated");
10903
+ handleSuccess();
11144
10904
  },
11145
- disabled: isPending,
11146
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
11147
- }
11148
- )
11149
- ] }) }) });
11150
- };
11151
- const StackedModalTrigger$1 = ({
11152
- type,
11153
- setModalContent
11154
- }) => {
11155
- const { setIsOpen } = useStackedModal();
11156
- const onClick = useCallback(() => {
11157
- setModalContent(type);
11158
- setIsOpen(STACKED_MODAL_ID, true);
11159
- }, [setModalContent, setIsOpen, type]);
11160
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
11161
- };
11162
- const VARIANT_PREFIX = "items";
11163
- const LIMIT = 50;
11164
- const ExistingItemsForm = ({ orderId, items }) => {
11165
- const { setIsOpen } = useStackedModal();
11166
- const [rowSelection, setRowSelection] = useState(
11167
- items.reduce((acc, item) => {
11168
- acc[item.variant_id] = true;
11169
- return acc;
11170
- }, {})
11171
- );
11172
- useEffect(() => {
11173
- setRowSelection(
11174
- items.reduce((acc, item) => {
11175
- if (item.variant_id) {
11176
- acc[item.variant_id] = true;
10905
+ onError: (error) => {
10906
+ toast.error(error.message);
11177
10907
  }
11178
- return acc;
11179
- }, {})
10908
+ }
11180
10909
  );
11181
- }, [items]);
11182
- const { q, order, offset } = useQueryParams(
11183
- ["q", "order", "offset"],
11184
- VARIANT_PREFIX
11185
- );
11186
- const { variants, count, isPending, isError, error } = useProductVariants(
10910
+ });
10911
+ const { fields, insert, remove } = useFieldArray({
10912
+ control: form.control,
10913
+ name: "metadata"
10914
+ });
10915
+ function deleteRow(index) {
10916
+ remove(index);
10917
+ if (fields.length === 1) {
10918
+ insert(0, {
10919
+ key: "",
10920
+ value: "",
10921
+ disabled: false
10922
+ });
10923
+ }
10924
+ }
10925
+ function insertRow(index, position) {
10926
+ insert(index + (position === "above" ? 0 : 1), {
10927
+ key: "",
10928
+ value: "",
10929
+ disabled: false
10930
+ });
10931
+ }
10932
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10933
+ KeyboundForm,
11187
10934
  {
11188
- q,
11189
- order,
11190
- offset: offset ? parseInt(offset) : void 0,
11191
- limit: LIMIT
11192
- },
10935
+ onSubmit: handleSubmit,
10936
+ className: "flex flex-1 flex-col overflow-hidden",
10937
+ children: [
10938
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10939
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10940
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10941
+ /* @__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" }) }),
10942
+ /* @__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" }) })
10943
+ ] }),
10944
+ fields.map((field, index) => {
10945
+ const isDisabled = field.disabled || false;
10946
+ let placeholder = "-";
10947
+ if (typeof field.value === "object") {
10948
+ placeholder = "{ ... }";
10949
+ }
10950
+ if (Array.isArray(field.value)) {
10951
+ placeholder = "[ ... ]";
10952
+ }
10953
+ return /* @__PURE__ */ jsx(
10954
+ ConditionalTooltip,
10955
+ {
10956
+ showTooltip: isDisabled,
10957
+ content: "This row is disabled because it contains non-primitive data.",
10958
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10959
+ /* @__PURE__ */ jsxs(
10960
+ "div",
10961
+ {
10962
+ className: clx("grid grid-cols-2 divide-x", {
10963
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
10964
+ }),
10965
+ children: [
10966
+ /* @__PURE__ */ jsx(
10967
+ Form$2.Field,
10968
+ {
10969
+ control: form.control,
10970
+ name: `metadata.${index}.key`,
10971
+ render: ({ field: field2 }) => {
10972
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10973
+ GridInput,
10974
+ {
10975
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
10976
+ ...field2,
10977
+ disabled: isDisabled,
10978
+ placeholder: "Key"
10979
+ }
10980
+ ) }) });
10981
+ }
10982
+ }
10983
+ ),
10984
+ /* @__PURE__ */ jsx(
10985
+ Form$2.Field,
10986
+ {
10987
+ control: form.control,
10988
+ name: `metadata.${index}.value`,
10989
+ render: ({ field: { value, ...field2 } }) => {
10990
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10991
+ GridInput,
10992
+ {
10993
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
10994
+ ...field2,
10995
+ value: isDisabled ? placeholder : value,
10996
+ disabled: isDisabled,
10997
+ placeholder: "Value"
10998
+ }
10999
+ ) }) });
11000
+ }
11001
+ }
11002
+ )
11003
+ ]
11004
+ }
11005
+ ),
11006
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
11007
+ /* @__PURE__ */ jsx(
11008
+ DropdownMenu.Trigger,
11009
+ {
11010
+ className: clx(
11011
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
11012
+ {
11013
+ hidden: isDisabled
11014
+ }
11015
+ ),
11016
+ disabled: isDisabled,
11017
+ asChild: true,
11018
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
11019
+ }
11020
+ ),
11021
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
11022
+ /* @__PURE__ */ jsxs(
11023
+ DropdownMenu.Item,
11024
+ {
11025
+ className: "gap-x-2",
11026
+ onClick: () => insertRow(index, "above"),
11027
+ children: [
11028
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
11029
+ "Insert row above"
11030
+ ]
11031
+ }
11032
+ ),
11033
+ /* @__PURE__ */ jsxs(
11034
+ DropdownMenu.Item,
11035
+ {
11036
+ className: "gap-x-2",
11037
+ onClick: () => insertRow(index, "below"),
11038
+ children: [
11039
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
11040
+ "Insert row below"
11041
+ ]
11042
+ }
11043
+ ),
11044
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
11045
+ /* @__PURE__ */ jsxs(
11046
+ DropdownMenu.Item,
11047
+ {
11048
+ className: "gap-x-2",
11049
+ onClick: () => deleteRow(index),
11050
+ children: [
11051
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
11052
+ "Delete row"
11053
+ ]
11054
+ }
11055
+ )
11056
+ ] })
11057
+ ] })
11058
+ ] })
11059
+ },
11060
+ field.id
11061
+ );
11062
+ })
11063
+ ] }),
11064
+ 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." })
11065
+ ] }),
11066
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11067
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11068
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11069
+ ] }) })
11070
+ ]
11071
+ }
11072
+ ) });
11073
+ };
11074
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
11075
+ return /* @__PURE__ */ jsx(
11076
+ "input",
11193
11077
  {
11194
- placeholderData: keepPreviousData
11078
+ ref,
11079
+ ...props,
11080
+ autoComplete: "off",
11081
+ className: clx(
11082
+ "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",
11083
+ className
11084
+ )
11195
11085
  }
11196
11086
  );
11197
- const columns = useColumns();
11198
- const { mutateAsync } = useDraftOrderAddItems(orderId);
11199
- const onSubmit = async () => {
11200
- const ids = Object.keys(rowSelection).filter(
11201
- (id) => !items.find((i) => i.variant_id === id)
11202
- );
11203
- await mutateAsync(
11204
- {
11205
- items: ids.map((id) => ({
11206
- variant_id: id,
11207
- quantity: 1
11208
- }))
11209
- },
11087
+ });
11088
+ GridInput.displayName = "MetadataForm.GridInput";
11089
+ const PlaceholderInner = () => {
11090
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11091
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11092
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11093
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11094
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11095
+ ] }) })
11096
+ ] });
11097
+ };
11098
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
11099
+ function getDefaultValues(metadata) {
11100
+ if (!metadata || !Object.keys(metadata).length) {
11101
+ return [
11210
11102
  {
11211
- onSuccess: () => {
11212
- setRowSelection({});
11213
- setIsOpen(STACKED_MODAL_ID, false);
11214
- },
11215
- onError: (e) => {
11216
- toast.error(e.message);
11217
- }
11103
+ key: "",
11104
+ value: "",
11105
+ disabled: false
11218
11106
  }
11219
- );
11220
- };
11221
- if (isError) {
11222
- throw error;
11107
+ ];
11223
11108
  }
11224
- return /* @__PURE__ */ jsxs(
11225
- StackedFocusModal.Content,
11226
- {
11227
- onOpenAutoFocus: (e) => {
11228
- e.preventDefault();
11229
- const searchInput = document.querySelector(
11230
- "[data-modal-id='modal-search-input']"
11231
- );
11232
- if (searchInput) {
11233
- searchInput.focus();
11234
- }
11235
- },
11236
- children: [
11237
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
11238
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
11239
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
11240
- ] }),
11241
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
11242
- DataTable,
11243
- {
11244
- data: variants,
11245
- columns,
11246
- isLoading: isPending,
11247
- getRowId: (row) => row.id,
11248
- rowCount: count,
11249
- prefix: VARIANT_PREFIX,
11250
- layout: "fill",
11251
- rowSelection: {
11252
- state: rowSelection,
11253
- onRowSelectionChange: setRowSelection,
11254
- enableRowSelection: (row) => {
11255
- return !items.find((i) => i.variant_id === row.original.id);
11256
- }
11257
- },
11258
- autoFocusSearch: true
11259
- }
11260
- ) }),
11261
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11262
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11263
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
11264
- ] }) })
11265
- ]
11109
+ return Object.entries(metadata).map(([key, value]) => {
11110
+ if (!EDITABLE_TYPES.includes(typeof value)) {
11111
+ return {
11112
+ key,
11113
+ value,
11114
+ disabled: true
11115
+ };
11116
+ }
11117
+ let stringValue = value;
11118
+ if (typeof value !== "string") {
11119
+ stringValue = JSON.stringify(value);
11120
+ }
11121
+ return {
11122
+ key,
11123
+ value: stringValue,
11124
+ original_key: key
11125
+ };
11126
+ });
11127
+ }
11128
+ function parseValues(values) {
11129
+ const metadata = values.metadata;
11130
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11131
+ if (isEmpty) {
11132
+ return null;
11133
+ }
11134
+ const update = {};
11135
+ metadata.forEach((field) => {
11136
+ let key = field.key;
11137
+ let value = field.value;
11138
+ const disabled = field.disabled;
11139
+ if (!key || !value) {
11140
+ return;
11141
+ }
11142
+ if (disabled) {
11143
+ update[key] = value;
11144
+ return;
11145
+ }
11146
+ key = key.trim();
11147
+ value = value.trim();
11148
+ if (value === "true") {
11149
+ update[key] = true;
11150
+ } else if (value === "false") {
11151
+ update[key] = false;
11152
+ } else {
11153
+ const parsedNumber = parseFloat(value);
11154
+ if (!isNaN(parsedNumber)) {
11155
+ update[key] = parsedNumber;
11156
+ } else {
11157
+ update[key] = value;
11158
+ }
11266
11159
  }
11160
+ });
11161
+ return update;
11162
+ }
11163
+ function getHasUneditableRows(metadata) {
11164
+ if (!metadata) {
11165
+ return false;
11166
+ }
11167
+ return Object.values(metadata).some(
11168
+ (value) => !EDITABLE_TYPES.includes(typeof value)
11267
11169
  );
11170
+ }
11171
+ const PROMOTION_QUERY_KEY = "promotions";
11172
+ const promotionsQueryKeys = {
11173
+ list: (query2) => [
11174
+ PROMOTION_QUERY_KEY,
11175
+ query2 ? query2 : void 0
11176
+ ],
11177
+ detail: (id, query2) => [
11178
+ PROMOTION_QUERY_KEY,
11179
+ id,
11180
+ query2 ? query2 : void 0
11181
+ ]
11268
11182
  };
11269
- const columnHelper = createDataTableColumnHelper();
11270
- const useColumns = () => {
11271
- return useMemo(() => {
11272
- return [
11273
- columnHelper.select(),
11274
- columnHelper.accessor("product.title", {
11275
- header: "Product",
11276
- cell: ({ row }) => {
11277
- var _a, _b, _c;
11278
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
11279
- /* @__PURE__ */ jsx(
11280
- Thumbnail,
11281
- {
11282
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
11283
- alt: (_b = row.original.product) == null ? void 0 : _b.title
11284
- }
11285
- ),
11286
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
11287
- ] });
11288
- },
11289
- enableSorting: true
11290
- }),
11291
- columnHelper.accessor("title", {
11292
- header: "Variant",
11293
- enableSorting: true
11294
- }),
11295
- columnHelper.accessor("sku", {
11296
- header: "SKU",
11297
- cell: ({ getValue }) => {
11298
- return getValue() ?? "-";
11299
- },
11300
- enableSorting: true
11301
- }),
11302
- columnHelper.accessor("updated_at", {
11303
- header: "Updated",
11304
- cell: ({ getValue }) => {
11305
- return /* @__PURE__ */ jsx(
11306
- Tooltip,
11307
- {
11308
- content: getFullDate({ date: getValue(), includeTime: true }),
11309
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
11310
- }
11311
- );
11312
- },
11313
- enableSorting: true,
11314
- sortAscLabel: "Oldest first",
11315
- sortDescLabel: "Newest first"
11316
- }),
11317
- columnHelper.accessor("created_at", {
11318
- header: "Created",
11319
- cell: ({ getValue }) => {
11320
- return /* @__PURE__ */ jsx(
11321
- Tooltip,
11322
- {
11323
- content: getFullDate({ date: getValue(), includeTime: true }),
11324
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
11325
- }
11326
- );
11327
- },
11328
- enableSorting: true,
11329
- sortAscLabel: "Oldest first",
11330
- sortDescLabel: "Newest first"
11331
- })
11332
- ];
11333
- }, []);
11183
+ const usePromotions = (query2, options) => {
11184
+ const { data, ...rest } = useQuery({
11185
+ queryKey: promotionsQueryKeys.list(query2),
11186
+ queryFn: async () => sdk.admin.promotion.list(query2),
11187
+ ...options
11188
+ });
11189
+ return { ...data, ...rest };
11190
+ };
11191
+ const Promotions = () => {
11192
+ const { id } = useParams();
11193
+ const {
11194
+ order: preview,
11195
+ isError: isPreviewError,
11196
+ error: previewError
11197
+ } = useOrderPreview(id, void 0);
11198
+ useInitiateOrderEdit({ preview });
11199
+ const { onCancel } = useCancelOrderEdit({ preview });
11200
+ if (isPreviewError) {
11201
+ throw previewError;
11202
+ }
11203
+ const isReady = !!preview;
11204
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
11205
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
11206
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
11207
+ ] });
11334
11208
  };
11335
- const CustomItemForm = ({ orderId, currencyCode }) => {
11336
- const { setIsOpen } = useStackedModal();
11337
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
11338
- const form = useForm({
11339
- defaultValues: {
11340
- title: "",
11341
- quantity: 1,
11342
- unit_price: ""
11209
+ const PromotionForm = ({ preview }) => {
11210
+ const { items, shipping_methods } = preview;
11211
+ const [isSubmitting, setIsSubmitting] = useState(false);
11212
+ const [comboboxValue, setComboboxValue] = useState("");
11213
+ const { handleSuccess } = useRouteModal();
11214
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11215
+ const promoIds = getPromotionIds(items, shipping_methods);
11216
+ const { promotions, isPending, isError, error } = usePromotions(
11217
+ {
11218
+ id: promoIds
11343
11219
  },
11344
- resolver: zodResolver(customItemSchema)
11220
+ {
11221
+ enabled: !!promoIds.length
11222
+ }
11223
+ );
11224
+ const comboboxData = useComboboxData({
11225
+ queryKey: ["promotions", "combobox", promoIds],
11226
+ queryFn: async (params) => {
11227
+ return await sdk.admin.promotion.list({
11228
+ ...params,
11229
+ id: {
11230
+ $nin: promoIds
11231
+ }
11232
+ });
11233
+ },
11234
+ getOptions: (data) => {
11235
+ return data.promotions.map((promotion) => ({
11236
+ label: promotion.code,
11237
+ value: promotion.code
11238
+ }));
11239
+ }
11345
11240
  });
11346
- const onSubmit = form.handleSubmit(async (data) => {
11347
- await addItems(
11241
+ const add = async (value) => {
11242
+ if (!value) {
11243
+ return;
11244
+ }
11245
+ addPromotions(
11348
11246
  {
11349
- items: [
11350
- {
11351
- title: data.title,
11352
- quantity: data.quantity,
11353
- unit_price: convertNumber(data.unit_price)
11354
- }
11355
- ]
11247
+ promo_codes: [value]
11356
11248
  },
11357
11249
  {
11358
- onSuccess: () => {
11359
- setIsOpen(STACKED_MODAL_ID, false);
11360
- },
11361
11250
  onError: (e) => {
11362
11251
  toast.error(e.message);
11252
+ comboboxData.onSearchValueChange("");
11253
+ setComboboxValue("");
11254
+ },
11255
+ onSuccess: () => {
11256
+ comboboxData.onSearchValueChange("");
11257
+ setComboboxValue("");
11363
11258
  }
11364
11259
  }
11365
11260
  );
11366
- });
11367
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
11368
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
11369
- /* @__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: [
11370
- /* @__PURE__ */ jsxs("div", { children: [
11371
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
11372
- /* @__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." }) })
11261
+ };
11262
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11263
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
11264
+ const onSubmit = async () => {
11265
+ setIsSubmitting(true);
11266
+ let requestSucceeded = false;
11267
+ await requestOrderEdit(void 0, {
11268
+ onError: (e) => {
11269
+ toast.error(e.message);
11270
+ },
11271
+ onSuccess: () => {
11272
+ requestSucceeded = true;
11273
+ }
11274
+ });
11275
+ if (!requestSucceeded) {
11276
+ setIsSubmitting(false);
11277
+ return;
11278
+ }
11279
+ await confirmOrderEdit(void 0, {
11280
+ onError: (e) => {
11281
+ toast.error(e.message);
11282
+ },
11283
+ onSuccess: () => {
11284
+ handleSuccess();
11285
+ },
11286
+ onSettled: () => {
11287
+ setIsSubmitting(false);
11288
+ }
11289
+ });
11290
+ };
11291
+ if (isError) {
11292
+ throw error;
11293
+ }
11294
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11295
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
11296
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
11297
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11298
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
11299
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11300
+ ] }),
11301
+ /* @__PURE__ */ jsx(
11302
+ Combobox,
11303
+ {
11304
+ id: "promotion-combobox",
11305
+ "aria-describedby": "promotion-combobox-hint",
11306
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
11307
+ fetchNextPage: comboboxData.fetchNextPage,
11308
+ options: comboboxData.options,
11309
+ onSearchValueChange: comboboxData.onSearchValueChange,
11310
+ searchValue: comboboxData.searchValue,
11311
+ disabled: comboboxData.disabled || isAddingPromotions,
11312
+ onChange: add,
11313
+ value: comboboxValue
11314
+ }
11315
+ )
11373
11316
  ] }),
11374
11317
  /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11318
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
11319
+ PromotionItem,
11320
+ {
11321
+ promotion,
11322
+ orderId: preview.id,
11323
+ isLoading: isPending
11324
+ },
11325
+ promotion.id
11326
+ )) })
11327
+ ] }) }),
11328
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11329
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11375
11330
  /* @__PURE__ */ jsx(
11376
- Form$2.Field,
11331
+ Button,
11377
11332
  {
11378
- control: form.control,
11379
- name: "title",
11380
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11381
- /* @__PURE__ */ jsxs("div", { children: [
11382
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
11383
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
11384
- ] }),
11385
- /* @__PURE__ */ jsxs("div", { children: [
11386
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11387
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11388
- ] })
11389
- ] }) })
11333
+ size: "small",
11334
+ type: "submit",
11335
+ isLoading: isSubmitting || isAddingPromotions,
11336
+ children: "Save"
11390
11337
  }
11391
- ),
11392
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11393
- /* @__PURE__ */ jsx(
11394
- Form$2.Field,
11338
+ )
11339
+ ] }) })
11340
+ ] });
11341
+ };
11342
+ const PromotionItem = ({
11343
+ promotion,
11344
+ orderId,
11345
+ isLoading
11346
+ }) => {
11347
+ var _a;
11348
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
11349
+ const onRemove = async () => {
11350
+ removePromotions(
11351
+ {
11352
+ promo_codes: [promotion.code]
11353
+ },
11354
+ {
11355
+ onError: (e) => {
11356
+ toast.error(e.message);
11357
+ }
11358
+ }
11359
+ );
11360
+ };
11361
+ const displayValue = getDisplayValue(promotion);
11362
+ return /* @__PURE__ */ jsxs(
11363
+ "div",
11364
+ {
11365
+ className: clx(
11366
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11395
11367
  {
11396
- control: form.control,
11397
- name: "unit_price",
11398
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11399
- /* @__PURE__ */ jsxs("div", { children: [
11400
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
11401
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
11402
- ] }),
11403
- /* @__PURE__ */ jsxs("div", { children: [
11404
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11405
- CurrencyInput,
11406
- {
11407
- symbol: getNativeSymbol(currencyCode),
11408
- code: currencyCode,
11409
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
11410
- ...field
11411
- }
11412
- ) }),
11413
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11414
- ] })
11415
- ] }) })
11368
+ "animate-pulse": isLoading
11416
11369
  }
11417
11370
  ),
11418
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11419
- /* @__PURE__ */ jsx(
11420
- Form$2.Field,
11421
- {
11422
- control: form.control,
11423
- name: "quantity",
11424
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11425
- /* @__PURE__ */ jsxs("div", { children: [
11426
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
11427
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
11371
+ children: [
11372
+ /* @__PURE__ */ jsxs("div", { children: [
11373
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11374
+ /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11375
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11376
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11377
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11428
11378
  ] }),
11429
- /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
11430
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
11431
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11432
- ] })
11433
- ] }) })
11434
- }
11435
- )
11436
- ] }) }) }),
11437
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11438
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11439
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
11440
- ] }) })
11441
- ] }) }) });
11379
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11380
+ ] })
11381
+ ] }),
11382
+ /* @__PURE__ */ jsx(
11383
+ IconButton,
11384
+ {
11385
+ size: "small",
11386
+ type: "button",
11387
+ variant: "transparent",
11388
+ onClick: onRemove,
11389
+ isLoading: isPending || isLoading,
11390
+ children: /* @__PURE__ */ jsx(XMark, {})
11391
+ }
11392
+ )
11393
+ ]
11394
+ },
11395
+ promotion.id
11396
+ );
11442
11397
  };
11443
- const customItemSchema = objectType({
11444
- title: stringType().min(1),
11445
- quantity: numberType(),
11446
- unit_price: unionType([numberType(), stringType()])
11398
+ function getDisplayValue(promotion) {
11399
+ var _a, _b, _c, _d;
11400
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11401
+ if (!value) {
11402
+ return null;
11403
+ }
11404
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11405
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11406
+ if (!currency) {
11407
+ return null;
11408
+ }
11409
+ return getLocaleAmount(value, currency);
11410
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11411
+ return formatPercentage(value);
11412
+ }
11413
+ return null;
11414
+ }
11415
+ const formatter = new Intl.NumberFormat([], {
11416
+ style: "percent",
11417
+ minimumFractionDigits: 2
11447
11418
  });
11419
+ const formatPercentage = (value, isPercentageValue = false) => {
11420
+ let val = value || 0;
11421
+ if (!isPercentageValue) {
11422
+ val = val / 100;
11423
+ }
11424
+ return formatter.format(val);
11425
+ };
11426
+ function getPromotionIds(items, shippingMethods) {
11427
+ const promotionIds = /* @__PURE__ */ new Set();
11428
+ for (const item of items) {
11429
+ if (item.adjustments) {
11430
+ for (const adjustment of item.adjustments) {
11431
+ if (adjustment.promotion_id) {
11432
+ promotionIds.add(adjustment.promotion_id);
11433
+ }
11434
+ }
11435
+ }
11436
+ }
11437
+ for (const shippingMethod of shippingMethods) {
11438
+ if (shippingMethod.adjustments) {
11439
+ for (const adjustment of shippingMethod.adjustments) {
11440
+ if (adjustment.promotion_id) {
11441
+ promotionIds.add(adjustment.promotion_id);
11442
+ }
11443
+ }
11444
+ }
11445
+ }
11446
+ return Array.from(promotionIds);
11447
+ }
11448
11448
  const SalesChannel = () => {
11449
11449
  const { id } = useParams();
11450
11450
  const { draft_order, isPending, isError, error } = useDraftOrder(
@@ -11541,16 +11541,219 @@ const SalesChannelField = ({ control, order }) => {
11541
11541
  placeholder: "Select sales channel",
11542
11542
  ...field
11543
11543
  }
11544
- ) }),
11545
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11546
- ] });
11547
- }
11544
+ ) }),
11545
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11546
+ ] });
11547
+ }
11548
+ }
11549
+ );
11550
+ };
11551
+ const schema$2 = objectType({
11552
+ sales_channel_id: stringType().min(1)
11553
+ });
11554
+ const ShippingAddress = () => {
11555
+ const { id } = useParams();
11556
+ const { order, isPending, isError, error } = useOrder(id, {
11557
+ fields: "+shipping_address"
11558
+ });
11559
+ if (isError) {
11560
+ throw error;
11561
+ }
11562
+ const isReady = !isPending && !!order;
11563
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11564
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11565
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Shipping Address" }) }),
11566
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the shipping address for the draft order" }) })
11567
+ ] }),
11568
+ isReady && /* @__PURE__ */ jsx(ShippingAddressForm, { order })
11569
+ ] });
11570
+ };
11571
+ const ShippingAddressForm = ({ order }) => {
11572
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
11573
+ const form = useForm({
11574
+ defaultValues: {
11575
+ first_name: ((_a = order.shipping_address) == null ? void 0 : _a.first_name) ?? "",
11576
+ last_name: ((_b = order.shipping_address) == null ? void 0 : _b.last_name) ?? "",
11577
+ company: ((_c = order.shipping_address) == null ? void 0 : _c.company) ?? "",
11578
+ address_1: ((_d = order.shipping_address) == null ? void 0 : _d.address_1) ?? "",
11579
+ address_2: ((_e = order.shipping_address) == null ? void 0 : _e.address_2) ?? "",
11580
+ city: ((_f = order.shipping_address) == null ? void 0 : _f.city) ?? "",
11581
+ province: ((_g = order.shipping_address) == null ? void 0 : _g.province) ?? "",
11582
+ country_code: ((_h = order.shipping_address) == null ? void 0 : _h.country_code) ?? "",
11583
+ postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
11584
+ phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
11585
+ },
11586
+ resolver: zodResolver(schema$1)
11587
+ });
11588
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11589
+ const { handleSuccess } = useRouteModal();
11590
+ const onSubmit = form.handleSubmit(async (data) => {
11591
+ await mutateAsync(
11592
+ {
11593
+ shipping_address: {
11594
+ first_name: data.first_name,
11595
+ last_name: data.last_name,
11596
+ company: data.company,
11597
+ address_1: data.address_1,
11598
+ address_2: data.address_2,
11599
+ city: data.city,
11600
+ province: data.province,
11601
+ country_code: data.country_code,
11602
+ postal_code: data.postal_code,
11603
+ phone: data.phone
11604
+ }
11605
+ },
11606
+ {
11607
+ onSuccess: () => {
11608
+ handleSuccess();
11609
+ },
11610
+ onError: (error) => {
11611
+ toast.error(error.message);
11612
+ }
11613
+ }
11614
+ );
11615
+ });
11616
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11617
+ KeyboundForm,
11618
+ {
11619
+ className: "flex flex-1 flex-col overflow-hidden",
11620
+ onSubmit,
11621
+ children: [
11622
+ /* @__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: [
11623
+ /* @__PURE__ */ jsx(
11624
+ Form$2.Field,
11625
+ {
11626
+ control: form.control,
11627
+ name: "country_code",
11628
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11629
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
11630
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
11631
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11632
+ ] })
11633
+ }
11634
+ ),
11635
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
11636
+ /* @__PURE__ */ jsx(
11637
+ Form$2.Field,
11638
+ {
11639
+ control: form.control,
11640
+ name: "first_name",
11641
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11642
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
11643
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11644
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11645
+ ] })
11646
+ }
11647
+ ),
11648
+ /* @__PURE__ */ jsx(
11649
+ Form$2.Field,
11650
+ {
11651
+ control: form.control,
11652
+ name: "last_name",
11653
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11654
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
11655
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11656
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11657
+ ] })
11658
+ }
11659
+ )
11660
+ ] }),
11661
+ /* @__PURE__ */ jsx(
11662
+ Form$2.Field,
11663
+ {
11664
+ control: form.control,
11665
+ name: "company",
11666
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11667
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
11668
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11669
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11670
+ ] })
11671
+ }
11672
+ ),
11673
+ /* @__PURE__ */ jsx(
11674
+ Form$2.Field,
11675
+ {
11676
+ control: form.control,
11677
+ name: "address_1",
11678
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11679
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
11680
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11681
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11682
+ ] })
11683
+ }
11684
+ ),
11685
+ /* @__PURE__ */ jsx(
11686
+ Form$2.Field,
11687
+ {
11688
+ control: form.control,
11689
+ name: "address_2",
11690
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11691
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
11692
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11693
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11694
+ ] })
11695
+ }
11696
+ ),
11697
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
11698
+ /* @__PURE__ */ jsx(
11699
+ Form$2.Field,
11700
+ {
11701
+ control: form.control,
11702
+ name: "postal_code",
11703
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11704
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
11705
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11706
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11707
+ ] })
11708
+ }
11709
+ ),
11710
+ /* @__PURE__ */ jsx(
11711
+ Form$2.Field,
11712
+ {
11713
+ control: form.control,
11714
+ name: "city",
11715
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11716
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
11717
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11718
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11719
+ ] })
11720
+ }
11721
+ )
11722
+ ] }),
11723
+ /* @__PURE__ */ jsx(
11724
+ Form$2.Field,
11725
+ {
11726
+ control: form.control,
11727
+ name: "province",
11728
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11729
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
11730
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11731
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11732
+ ] })
11733
+ }
11734
+ ),
11735
+ /* @__PURE__ */ jsx(
11736
+ Form$2.Field,
11737
+ {
11738
+ control: form.control,
11739
+ name: "phone",
11740
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11741
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
11742
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11743
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11744
+ ] })
11745
+ }
11746
+ )
11747
+ ] }) }),
11748
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11749
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11750
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11751
+ ] }) })
11752
+ ]
11548
11753
  }
11549
- );
11754
+ ) });
11550
11755
  };
11551
- const schema$2 = objectType({
11552
- sales_channel_id: stringType().min(1)
11553
- });
11756
+ const schema$1 = addressSchema;
11554
11757
  const STACKED_FOCUS_MODAL_ID = "shipping-form";
11555
11758
  const Shipping = () => {
11556
11759
  var _a;
@@ -12358,209 +12561,6 @@ const CustomAmountField = ({
12358
12561
  }
12359
12562
  );
12360
12563
  };
12361
- const ShippingAddress = () => {
12362
- const { id } = useParams();
12363
- const { order, isPending, isError, error } = useOrder(id, {
12364
- fields: "+shipping_address"
12365
- });
12366
- if (isError) {
12367
- throw error;
12368
- }
12369
- const isReady = !isPending && !!order;
12370
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12371
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12372
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Shipping Address" }) }),
12373
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the shipping address for the draft order" }) })
12374
- ] }),
12375
- isReady && /* @__PURE__ */ jsx(ShippingAddressForm, { order })
12376
- ] });
12377
- };
12378
- const ShippingAddressForm = ({ order }) => {
12379
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
12380
- const form = useForm({
12381
- defaultValues: {
12382
- first_name: ((_a = order.shipping_address) == null ? void 0 : _a.first_name) ?? "",
12383
- last_name: ((_b = order.shipping_address) == null ? void 0 : _b.last_name) ?? "",
12384
- company: ((_c = order.shipping_address) == null ? void 0 : _c.company) ?? "",
12385
- address_1: ((_d = order.shipping_address) == null ? void 0 : _d.address_1) ?? "",
12386
- address_2: ((_e = order.shipping_address) == null ? void 0 : _e.address_2) ?? "",
12387
- city: ((_f = order.shipping_address) == null ? void 0 : _f.city) ?? "",
12388
- province: ((_g = order.shipping_address) == null ? void 0 : _g.province) ?? "",
12389
- country_code: ((_h = order.shipping_address) == null ? void 0 : _h.country_code) ?? "",
12390
- postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12391
- phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12392
- },
12393
- resolver: zodResolver(schema$1)
12394
- });
12395
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12396
- const { handleSuccess } = useRouteModal();
12397
- const onSubmit = form.handleSubmit(async (data) => {
12398
- await mutateAsync(
12399
- {
12400
- shipping_address: {
12401
- first_name: data.first_name,
12402
- last_name: data.last_name,
12403
- company: data.company,
12404
- address_1: data.address_1,
12405
- address_2: data.address_2,
12406
- city: data.city,
12407
- province: data.province,
12408
- country_code: data.country_code,
12409
- postal_code: data.postal_code,
12410
- phone: data.phone
12411
- }
12412
- },
12413
- {
12414
- onSuccess: () => {
12415
- handleSuccess();
12416
- },
12417
- onError: (error) => {
12418
- toast.error(error.message);
12419
- }
12420
- }
12421
- );
12422
- });
12423
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12424
- KeyboundForm,
12425
- {
12426
- className: "flex flex-1 flex-col overflow-hidden",
12427
- onSubmit,
12428
- children: [
12429
- /* @__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: [
12430
- /* @__PURE__ */ jsx(
12431
- Form$2.Field,
12432
- {
12433
- control: form.control,
12434
- name: "country_code",
12435
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12436
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
12437
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
12438
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12439
- ] })
12440
- }
12441
- ),
12442
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12443
- /* @__PURE__ */ jsx(
12444
- Form$2.Field,
12445
- {
12446
- control: form.control,
12447
- name: "first_name",
12448
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12449
- /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
12450
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12451
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12452
- ] })
12453
- }
12454
- ),
12455
- /* @__PURE__ */ jsx(
12456
- Form$2.Field,
12457
- {
12458
- control: form.control,
12459
- name: "last_name",
12460
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12461
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
12462
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12463
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12464
- ] })
12465
- }
12466
- )
12467
- ] }),
12468
- /* @__PURE__ */ jsx(
12469
- Form$2.Field,
12470
- {
12471
- control: form.control,
12472
- name: "company",
12473
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12474
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
12475
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12476
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12477
- ] })
12478
- }
12479
- ),
12480
- /* @__PURE__ */ jsx(
12481
- Form$2.Field,
12482
- {
12483
- control: form.control,
12484
- name: "address_1",
12485
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12486
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
12487
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12488
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12489
- ] })
12490
- }
12491
- ),
12492
- /* @__PURE__ */ jsx(
12493
- Form$2.Field,
12494
- {
12495
- control: form.control,
12496
- name: "address_2",
12497
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12498
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
12499
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12500
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12501
- ] })
12502
- }
12503
- ),
12504
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12505
- /* @__PURE__ */ jsx(
12506
- Form$2.Field,
12507
- {
12508
- control: form.control,
12509
- name: "postal_code",
12510
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12511
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
12512
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12513
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12514
- ] })
12515
- }
12516
- ),
12517
- /* @__PURE__ */ jsx(
12518
- Form$2.Field,
12519
- {
12520
- control: form.control,
12521
- name: "city",
12522
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12523
- /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
12524
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12525
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12526
- ] })
12527
- }
12528
- )
12529
- ] }),
12530
- /* @__PURE__ */ jsx(
12531
- Form$2.Field,
12532
- {
12533
- control: form.control,
12534
- name: "province",
12535
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12536
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
12537
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12538
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12539
- ] })
12540
- }
12541
- ),
12542
- /* @__PURE__ */ jsx(
12543
- Form$2.Field,
12544
- {
12545
- control: form.control,
12546
- name: "phone",
12547
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12548
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
12549
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12550
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12551
- ] })
12552
- }
12553
- )
12554
- ] }) }),
12555
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
12556
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
12557
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
12558
- ] }) })
12559
- ]
12560
- }
12561
- ) });
12562
- };
12563
- const schema$1 = addressSchema;
12564
12564
  const TransferOwnership = () => {
12565
12565
  const { id } = useParams();
12566
12566
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -13061,38 +13061,38 @@ const routeModule = {
13061
13061
  Component: BillingAddress,
13062
13062
  path: "/draft-orders/:id/billing-address"
13063
13063
  },
13064
- {
13065
- Component: CustomItems,
13066
- path: "/draft-orders/:id/custom-items"
13067
- },
13068
13064
  {
13069
13065
  Component: Email,
13070
13066
  path: "/draft-orders/:id/email"
13071
13067
  },
13072
13068
  {
13073
- Component: Promotions,
13074
- path: "/draft-orders/:id/promotions"
13069
+ Component: CustomItems,
13070
+ path: "/draft-orders/:id/custom-items"
13071
+ },
13072
+ {
13073
+ Component: Items,
13074
+ path: "/draft-orders/:id/items"
13075
13075
  },
13076
13076
  {
13077
13077
  Component: Metadata,
13078
13078
  path: "/draft-orders/:id/metadata"
13079
13079
  },
13080
13080
  {
13081
- Component: Items,
13082
- path: "/draft-orders/:id/items"
13081
+ Component: Promotions,
13082
+ path: "/draft-orders/:id/promotions"
13083
13083
  },
13084
13084
  {
13085
13085
  Component: SalesChannel,
13086
13086
  path: "/draft-orders/:id/sales-channel"
13087
13087
  },
13088
- {
13089
- Component: Shipping,
13090
- path: "/draft-orders/:id/shipping"
13091
- },
13092
13088
  {
13093
13089
  Component: ShippingAddress,
13094
13090
  path: "/draft-orders/:id/shipping-address"
13095
13091
  },
13092
+ {
13093
+ Component: Shipping,
13094
+ path: "/draft-orders/:id/shipping"
13095
+ },
13096
13096
  {
13097
13097
  Component: TransferOwnership,
13098
13098
  path: "/draft-orders/:id/transfer-ownership"