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

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,1441 +10095,1356 @@ 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." })
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
+ )
10414
10328
  ] }),
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 [
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,
10451
10342
  {
10452
- key: "",
10453
- value: "",
10454
- disabled: false
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 }) }) });
10347
+ }
10455
10348
  }
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
- };
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,
10352
+ {
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,
10358
+ {
10359
+ ...field,
10360
+ symbol: getNativeSymbol(currencyCode),
10361
+ code: currencyCode,
10362
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10363
+ }
10364
+ ) }) });
10365
+ }
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
+ ] }) }) });
10381
+ };
10382
+ const variantItemSchema = objectType({
10383
+ quantity: numberType(),
10384
+ unit_price: unionType([numberType(), stringType()])
10385
+ });
10386
+ const CustomItem = ({ item, preview, currencyCode }) => {
10387
+ const [editing, setEditing] = useState(false);
10388
+ const { quantity, unit_price, title } = item;
10389
+ const form = useForm({
10390
+ defaultValues: {
10391
+ title,
10392
+ quantity,
10393
+ unit_price
10394
+ },
10395
+ resolver: zodResolver(customItemSchema)
10475
10396
  });
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) {
10397
+ useEffect(() => {
10398
+ form.reset({
10399
+ title,
10400
+ quantity,
10401
+ unit_price
10402
+ });
10403
+ }, [form, title, quantity, unit_price]);
10404
+ const actionId = useMemo(() => {
10405
+ var _a, _b;
10406
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10407
+ }, [item]);
10408
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10409
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10410
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10411
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10412
+ const onSubmit = form.handleSubmit(async (data) => {
10413
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10414
+ setEditing(false);
10489
10415
  return;
10490
10416
  }
10491
- if (disabled) {
10492
- update[key] = value;
10417
+ if (!actionId) {
10418
+ await updateOriginalItem(
10419
+ {
10420
+ item_id: item.id,
10421
+ quantity: data.quantity,
10422
+ unit_price: convertNumber(data.unit_price)
10423
+ },
10424
+ {
10425
+ onSuccess: () => {
10426
+ setEditing(false);
10427
+ },
10428
+ onError: (e) => {
10429
+ toast.error(e.message);
10430
+ }
10431
+ }
10432
+ );
10493
10433
  return;
10494
10434
  }
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
- }
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;
10508
10445
  }
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);
10446
+ await updateActionItem(
10447
+ {
10448
+ action_id: actionId,
10449
+ quantity: data.quantity,
10450
+ unit_price: convertNumber(data.unit_price)
10451
+ },
10452
+ {
10453
+ onSuccess: () => {
10454
+ setEditing(false);
10455
+ },
10456
+ onError: (e) => {
10457
+ toast.error(e.message);
10458
+ }
10542
10459
  }
10543
- };
10544
- const handleDecrement = () => {
10545
- const newValue = value - step;
10546
- if (min === void 0 || newValue >= min) {
10547
- onChange(newValue);
10460
+ );
10461
+ });
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: [
10463
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10464
+ /* @__PURE__ */ jsx(
10465
+ Thumbnail,
10466
+ {
10467
+ thumbnail: item.thumbnail,
10468
+ alt: item.title ?? void 0
10469
+ }
10470
+ ),
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 }) }) });
10478
+ }
10479
+ }
10480
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10481
+ ] }),
10482
+ editing ? /* @__PURE__ */ jsx(
10483
+ Form$2.Field,
10484
+ {
10485
+ control: form.control,
10486
+ name: "quantity",
10487
+ render: ({ field }) => {
10488
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10489
+ }
10548
10490
  }
10549
- };
10550
- return /* @__PURE__ */ jsxs(
10551
- "div",
10491
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10492
+ editing ? /* @__PURE__ */ jsx(
10493
+ Form$2.Field,
10552
10494
  {
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",
10495
+ control: form.control,
10496
+ name: "unit_price",
10497
+ render: ({ field: { onChange, ...field } }) => {
10498
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10499
+ CurrencyInput,
10605
10500
  {
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
- ]
10501
+ ...field,
10502
+ symbol: getNativeSymbol(currencyCode),
10503
+ code: currencyCode,
10504
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10623
10505
  }
10624
- )
10625
- ]
10506
+ ) }) });
10507
+ }
10626
10508
  }
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
- ]
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
+ ] }) }) });
10636
10523
  };
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 };
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" }) });
10644
10534
  };
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,
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(
10662
10560
  {
10663
- fields: "currency_code"
10561
+ q,
10562
+ order,
10563
+ offset: offset ? parseInt(offset) : void 0,
10564
+ limit: LIMIT
10664
10565
  },
10665
10566
  {
10666
- enabled: !!id
10567
+ placeholderData: keepPreviousData
10667
10568
  }
10668
10569
  );
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]);
10570
+ const columns = useColumns();
10571
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10698
10572
  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();
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
+ }))
10719
10582
  },
10720
- onSettled: () => {
10721
- setIsSubmitting(false);
10583
+ {
10584
+ onSuccess: () => {
10585
+ setRowSelection({});
10586
+ setIsOpen(STACKED_MODAL_ID, false);
10587
+ },
10588
+ onError: (e) => {
10589
+ toast.error(e.message);
10590
+ }
10722
10591
  }
10723
- });
10592
+ );
10724
10593
  };
10725
- const onKeyDown = useCallback(
10726
- (e) => {
10727
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10728
- if (modalContent || isSubmitting) {
10729
- return;
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();
10730
10607
  }
10731
- onSubmit();
10732
- }
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() }) })
10698
+ }
10699
+ );
10700
+ },
10701
+ enableSorting: true,
10702
+ sortAscLabel: "Oldest first",
10703
+ sortDescLabel: "Newest first"
10704
+ })
10705
+ ];
10706
+ }, []);
10707
+ };
10708
+ const CustomItemForm = ({ orderId, currencyCode }) => {
10709
+ const { setIsOpen } = useStackedModal();
10710
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10711
+ const form = useForm({
10712
+ defaultValues: {
10713
+ title: "",
10714
+ quantity: 1,
10715
+ unit_price: ""
10733
10716
  },
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,
10717
+ resolver: zodResolver(customItemSchema)
10718
+ });
10719
+ const onSubmit = form.handleSubmit(async (data) => {
10720
+ await addItems(
10746
10721
  {
10747
- id: STACKED_MODAL_ID,
10748
- onOpenChangeCallback: (open) => {
10749
- if (!open) {
10750
- setModalContent(null);
10722
+ items: [
10723
+ {
10724
+ title: data.title,
10725
+ quantity: data.quantity,
10726
+ unit_price: convertNumber(data.unit_price)
10751
10727
  }
10728
+ ]
10729
+ },
10730
+ {
10731
+ onSuccess: () => {
10732
+ setIsOpen(STACKED_MODAL_ID, false);
10752
10733
  },
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: [
10734
+ onError: (e) => {
10735
+ toast.error(e.message);
10736
+ }
10737
+ }
10738
+ );
10739
+ });
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" }),
10748
+ /* @__PURE__ */ jsx(
10749
+ Form$2.Field,
10750
+ {
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: [
10755
10754
  /* @__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" }) })
10755
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10756
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10758
10757
  ] }),
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
- ] })
10758
+ /* @__PURE__ */ jsxs("div", { children: [
10759
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10760
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10761
+ ] })
10762
+ ] }) })
10763
+ }
10764
+ ),
10765
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10766
+ /* @__PURE__ */ jsx(
10767
+ Form$2.Field,
10768
+ {
10769
+ control: form.control,
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" })
10824
10775
  ] }),
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,
10776
+ /* @__PURE__ */ jsxs("div", { children: [
10777
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10778
+ CurrencyInput,
10830
10779
  {
10831
- size: "small",
10832
- leading: "compact",
10833
- className: "text-ui-fg-subtle",
10834
- children: [
10835
- itemCount,
10836
- " ",
10837
- itemCount === 1 ? "item" : "items"
10838
- ]
10780
+ symbol: getNativeSymbol(currencyCode),
10781
+ code: currencyCode,
10782
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10783
+ ...field
10839
10784
  }
10840
10785
  ) }),
10841
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10786
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10842
10787
  ] })
10843
- ] }) }),
10844
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10845
- CustomItemForm,
10846
- {
10847
- orderId: preview.id,
10848
- currencyCode
10849
- }
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" }) }),
10788
+ ] }) })
10789
+ }
10790
+ ),
10791
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10856
10792
  /* @__PURE__ */ jsx(
10857
- Button,
10793
+ Form$2.Field,
10858
10794
  {
10859
- size: "small",
10860
- type: "button",
10861
- onClick: onSubmit,
10862
- isLoading: isSubmitting,
10863
- children: "Save"
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
+ ] }) })
10864
10807
  }
10865
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" })
10866
10813
  ] }) })
10867
- ] });
10814
+ ] }) }) });
10815
+ };
10816
+ const customItemSchema = objectType({
10817
+ title: stringType().min(1),
10818
+ quantity: numberType(),
10819
+ unit_price: unionType([numberType(), stringType()])
10820
+ });
10821
+ const PROMOTION_QUERY_KEY = "promotions";
10822
+ const promotionsQueryKeys = {
10823
+ list: (query2) => [
10824
+ PROMOTION_QUERY_KEY,
10825
+ query2 ? query2 : void 0
10826
+ ],
10827
+ detail: (id, query2) => [
10828
+ PROMOTION_QUERY_KEY,
10829
+ id,
10830
+ query2 ? query2 : void 0
10831
+ ]
10868
10832
  };
10869
- const Item = ({ item, preview, currencyCode }) => {
10870
- if (item.variant_id) {
10871
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10833
+ const usePromotions = (query2, options) => {
10834
+ const { data, ...rest } = useQuery({
10835
+ queryKey: promotionsQueryKeys.list(query2),
10836
+ queryFn: async () => sdk.admin.promotion.list(query2),
10837
+ ...options
10838
+ });
10839
+ return { ...data, ...rest };
10840
+ };
10841
+ const Promotions = () => {
10842
+ const { id } = useParams();
10843
+ const {
10844
+ order: preview,
10845
+ isError: isPreviewError,
10846
+ error: previewError
10847
+ } = useOrderPreview(id, void 0);
10848
+ useInitiateOrderEdit({ preview });
10849
+ const { onCancel } = useCancelOrderEdit({ preview });
10850
+ if (isPreviewError) {
10851
+ throw previewError;
10872
10852
  }
10873
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10853
+ const isReady = !!preview;
10854
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10855
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10856
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10857
+ ] });
10874
10858
  };
10875
- const VariantItem = ({ item, preview, currencyCode }) => {
10876
- const [editing, setEditing] = useState(false);
10877
- const form = useForm({
10878
- defaultValues: {
10879
- quantity: item.quantity,
10880
- unit_price: item.unit_price
10859
+ const PromotionForm = ({ preview }) => {
10860
+ const { items, shipping_methods } = preview;
10861
+ const [isSubmitting, setIsSubmitting] = useState(false);
10862
+ const [comboboxValue, setComboboxValue] = useState("");
10863
+ const { handleSuccess } = useRouteModal();
10864
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10865
+ const promoIds = getPromotionIds(items, shipping_methods);
10866
+ const { promotions, isPending, isError, error } = usePromotions(
10867
+ {
10868
+ id: promoIds
10881
10869
  },
10882
- resolver: zodResolver(variantItemSchema)
10883
- });
10884
- const actionId = useMemo(() => {
10885
- var _a, _b;
10886
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10887
- }, [item]);
10888
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10889
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10890
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10891
- const onSubmit = form.handleSubmit(async (data) => {
10892
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10893
- setEditing(false);
10894
- return;
10870
+ {
10871
+ enabled: !!promoIds.length
10895
10872
  }
10896
- if (!actionId) {
10897
- await updateOriginalItem(
10898
- {
10899
- item_id: item.id,
10900
- quantity: data.quantity,
10901
- unit_price: convertNumber(data.unit_price)
10902
- },
10903
- {
10904
- onSuccess: () => {
10905
- setEditing(false);
10906
- },
10907
- onError: (e) => {
10908
- toast.error(e.message);
10909
- }
10873
+ );
10874
+ const comboboxData = useComboboxData({
10875
+ queryKey: ["promotions", "combobox", promoIds],
10876
+ queryFn: async (params) => {
10877
+ return await sdk.admin.promotion.list({
10878
+ ...params,
10879
+ id: {
10880
+ $nin: promoIds
10910
10881
  }
10911
- );
10882
+ });
10883
+ },
10884
+ getOptions: (data) => {
10885
+ return data.promotions.map((promotion) => ({
10886
+ label: promotion.code,
10887
+ value: promotion.code
10888
+ }));
10889
+ }
10890
+ });
10891
+ const add = async (value) => {
10892
+ if (!value) {
10912
10893
  return;
10913
10894
  }
10914
- await updateActionItem(
10895
+ addPromotions(
10915
10896
  {
10916
- action_id: actionId,
10917
- quantity: data.quantity,
10918
- unit_price: convertNumber(data.unit_price)
10897
+ promo_codes: [value]
10919
10898
  },
10920
10899
  {
10921
- onSuccess: () => {
10922
- setEditing(false);
10923
- },
10924
10900
  onError: (e) => {
10925
10901
  toast.error(e.message);
10902
+ comboboxData.onSearchValueChange("");
10903
+ setComboboxValue("");
10904
+ },
10905
+ onSuccess: () => {
10906
+ comboboxData.onSearchValueChange("");
10907
+ setComboboxValue("");
10926
10908
  }
10927
10909
  }
10928
10910
  );
10929
- });
10930
- 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: [
10932
- /* @__PURE__ */ jsx(
10933
- Thumbnail,
10934
- {
10935
- thumbnail: item.thumbnail,
10936
- alt: item.product_title ?? void 0
10937
- }
10938
- ),
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
10963
- }
10964
- )
10965
- ] })
10966
- ] }),
10967
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10968
- Form$2.Field,
10969
- {
10970
- control: form.control,
10971
- name: "quantity",
10972
- render: ({ field }) => {
10973
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10974
- }
10975
- }
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(
10978
- Form$2.Field,
10979
- {
10980
- control: form.control,
10981
- name: "unit_price",
10982
- render: ({ field: { onChange, ...field } }) => {
10983
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10984
- CurrencyInput,
10985
- {
10986
- ...field,
10987
- symbol: getNativeSymbol(currencyCode),
10988
- code: currencyCode,
10989
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10990
- }
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);
11002
- },
11003
- disabled: isPending,
11004
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10911
+ };
10912
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10913
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10914
+ const onSubmit = async () => {
10915
+ setIsSubmitting(true);
10916
+ let requestSucceeded = false;
10917
+ await requestOrderEdit(void 0, {
10918
+ onError: (e) => {
10919
+ toast.error(e.message);
10920
+ },
10921
+ onSuccess: () => {
10922
+ requestSucceeded = true;
11005
10923
  }
11006
- )
11007
- ] }) }) });
11008
- };
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;
11016
- const form = useForm({
11017
- defaultValues: {
11018
- title,
11019
- quantity,
11020
- unit_price
11021
- },
11022
- resolver: zodResolver(customItemSchema)
11023
- });
11024
- useEffect(() => {
11025
- form.reset({
11026
- title,
11027
- quantity,
11028
- unit_price
11029
10924
  });
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
- 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);
10925
+ if (!requestSucceeded) {
10926
+ setIsSubmitting(false);
11042
10927
  return;
11043
10928
  }
11044
- if (!actionId) {
11045
- await updateOriginalItem(
10929
+ await confirmOrderEdit(void 0, {
10930
+ onError: (e) => {
10931
+ toast.error(e.message);
10932
+ },
10933
+ onSuccess: () => {
10934
+ handleSuccess();
10935
+ },
10936
+ onSettled: () => {
10937
+ setIsSubmitting(false);
10938
+ }
10939
+ });
10940
+ };
10941
+ if (isError) {
10942
+ throw error;
10943
+ }
10944
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10945
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10946
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10947
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10948
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10949
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10950
+ ] }),
10951
+ /* @__PURE__ */ jsx(
10952
+ Combobox,
10953
+ {
10954
+ id: "promotion-combobox",
10955
+ "aria-describedby": "promotion-combobox-hint",
10956
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
10957
+ fetchNextPage: comboboxData.fetchNextPage,
10958
+ options: comboboxData.options,
10959
+ onSearchValueChange: comboboxData.onSearchValueChange,
10960
+ searchValue: comboboxData.searchValue,
10961
+ disabled: comboboxData.disabled || isAddingPromotions,
10962
+ onChange: add,
10963
+ value: comboboxValue
10964
+ }
10965
+ )
10966
+ ] }),
10967
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10968
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10969
+ PromotionItem,
11046
10970
  {
11047
- item_id: item.id,
11048
- quantity: data.quantity,
11049
- unit_price: convertNumber(data.unit_price)
10971
+ promotion,
10972
+ orderId: preview.id,
10973
+ isLoading: isPending
11050
10974
  },
10975
+ promotion.id
10976
+ )) })
10977
+ ] }) }),
10978
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10979
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10980
+ /* @__PURE__ */ jsx(
10981
+ Button,
11051
10982
  {
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);
10983
+ size: "small",
10984
+ type: "submit",
10985
+ isLoading: isSubmitting || isAddingPromotions,
10986
+ children: "Save"
11069
10987
  }
11070
- });
11071
- return;
11072
- }
11073
- await updateActionItem(
10988
+ )
10989
+ ] }) })
10990
+ ] });
10991
+ };
10992
+ const PromotionItem = ({
10993
+ promotion,
10994
+ orderId,
10995
+ isLoading
10996
+ }) => {
10997
+ var _a;
10998
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10999
+ const onRemove = async () => {
11000
+ removePromotions(
11074
11001
  {
11075
- action_id: actionId,
11076
- quantity: data.quantity,
11077
- unit_price: convertNumber(data.unit_price)
11002
+ promo_codes: [promotion.code]
11078
11003
  },
11079
11004
  {
11080
- onSuccess: () => {
11081
- setEditing(false);
11082
- },
11083
11005
  onError: (e) => {
11084
11006
  toast.error(e.message);
11085
11007
  }
11086
11008
  }
11087
11009
  );
11088
- });
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: [
11091
- /* @__PURE__ */ jsx(
11092
- Thumbnail,
11010
+ };
11011
+ const displayValue = getDisplayValue(promotion);
11012
+ return /* @__PURE__ */ jsxs(
11013
+ "div",
11014
+ {
11015
+ className: clx(
11016
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11093
11017
  {
11094
- thumbnail: item.thumbnail,
11095
- alt: item.title ?? void 0
11018
+ "animate-pulse": isLoading
11096
11019
  }
11097
11020
  ),
11098
- editing ? /* @__PURE__ */ jsx(
11099
- Form$2.Field,
11100
- {
11101
- 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 }) }) });
11021
+ children: [
11022
+ /* @__PURE__ */ jsxs("div", { children: [
11023
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11024
+ /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11025
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11026
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11027
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11028
+ ] }),
11029
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11030
+ ] })
11031
+ ] }),
11032
+ /* @__PURE__ */ jsx(
11033
+ IconButton,
11034
+ {
11035
+ size: "small",
11036
+ type: "button",
11037
+ variant: "transparent",
11038
+ onClick: onRemove,
11039
+ isLoading: isPending || isLoading,
11040
+ children: /* @__PURE__ */ jsx(XMark, {})
11105
11041
  }
11106
- }
11107
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
11108
- ] }),
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,
11121
- {
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,
11139
- {
11140
- type: "button",
11141
- size: "small",
11142
- onClick: editing ? onSubmit : () => {
11143
- setEditing(true);
11144
- },
11145
- disabled: isPending,
11146
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
11147
- }
11148
- )
11149
- ] }) }) });
11042
+ )
11043
+ ]
11044
+ },
11045
+ promotion.id
11046
+ );
11150
11047
  };
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" }) });
11048
+ function getDisplayValue(promotion) {
11049
+ var _a, _b, _c, _d;
11050
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11051
+ if (!value) {
11052
+ return null;
11053
+ }
11054
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11055
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11056
+ if (!currency) {
11057
+ return null;
11058
+ }
11059
+ return getLocaleAmount(value, currency);
11060
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11061
+ return formatPercentage(value);
11062
+ }
11063
+ return null;
11064
+ }
11065
+ const formatter = new Intl.NumberFormat([], {
11066
+ style: "percent",
11067
+ minimumFractionDigits: 2
11068
+ });
11069
+ const formatPercentage = (value, isPercentageValue = false) => {
11070
+ let val = value || 0;
11071
+ if (!isPercentageValue) {
11072
+ val = val / 100;
11073
+ }
11074
+ return formatter.format(val);
11161
11075
  };
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;
11076
+ function getPromotionIds(items, shippingMethods) {
11077
+ const promotionIds = /* @__PURE__ */ new Set();
11078
+ for (const item of items) {
11079
+ if (item.adjustments) {
11080
+ for (const adjustment of item.adjustments) {
11081
+ if (adjustment.promotion_id) {
11082
+ promotionIds.add(adjustment.promotion_id);
11177
11083
  }
11178
- return acc;
11179
- }, {})
11180
- );
11181
- }, [items]);
11182
- const { q, order, offset } = useQueryParams(
11183
- ["q", "order", "offset"],
11184
- VARIANT_PREFIX
11185
- );
11186
- const { variants, count, isPending, isError, error } = useProductVariants(
11187
- {
11188
- q,
11189
- order,
11190
- offset: offset ? parseInt(offset) : void 0,
11191
- limit: LIMIT
11192
- },
11193
- {
11194
- placeholderData: keepPreviousData
11084
+ }
11085
+ }
11086
+ }
11087
+ for (const shippingMethod of shippingMethods) {
11088
+ if (shippingMethod.adjustments) {
11089
+ for (const adjustment of shippingMethod.adjustments) {
11090
+ if (adjustment.promotion_id) {
11091
+ promotionIds.add(adjustment.promotion_id);
11092
+ }
11093
+ }
11195
11094
  }
11196
- );
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)
11095
+ }
11096
+ return Array.from(promotionIds);
11097
+ }
11098
+ const InlineTip = forwardRef(
11099
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
11100
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
11101
+ return /* @__PURE__ */ jsxs(
11102
+ "div",
11103
+ {
11104
+ ref,
11105
+ className: clx(
11106
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
11107
+ className
11108
+ ),
11109
+ ...props,
11110
+ children: [
11111
+ /* @__PURE__ */ jsx(
11112
+ "div",
11113
+ {
11114
+ role: "presentation",
11115
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
11116
+ "bg-ui-tag-orange-icon": variant === "warning"
11117
+ })
11118
+ }
11119
+ ),
11120
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
11121
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
11122
+ labelValue,
11123
+ ":"
11124
+ ] }),
11125
+ " ",
11126
+ children
11127
+ ] })
11128
+ ]
11129
+ }
11202
11130
  );
11131
+ }
11132
+ );
11133
+ InlineTip.displayName = "InlineTip";
11134
+ const MetadataFieldSchema = objectType({
11135
+ key: stringType(),
11136
+ disabled: booleanType().optional(),
11137
+ value: anyType()
11138
+ });
11139
+ const MetadataSchema = objectType({
11140
+ metadata: arrayType(MetadataFieldSchema)
11141
+ });
11142
+ const Metadata = () => {
11143
+ const { id } = useParams();
11144
+ const { order, isPending, isError, error } = useOrder(id, {
11145
+ fields: "metadata"
11146
+ });
11147
+ if (isError) {
11148
+ throw error;
11149
+ }
11150
+ const isReady = !isPending && !!order;
11151
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11152
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11153
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
11154
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
11155
+ ] }),
11156
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
11157
+ ] });
11158
+ };
11159
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
11160
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
11161
+ const MetadataForm = ({ orderId, metadata }) => {
11162
+ const { handleSuccess } = useRouteModal();
11163
+ const hasUneditableRows = getHasUneditableRows(metadata);
11164
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
11165
+ const form = useForm({
11166
+ defaultValues: {
11167
+ metadata: getDefaultValues(metadata)
11168
+ },
11169
+ resolver: zodResolver(MetadataSchema)
11170
+ });
11171
+ const handleSubmit = form.handleSubmit(async (data) => {
11172
+ const parsedData = parseValues(data);
11203
11173
  await mutateAsync(
11204
11174
  {
11205
- items: ids.map((id) => ({
11206
- variant_id: id,
11207
- quantity: 1
11208
- }))
11175
+ metadata: parsedData
11209
11176
  },
11210
11177
  {
11211
11178
  onSuccess: () => {
11212
- setRowSelection({});
11213
- setIsOpen(STACKED_MODAL_ID, false);
11179
+ toast.success("Metadata updated");
11180
+ handleSuccess();
11214
11181
  },
11215
- onError: (e) => {
11216
- toast.error(e.message);
11182
+ onError: (error) => {
11183
+ toast.error(error.message);
11217
11184
  }
11218
11185
  }
11219
11186
  );
11220
- };
11221
- if (isError) {
11222
- throw error;
11187
+ });
11188
+ const { fields, insert, remove } = useFieldArray({
11189
+ control: form.control,
11190
+ name: "metadata"
11191
+ });
11192
+ function deleteRow(index) {
11193
+ remove(index);
11194
+ if (fields.length === 1) {
11195
+ insert(0, {
11196
+ key: "",
11197
+ value: "",
11198
+ disabled: false
11199
+ });
11200
+ }
11223
11201
  }
11224
- return /* @__PURE__ */ jsxs(
11225
- StackedFocusModal.Content,
11202
+ function insertRow(index, position) {
11203
+ insert(index + (position === "above" ? 0 : 1), {
11204
+ key: "",
11205
+ value: "",
11206
+ disabled: false
11207
+ });
11208
+ }
11209
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11210
+ KeyboundForm,
11226
11211
  {
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
- },
11212
+ onSubmit: handleSubmit,
11213
+ className: "flex flex-1 flex-col overflow-hidden",
11236
11214
  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." }) })
11215
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
11216
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
11217
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
11218
+ /* @__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" }) }),
11219
+ /* @__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" }) })
11220
+ ] }),
11221
+ fields.map((field, index) => {
11222
+ const isDisabled = field.disabled || false;
11223
+ let placeholder = "-";
11224
+ if (typeof field.value === "object") {
11225
+ placeholder = "{ ... }";
11226
+ }
11227
+ if (Array.isArray(field.value)) {
11228
+ placeholder = "[ ... ]";
11229
+ }
11230
+ return /* @__PURE__ */ jsx(
11231
+ ConditionalTooltip,
11232
+ {
11233
+ showTooltip: isDisabled,
11234
+ content: "This row is disabled because it contains non-primitive data.",
11235
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
11236
+ /* @__PURE__ */ jsxs(
11237
+ "div",
11238
+ {
11239
+ className: clx("grid grid-cols-2 divide-x", {
11240
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
11241
+ }),
11242
+ children: [
11243
+ /* @__PURE__ */ jsx(
11244
+ Form$2.Field,
11245
+ {
11246
+ control: form.control,
11247
+ name: `metadata.${index}.key`,
11248
+ render: ({ field: field2 }) => {
11249
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11250
+ GridInput,
11251
+ {
11252
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
11253
+ ...field2,
11254
+ disabled: isDisabled,
11255
+ placeholder: "Key"
11256
+ }
11257
+ ) }) });
11258
+ }
11259
+ }
11260
+ ),
11261
+ /* @__PURE__ */ jsx(
11262
+ Form$2.Field,
11263
+ {
11264
+ control: form.control,
11265
+ name: `metadata.${index}.value`,
11266
+ render: ({ field: { value, ...field2 } }) => {
11267
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11268
+ GridInput,
11269
+ {
11270
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
11271
+ ...field2,
11272
+ value: isDisabled ? placeholder : value,
11273
+ disabled: isDisabled,
11274
+ placeholder: "Value"
11275
+ }
11276
+ ) }) });
11277
+ }
11278
+ }
11279
+ )
11280
+ ]
11281
+ }
11282
+ ),
11283
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
11284
+ /* @__PURE__ */ jsx(
11285
+ DropdownMenu.Trigger,
11286
+ {
11287
+ className: clx(
11288
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
11289
+ {
11290
+ hidden: isDisabled
11291
+ }
11292
+ ),
11293
+ disabled: isDisabled,
11294
+ asChild: true,
11295
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
11296
+ }
11297
+ ),
11298
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
11299
+ /* @__PURE__ */ jsxs(
11300
+ DropdownMenu.Item,
11301
+ {
11302
+ className: "gap-x-2",
11303
+ onClick: () => insertRow(index, "above"),
11304
+ children: [
11305
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
11306
+ "Insert row above"
11307
+ ]
11308
+ }
11309
+ ),
11310
+ /* @__PURE__ */ jsxs(
11311
+ DropdownMenu.Item,
11312
+ {
11313
+ className: "gap-x-2",
11314
+ onClick: () => insertRow(index, "below"),
11315
+ children: [
11316
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
11317
+ "Insert row below"
11318
+ ]
11319
+ }
11320
+ ),
11321
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
11322
+ /* @__PURE__ */ jsxs(
11323
+ DropdownMenu.Item,
11324
+ {
11325
+ className: "gap-x-2",
11326
+ onClick: () => deleteRow(index),
11327
+ children: [
11328
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
11329
+ "Delete row"
11330
+ ]
11331
+ }
11332
+ )
11333
+ ] })
11334
+ ] })
11335
+ ] })
11336
+ },
11337
+ field.id
11338
+ );
11339
+ })
11340
+ ] }),
11341
+ 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." })
11240
11342
  ] }),
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" })
11343
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11344
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11345
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11264
11346
  ] }) })
11265
11347
  ]
11266
11348
  }
11349
+ ) });
11350
+ };
11351
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
11352
+ return /* @__PURE__ */ jsx(
11353
+ "input",
11354
+ {
11355
+ ref,
11356
+ ...props,
11357
+ autoComplete: "off",
11358
+ className: clx(
11359
+ "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",
11360
+ className
11361
+ )
11362
+ }
11267
11363
  );
11364
+ });
11365
+ GridInput.displayName = "MetadataForm.GridInput";
11366
+ const PlaceholderInner = () => {
11367
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11368
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11369
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11370
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11371
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11372
+ ] }) })
11373
+ ] });
11268
11374
  };
11269
- const columnHelper = createDataTableColumnHelper();
11270
- const useColumns = () => {
11271
- return useMemo(() => {
11375
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
11376
+ function getDefaultValues(metadata) {
11377
+ if (!metadata || !Object.keys(metadata).length) {
11272
11378
  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
- }, []);
11334
- };
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: ""
11343
- },
11344
- resolver: zodResolver(customItemSchema)
11345
- });
11346
- const onSubmit = form.handleSubmit(async (data) => {
11347
- await addItems(
11348
- {
11349
- items: [
11350
- {
11351
- title: data.title,
11352
- quantity: data.quantity,
11353
- unit_price: convertNumber(data.unit_price)
11354
- }
11355
- ]
11356
- },
11357
11379
  {
11358
- onSuccess: () => {
11359
- setIsOpen(STACKED_MODAL_ID, false);
11360
- },
11361
- onError: (e) => {
11362
- toast.error(e.message);
11363
- }
11380
+ key: "",
11381
+ value: "",
11382
+ disabled: false
11364
11383
  }
11365
- );
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." }) })
11373
- ] }),
11374
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11375
- /* @__PURE__ */ jsx(
11376
- Form$2.Field,
11377
- {
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
- ] }) })
11390
- }
11391
- ),
11392
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11393
- /* @__PURE__ */ jsx(
11394
- Form$2.Field,
11395
- {
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
- ] }) })
11416
- }
11417
- ),
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" })
11428
- ] }),
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
- ] }) }) });
11442
- };
11443
- const customItemSchema = objectType({
11444
- title: stringType().min(1),
11445
- quantity: numberType(),
11446
- unit_price: unionType([numberType(), stringType()])
11447
- });
11384
+ ];
11385
+ }
11386
+ return Object.entries(metadata).map(([key, value]) => {
11387
+ if (!EDITABLE_TYPES.includes(typeof value)) {
11388
+ return {
11389
+ key,
11390
+ value,
11391
+ disabled: true
11392
+ };
11393
+ }
11394
+ let stringValue = value;
11395
+ if (typeof value !== "string") {
11396
+ stringValue = JSON.stringify(value);
11397
+ }
11398
+ return {
11399
+ key,
11400
+ value: stringValue,
11401
+ original_key: key
11402
+ };
11403
+ });
11404
+ }
11405
+ function parseValues(values) {
11406
+ const metadata = values.metadata;
11407
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11408
+ if (isEmpty) {
11409
+ return null;
11410
+ }
11411
+ const update = {};
11412
+ metadata.forEach((field) => {
11413
+ let key = field.key;
11414
+ let value = field.value;
11415
+ const disabled = field.disabled;
11416
+ if (!key || !value) {
11417
+ return;
11418
+ }
11419
+ if (disabled) {
11420
+ update[key] = value;
11421
+ return;
11422
+ }
11423
+ key = key.trim();
11424
+ value = value.trim();
11425
+ if (value === "true") {
11426
+ update[key] = true;
11427
+ } else if (value === "false") {
11428
+ update[key] = false;
11429
+ } else {
11430
+ const parsedNumber = parseFloat(value);
11431
+ if (!isNaN(parsedNumber)) {
11432
+ update[key] = parsedNumber;
11433
+ } else {
11434
+ update[key] = value;
11435
+ }
11436
+ }
11437
+ });
11438
+ return update;
11439
+ }
11440
+ function getHasUneditableRows(metadata) {
11441
+ if (!metadata) {
11442
+ return false;
11443
+ }
11444
+ return Object.values(metadata).some(
11445
+ (value) => !EDITABLE_TYPES.includes(typeof value)
11446
+ );
11447
+ }
11448
11448
  const SalesChannel = () => {
11449
11449
  const { id } = useParams();
11450
11450
  const { draft_order, isPending, isError, error } = useDraftOrder(
@@ -12337,230 +12337,27 @@ const CustomAmountField = ({
12337
12337
  Form$2.Field,
12338
12338
  {
12339
12339
  control,
12340
- name: "custom_amount",
12341
- render: ({ field: { onChange, ...field } }) => {
12342
- return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12343
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12344
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Custom amount" }),
12345
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
12346
- ] }),
12347
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12348
- CurrencyInput,
12349
- {
12350
- ...field,
12351
- onValueChange: (value) => onChange(value),
12352
- symbol: getNativeSymbol(currencyCode),
12353
- code: currencyCode
12354
- }
12355
- ) })
12356
- ] });
12357
- }
12358
- }
12359
- );
12360
- };
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,
12340
+ name: "custom_amount",
12341
+ render: ({ field: { onChange, ...field } }) => {
12342
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12343
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12344
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Custom amount" }),
12345
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
12346
+ ] }),
12347
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12348
+ CurrencyInput,
12544
12349
  {
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
- ] })
12350
+ ...field,
12351
+ onValueChange: (value) => onChange(value),
12352
+ symbol: getNativeSymbol(currencyCode),
12353
+ code: currencyCode
12552
12354
  }
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
- ]
12355
+ ) })
12356
+ ] });
12357
+ }
12560
12358
  }
12561
- ) });
12359
+ );
12562
12360
  };
12563
- const schema$1 = addressSchema;
12564
12361
  const TransferOwnership = () => {
12565
12362
  const { id } = useParams();
12566
12363
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -12584,7 +12381,7 @@ const TransferOwnershipForm = ({ order }) => {
12584
12381
  defaultValues: {
12585
12382
  customer_id: order.customer_id || ""
12586
12383
  },
12587
- resolver: zodResolver(schema)
12384
+ resolver: zodResolver(schema$1)
12588
12385
  });
12589
12386
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12590
12387
  const { handleSuccess } = useRouteModal();
@@ -13034,9 +12831,212 @@ const Illustration = () => {
13034
12831
  }
13035
12832
  );
13036
12833
  };
13037
- const schema = objectType({
12834
+ const schema$1 = objectType({
13038
12835
  customer_id: stringType().min(1)
13039
12836
  });
12837
+ const ShippingAddress = () => {
12838
+ const { id } = useParams();
12839
+ const { order, isPending, isError, error } = useOrder(id, {
12840
+ fields: "+shipping_address"
12841
+ });
12842
+ if (isError) {
12843
+ throw error;
12844
+ }
12845
+ const isReady = !isPending && !!order;
12846
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12847
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12848
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Shipping Address" }) }),
12849
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the shipping address for the draft order" }) })
12850
+ ] }),
12851
+ isReady && /* @__PURE__ */ jsx(ShippingAddressForm, { order })
12852
+ ] });
12853
+ };
12854
+ const ShippingAddressForm = ({ order }) => {
12855
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
12856
+ const form = useForm({
12857
+ defaultValues: {
12858
+ first_name: ((_a = order.shipping_address) == null ? void 0 : _a.first_name) ?? "",
12859
+ last_name: ((_b = order.shipping_address) == null ? void 0 : _b.last_name) ?? "",
12860
+ company: ((_c = order.shipping_address) == null ? void 0 : _c.company) ?? "",
12861
+ address_1: ((_d = order.shipping_address) == null ? void 0 : _d.address_1) ?? "",
12862
+ address_2: ((_e = order.shipping_address) == null ? void 0 : _e.address_2) ?? "",
12863
+ city: ((_f = order.shipping_address) == null ? void 0 : _f.city) ?? "",
12864
+ province: ((_g = order.shipping_address) == null ? void 0 : _g.province) ?? "",
12865
+ country_code: ((_h = order.shipping_address) == null ? void 0 : _h.country_code) ?? "",
12866
+ postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12867
+ phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12868
+ },
12869
+ resolver: zodResolver(schema)
12870
+ });
12871
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12872
+ const { handleSuccess } = useRouteModal();
12873
+ const onSubmit = form.handleSubmit(async (data) => {
12874
+ await mutateAsync(
12875
+ {
12876
+ shipping_address: {
12877
+ first_name: data.first_name,
12878
+ last_name: data.last_name,
12879
+ company: data.company,
12880
+ address_1: data.address_1,
12881
+ address_2: data.address_2,
12882
+ city: data.city,
12883
+ province: data.province,
12884
+ country_code: data.country_code,
12885
+ postal_code: data.postal_code,
12886
+ phone: data.phone
12887
+ }
12888
+ },
12889
+ {
12890
+ onSuccess: () => {
12891
+ handleSuccess();
12892
+ },
12893
+ onError: (error) => {
12894
+ toast.error(error.message);
12895
+ }
12896
+ }
12897
+ );
12898
+ });
12899
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12900
+ KeyboundForm,
12901
+ {
12902
+ className: "flex flex-1 flex-col overflow-hidden",
12903
+ onSubmit,
12904
+ children: [
12905
+ /* @__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: [
12906
+ /* @__PURE__ */ jsx(
12907
+ Form$2.Field,
12908
+ {
12909
+ control: form.control,
12910
+ name: "country_code",
12911
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12912
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
12913
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
12914
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12915
+ ] })
12916
+ }
12917
+ ),
12918
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12919
+ /* @__PURE__ */ jsx(
12920
+ Form$2.Field,
12921
+ {
12922
+ control: form.control,
12923
+ name: "first_name",
12924
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12925
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
12926
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12927
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12928
+ ] })
12929
+ }
12930
+ ),
12931
+ /* @__PURE__ */ jsx(
12932
+ Form$2.Field,
12933
+ {
12934
+ control: form.control,
12935
+ name: "last_name",
12936
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12937
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
12938
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12939
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12940
+ ] })
12941
+ }
12942
+ )
12943
+ ] }),
12944
+ /* @__PURE__ */ jsx(
12945
+ Form$2.Field,
12946
+ {
12947
+ control: form.control,
12948
+ name: "company",
12949
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12950
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
12951
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12952
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12953
+ ] })
12954
+ }
12955
+ ),
12956
+ /* @__PURE__ */ jsx(
12957
+ Form$2.Field,
12958
+ {
12959
+ control: form.control,
12960
+ name: "address_1",
12961
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12962
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
12963
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12964
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12965
+ ] })
12966
+ }
12967
+ ),
12968
+ /* @__PURE__ */ jsx(
12969
+ Form$2.Field,
12970
+ {
12971
+ control: form.control,
12972
+ name: "address_2",
12973
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12974
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
12975
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12976
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12977
+ ] })
12978
+ }
12979
+ ),
12980
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12981
+ /* @__PURE__ */ jsx(
12982
+ Form$2.Field,
12983
+ {
12984
+ control: form.control,
12985
+ name: "postal_code",
12986
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12987
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
12988
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12989
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12990
+ ] })
12991
+ }
12992
+ ),
12993
+ /* @__PURE__ */ jsx(
12994
+ Form$2.Field,
12995
+ {
12996
+ control: form.control,
12997
+ name: "city",
12998
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12999
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
13000
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13001
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13002
+ ] })
13003
+ }
13004
+ )
13005
+ ] }),
13006
+ /* @__PURE__ */ jsx(
13007
+ Form$2.Field,
13008
+ {
13009
+ control: form.control,
13010
+ name: "province",
13011
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13012
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
13013
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13014
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13015
+ ] })
13016
+ }
13017
+ ),
13018
+ /* @__PURE__ */ jsx(
13019
+ Form$2.Field,
13020
+ {
13021
+ control: form.control,
13022
+ name: "phone",
13023
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13024
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
13025
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13026
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13027
+ ] })
13028
+ }
13029
+ )
13030
+ ] }) }),
13031
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13032
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
13033
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
13034
+ ] }) })
13035
+ ]
13036
+ }
13037
+ ) });
13038
+ };
13039
+ const schema = addressSchema;
13040
13040
  const widgetModule = { widgets: [] };
13041
13041
  const routeModule = {
13042
13042
  routes: [
@@ -13061,13 +13061,17 @@ const routeModule = {
13061
13061
  Component: BillingAddress,
13062
13062
  path: "/draft-orders/:id/billing-address"
13063
13063
  },
13064
+ {
13065
+ Component: Email,
13066
+ path: "/draft-orders/:id/email"
13067
+ },
13064
13068
  {
13065
13069
  Component: CustomItems,
13066
13070
  path: "/draft-orders/:id/custom-items"
13067
13071
  },
13068
13072
  {
13069
- Component: Email,
13070
- path: "/draft-orders/:id/email"
13073
+ Component: Items,
13074
+ path: "/draft-orders/:id/items"
13071
13075
  },
13072
13076
  {
13073
13077
  Component: Promotions,
@@ -13077,10 +13081,6 @@ const routeModule = {
13077
13081
  Component: Metadata,
13078
13082
  path: "/draft-orders/:id/metadata"
13079
13083
  },
13080
- {
13081
- Component: Items,
13082
- path: "/draft-orders/:id/items"
13083
- },
13084
13084
  {
13085
13085
  Component: SalesChannel,
13086
13086
  path: "/draft-orders/:id/sales-channel"
@@ -13089,13 +13089,13 @@ const routeModule = {
13089
13089
  Component: Shipping,
13090
13090
  path: "/draft-orders/:id/shipping"
13091
13091
  },
13092
- {
13093
- Component: ShippingAddress,
13094
- path: "/draft-orders/:id/shipping-address"
13095
- },
13096
13092
  {
13097
13093
  Component: TransferOwnership,
13098
13094
  path: "/draft-orders/:id/transfer-ownership"
13095
+ },
13096
+ {
13097
+ Component: ShippingAddress,
13098
+ path: "/draft-orders/:id/shipping-address"
13099
13099
  }
13100
13100
  ]
13101
13101
  }