@medusajs/draft-order 2.11.4-preview-20251106060134 → 2.11.4-preview-20251106090134

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