@medusajs/draft-order 2.10.4-preview-20250928000328 → 2.10.4-snapshot-20250918173105

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