@medusajs/draft-order 2.11.2-snapshot-20251029124358 → 2.11.2-snapshot-20251029143232

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";
@@ -9823,1429 +9823,859 @@ const EmailForm = ({ order }) => {
9823
9823
  const schema$4 = objectType({
9824
9824
  email: stringType().email()
9825
9825
  });
9826
- const NumberInput = forwardRef(
9827
- ({
9828
- value,
9829
- onChange,
9830
- size = "base",
9831
- min = 0,
9832
- max = 100,
9833
- step = 1,
9834
- className,
9835
- disabled,
9836
- ...props
9837
- }, ref) => {
9838
- const handleChange = (event) => {
9839
- const newValue = event.target.value === "" ? min : Number(event.target.value);
9840
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9841
- onChange(newValue);
9842
- }
9843
- };
9844
- const handleIncrement = () => {
9845
- const newValue = value + step;
9846
- if (max === void 0 || newValue <= max) {
9847
- onChange(newValue);
9848
- }
9849
- };
9850
- const handleDecrement = () => {
9851
- const newValue = value - step;
9852
- if (min === void 0 || newValue >= min) {
9853
- onChange(newValue);
9854
- }
9855
- };
9826
+ const InlineTip = forwardRef(
9827
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
9828
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
9856
9829
  return /* @__PURE__ */ jsxs(
9857
9830
  "div",
9858
9831
  {
9832
+ ref,
9859
9833
  className: clx(
9860
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9861
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9862
- {
9863
- "h-7": size === "small",
9864
- "h-8": size === "base"
9865
- },
9834
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
9866
9835
  className
9867
9836
  ),
9837
+ ...props,
9868
9838
  children: [
9869
9839
  /* @__PURE__ */ jsx(
9870
- "input",
9871
- {
9872
- ref,
9873
- type: "number",
9874
- value,
9875
- onChange: handleChange,
9876
- min,
9877
- max,
9878
- step,
9879
- className: clx(
9880
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9881
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9882
- "placeholder:text-ui-fg-muted"
9883
- ),
9884
- ...props
9885
- }
9886
- ),
9887
- /* @__PURE__ */ jsxs(
9888
- "button",
9840
+ "div",
9889
9841
  {
9890
- className: clx(
9891
- "flex items-center justify-center outline-none transition-fg",
9892
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9893
- "focus:bg-ui-bg-field-component-hover",
9894
- "hover:bg-ui-bg-field-component-hover",
9895
- {
9896
- "size-7": size === "small",
9897
- "size-8": size === "base"
9898
- }
9899
- ),
9900
- type: "button",
9901
- onClick: handleDecrement,
9902
- disabled: min !== void 0 && value <= min || disabled,
9903
- children: [
9904
- /* @__PURE__ */ jsx(Minus, {}),
9905
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9906
- ]
9842
+ role: "presentation",
9843
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
9844
+ "bg-ui-tag-orange-icon": variant === "warning"
9845
+ })
9907
9846
  }
9908
9847
  ),
9909
- /* @__PURE__ */ jsxs(
9910
- "button",
9911
- {
9912
- className: clx(
9913
- "flex items-center justify-center outline-none transition-fg",
9914
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9915
- "focus:bg-ui-bg-field-hover",
9916
- "hover:bg-ui-bg-field-hover",
9917
- {
9918
- "size-7": size === "small",
9919
- "size-8": size === "base"
9920
- }
9921
- ),
9922
- type: "button",
9923
- onClick: handleIncrement,
9924
- disabled: max !== void 0 && value >= max || disabled,
9925
- children: [
9926
- /* @__PURE__ */ jsx(Plus, {}),
9927
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9928
- ]
9929
- }
9930
- )
9848
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
9849
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
9850
+ labelValue,
9851
+ ":"
9852
+ ] }),
9853
+ " ",
9854
+ children
9855
+ ] })
9931
9856
  ]
9932
9857
  }
9933
9858
  );
9934
9859
  }
9935
9860
  );
9936
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9937
- const productVariantsQueryKeys = {
9938
- list: (query2) => [
9939
- PRODUCT_VARIANTS_QUERY_KEY,
9940
- query2 ? query2 : void 0
9941
- ]
9942
- };
9943
- const useProductVariants = (query2, options) => {
9944
- const { data, ...rest } = useQuery({
9945
- queryKey: productVariantsQueryKeys.list(query2),
9946
- queryFn: async () => await sdk.admin.productVariant.list(query2),
9947
- ...options
9948
- });
9949
- return { ...data, ...rest };
9950
- };
9951
- const useCancelOrderEdit = ({ preview }) => {
9952
- const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
9953
- const onCancel = useCallback(async () => {
9954
- if (!preview) {
9955
- return true;
9956
- }
9957
- let res = false;
9958
- await cancelOrderEdit(void 0, {
9959
- onError: (e) => {
9960
- toast.error(e.message);
9961
- },
9962
- onSuccess: () => {
9963
- res = true;
9964
- }
9965
- });
9966
- return res;
9967
- }, [preview, cancelOrderEdit]);
9968
- return { onCancel };
9969
- };
9970
- let IS_REQUEST_RUNNING = false;
9971
- const useInitiateOrderEdit = ({
9972
- preview
9973
- }) => {
9974
- const navigate = useNavigate();
9975
- const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
9976
- useEffect(() => {
9977
- async function run() {
9978
- if (IS_REQUEST_RUNNING || !preview) {
9979
- return;
9980
- }
9981
- if (preview.order_change) {
9982
- return;
9983
- }
9984
- IS_REQUEST_RUNNING = true;
9985
- await mutateAsync(void 0, {
9986
- onError: (e) => {
9987
- toast.error(e.message);
9988
- navigate(`/draft-orders/${preview.id}`, { replace: true });
9989
- return;
9990
- }
9991
- });
9992
- IS_REQUEST_RUNNING = false;
9993
- }
9994
- run();
9995
- }, [preview, navigate, mutateAsync]);
9996
- };
9997
- function convertNumber(value) {
9998
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
9999
- }
10000
- const STACKED_MODAL_ID = "items_stacked_modal";
10001
- const Items = () => {
9861
+ InlineTip.displayName = "InlineTip";
9862
+ const MetadataFieldSchema = objectType({
9863
+ key: stringType(),
9864
+ disabled: booleanType().optional(),
9865
+ value: anyType()
9866
+ });
9867
+ const MetadataSchema = objectType({
9868
+ metadata: arrayType(MetadataFieldSchema)
9869
+ });
9870
+ const Metadata = () => {
10002
9871
  const { id } = useParams();
10003
- const {
10004
- order: preview,
10005
- isPending: isPreviewPending,
10006
- isError: isPreviewError,
10007
- error: previewError
10008
- } = useOrderPreview(id, void 0, {
10009
- placeholderData: keepPreviousData
9872
+ const { order, isPending, isError, error } = useOrder(id, {
9873
+ fields: "metadata"
10010
9874
  });
10011
- useInitiateOrderEdit({ preview });
10012
- const { draft_order, isPending, isError, error } = useDraftOrder(
10013
- id,
10014
- {
10015
- fields: "currency_code"
10016
- },
10017
- {
10018
- enabled: !!id
10019
- }
10020
- );
10021
- const { onCancel } = useCancelOrderEdit({ preview });
10022
9875
  if (isError) {
10023
9876
  throw error;
10024
9877
  }
10025
- if (isPreviewError) {
10026
- throw previewError;
10027
- }
10028
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10029
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10030
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10031
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10032
- ] }) });
9878
+ const isReady = !isPending && !!order;
9879
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9880
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9881
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
9882
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
9883
+ ] }),
9884
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
9885
+ ] });
10033
9886
  };
10034
- const ItemsForm = ({ preview, currencyCode }) => {
10035
- var _a;
10036
- const [isSubmitting, setIsSubmitting] = useState(false);
10037
- const [modalContent, setModalContent] = useState(
10038
- null
10039
- );
9887
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
9888
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
9889
+ const MetadataForm = ({ orderId, metadata }) => {
10040
9890
  const { handleSuccess } = useRouteModal();
10041
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10042
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10043
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10044
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10045
- const matches = useMemo(() => {
10046
- return matchSorter(preview.items, query2, {
10047
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10048
- });
10049
- }, [preview.items, query2]);
10050
- const onSubmit = async () => {
10051
- setIsSubmitting(true);
10052
- let requestSucceeded = false;
10053
- await requestOrderEdit(void 0, {
10054
- onError: (e) => {
10055
- toast.error(`Failed to request order edit: ${e.message}`);
10056
- },
10057
- onSuccess: () => {
10058
- requestSucceeded = true;
10059
- }
10060
- });
10061
- if (!requestSucceeded) {
10062
- setIsSubmitting(false);
10063
- return;
10064
- }
10065
- await confirmOrderEdit(void 0, {
10066
- onError: (e) => {
10067
- toast.error(`Failed to confirm order edit: ${e.message}`);
10068
- },
10069
- onSuccess: () => {
10070
- handleSuccess();
10071
- },
10072
- onSettled: () => {
10073
- setIsSubmitting(false);
10074
- }
10075
- });
10076
- };
10077
- const onKeyDown = useCallback(
10078
- (e) => {
10079
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10080
- if (modalContent || isSubmitting) {
10081
- return;
10082
- }
10083
- onSubmit();
10084
- }
10085
- },
10086
- [modalContent, isSubmitting, onSubmit]
10087
- );
10088
- useEffect(() => {
10089
- document.addEventListener("keydown", onKeyDown);
10090
- return () => {
10091
- document.removeEventListener("keydown", onKeyDown);
10092
- };
10093
- }, [onKeyDown]);
10094
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10095
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10096
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10097
- StackedFocusModal,
10098
- {
10099
- id: STACKED_MODAL_ID,
10100
- onOpenChangeCallback: (open) => {
10101
- if (!open) {
10102
- setModalContent(null);
10103
- }
10104
- },
10105
- children: [
10106
- /* @__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: [
10107
- /* @__PURE__ */ jsxs("div", { children: [
10108
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10109
- /* @__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" }) })
10110
- ] }),
10111
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10112
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10113
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10114
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10115
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10116
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10117
- ] }),
10118
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10119
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10120
- Input,
10121
- {
10122
- type: "search",
10123
- placeholder: "Search items",
10124
- value: searchValue,
10125
- onChange: (e) => onSearchValueChange(e.target.value)
10126
- }
10127
- ) }),
10128
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10129
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10130
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10131
- /* @__PURE__ */ jsx(
10132
- StackedModalTrigger$1,
10133
- {
10134
- type: "add-items",
10135
- setModalContent
10136
- }
10137
- ),
10138
- /* @__PURE__ */ jsx(
10139
- StackedModalTrigger$1,
10140
- {
10141
- type: "add-custom-item",
10142
- setModalContent
10143
- }
10144
- )
10145
- ] })
10146
- ] })
10147
- ] })
10148
- ] }),
10149
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10150
- /* @__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: [
10151
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10152
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10153
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10154
- /* @__PURE__ */ jsx("div", {})
10155
- ] }) }),
10156
- /* @__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: [
10157
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10158
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10159
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10160
- Item,
10161
- {
10162
- item,
10163
- preview,
10164
- currencyCode
10165
- },
10166
- item.id
10167
- )) : /* @__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: [
10168
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10169
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10170
- 'No items found for "',
10171
- query2,
10172
- '".'
10173
- ] })
10174
- ] }) })
10175
- ] })
10176
- ] }),
10177
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10178
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10179
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10180
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10181
- Text,
10182
- {
10183
- size: "small",
10184
- leading: "compact",
10185
- className: "text-ui-fg-subtle",
10186
- children: [
10187
- itemCount,
10188
- " ",
10189
- itemCount === 1 ? "item" : "items"
10190
- ]
10191
- }
10192
- ) }),
10193
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10194
- ] })
10195
- ] }) }),
10196
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10197
- CustomItemForm,
10198
- {
10199
- orderId: preview.id,
10200
- currencyCode
10201
- }
10202
- ) : null)
10203
- ]
10204
- }
10205
- ) }),
10206
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10207
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10208
- /* @__PURE__ */ jsx(
10209
- Button,
10210
- {
10211
- size: "small",
10212
- type: "button",
10213
- onClick: onSubmit,
10214
- isLoading: isSubmitting,
10215
- children: "Save"
10216
- }
10217
- )
10218
- ] }) })
10219
- ] });
10220
- };
10221
- const Item = ({ item, preview, currencyCode }) => {
10222
- if (item.variant_id) {
10223
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10224
- }
10225
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10226
- };
10227
- const VariantItem = ({ item, preview, currencyCode }) => {
10228
- const [editing, setEditing] = useState(false);
9891
+ const hasUneditableRows = getHasUneditableRows(metadata);
9892
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10229
9893
  const form = useForm({
10230
9894
  defaultValues: {
10231
- quantity: item.quantity,
10232
- unit_price: item.unit_price
9895
+ metadata: getDefaultValues(metadata)
10233
9896
  },
10234
- resolver: zodResolver(variantItemSchema)
9897
+ resolver: zodResolver(MetadataSchema)
10235
9898
  });
10236
- const actionId = useMemo(() => {
10237
- var _a, _b;
10238
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10239
- }, [item]);
10240
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10241
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10242
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10243
- const onSubmit = form.handleSubmit(async (data) => {
10244
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10245
- setEditing(false);
10246
- return;
10247
- }
10248
- if (!actionId) {
10249
- await updateOriginalItem(
10250
- {
10251
- item_id: item.id,
10252
- quantity: data.quantity,
10253
- unit_price: convertNumber(data.unit_price)
10254
- },
10255
- {
10256
- onSuccess: () => {
10257
- setEditing(false);
10258
- },
10259
- onError: (e) => {
10260
- toast.error(e.message);
10261
- }
10262
- }
10263
- );
10264
- return;
10265
- }
10266
- await updateActionItem(
9899
+ const handleSubmit = form.handleSubmit(async (data) => {
9900
+ const parsedData = parseValues(data);
9901
+ await mutateAsync(
10267
9902
  {
10268
- action_id: actionId,
10269
- quantity: data.quantity,
10270
- unit_price: convertNumber(data.unit_price)
9903
+ metadata: parsedData
10271
9904
  },
10272
9905
  {
10273
9906
  onSuccess: () => {
10274
- setEditing(false);
9907
+ toast.success("Metadata updated");
9908
+ handleSuccess();
10275
9909
  },
10276
- onError: (e) => {
10277
- toast.error(e.message);
9910
+ onError: (error) => {
9911
+ toast.error(error.message);
10278
9912
  }
10279
9913
  }
10280
9914
  );
10281
9915
  });
10282
- 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: [
10283
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10284
- /* @__PURE__ */ jsx(
10285
- Thumbnail,
10286
- {
10287
- thumbnail: item.thumbnail,
10288
- alt: item.product_title ?? void 0
10289
- }
10290
- ),
10291
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10292
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10293
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10294
- /* @__PURE__ */ jsxs(
10295
- Text,
10296
- {
10297
- size: "small",
10298
- leading: "compact",
10299
- className: "text-ui-fg-subtle",
10300
- children: [
10301
- "(",
10302
- item.variant_title,
10303
- ")"
10304
- ]
10305
- }
10306
- )
10307
- ] }),
10308
- /* @__PURE__ */ jsx(
10309
- Text,
10310
- {
10311
- size: "small",
10312
- leading: "compact",
10313
- className: "text-ui-fg-subtle",
10314
- children: item.variant_sku
10315
- }
10316
- )
10317
- ] })
10318
- ] }),
10319
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10320
- Form$2.Field,
10321
- {
10322
- control: form.control,
10323
- name: "quantity",
10324
- render: ({ field }) => {
10325
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10326
- }
10327
- }
10328
- ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10329
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10330
- Form$2.Field,
10331
- {
10332
- control: form.control,
10333
- name: "unit_price",
10334
- render: ({ field: { onChange, ...field } }) => {
10335
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10336
- CurrencyInput,
10337
- {
10338
- ...field,
10339
- symbol: getNativeSymbol(currencyCode),
10340
- code: currencyCode,
10341
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10342
- }
10343
- ) }) });
10344
- }
10345
- }
10346
- ) }) : /* @__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) }) }),
10347
- /* @__PURE__ */ jsx(
10348
- IconButton,
10349
- {
10350
- type: "button",
10351
- size: "small",
10352
- onClick: editing ? onSubmit : () => {
10353
- setEditing(true);
10354
- },
10355
- disabled: isPending,
10356
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10357
- }
10358
- )
10359
- ] }) }) });
10360
- };
10361
- const variantItemSchema = objectType({
10362
- quantity: numberType(),
10363
- unit_price: unionType([numberType(), stringType()])
10364
- });
10365
- const CustomItem = ({ item, preview, currencyCode }) => {
10366
- const [editing, setEditing] = useState(false);
10367
- const { quantity, unit_price, title } = item;
10368
- const form = useForm({
10369
- defaultValues: {
10370
- title,
10371
- quantity,
10372
- unit_price
10373
- },
10374
- resolver: zodResolver(customItemSchema)
9916
+ const { fields, insert, remove } = useFieldArray({
9917
+ control: form.control,
9918
+ name: "metadata"
10375
9919
  });
10376
- useEffect(() => {
10377
- form.reset({
10378
- title,
10379
- quantity,
10380
- unit_price
10381
- });
10382
- }, [form, title, quantity, unit_price]);
10383
- const actionId = useMemo(() => {
10384
- var _a, _b;
10385
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10386
- }, [item]);
10387
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10388
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10389
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10390
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10391
- const onSubmit = form.handleSubmit(async (data) => {
10392
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10393
- setEditing(false);
10394
- return;
10395
- }
10396
- if (!actionId) {
10397
- await updateOriginalItem(
10398
- {
10399
- item_id: item.id,
10400
- quantity: data.quantity,
10401
- unit_price: convertNumber(data.unit_price)
10402
- },
10403
- {
10404
- onSuccess: () => {
10405
- setEditing(false);
10406
- },
10407
- onError: (e) => {
10408
- toast.error(e.message);
10409
- }
10410
- }
10411
- );
10412
- return;
10413
- }
10414
- if (data.quantity === 0) {
10415
- await removeActionItem(actionId, {
10416
- onSuccess: () => {
10417
- setEditing(false);
10418
- },
10419
- onError: (e) => {
10420
- toast.error(e.message);
10421
- }
9920
+ function deleteRow(index) {
9921
+ remove(index);
9922
+ if (fields.length === 1) {
9923
+ insert(0, {
9924
+ key: "",
9925
+ value: "",
9926
+ disabled: false
10422
9927
  });
10423
- return;
10424
9928
  }
10425
- await updateActionItem(
10426
- {
10427
- action_id: actionId,
10428
- quantity: data.quantity,
10429
- unit_price: convertNumber(data.unit_price)
10430
- },
10431
- {
10432
- onSuccess: () => {
10433
- setEditing(false);
10434
- },
10435
- onError: (e) => {
10436
- toast.error(e.message);
10437
- }
10438
- }
10439
- );
10440
- });
10441
- 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: [
10442
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10443
- /* @__PURE__ */ jsx(
10444
- Thumbnail,
10445
- {
10446
- thumbnail: item.thumbnail,
10447
- alt: item.title ?? void 0
10448
- }
10449
- ),
10450
- editing ? /* @__PURE__ */ jsx(
10451
- Form$2.Field,
10452
- {
10453
- control: form.control,
10454
- name: "title",
10455
- render: ({ field }) => {
10456
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10457
- }
10458
- }
10459
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10460
- ] }),
10461
- editing ? /* @__PURE__ */ jsx(
10462
- Form$2.Field,
10463
- {
10464
- control: form.control,
10465
- name: "quantity",
10466
- render: ({ field }) => {
10467
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10468
- }
10469
- }
10470
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10471
- editing ? /* @__PURE__ */ jsx(
10472
- Form$2.Field,
10473
- {
10474
- control: form.control,
10475
- name: "unit_price",
10476
- render: ({ field: { onChange, ...field } }) => {
10477
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10478
- CurrencyInput,
10479
- {
10480
- ...field,
10481
- symbol: getNativeSymbol(currencyCode),
10482
- code: currencyCode,
10483
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10484
- }
10485
- ) }) });
10486
- }
10487
- }
10488
- ) : /* @__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) }) }),
10489
- /* @__PURE__ */ jsx(
10490
- IconButton,
10491
- {
10492
- type: "button",
10493
- size: "small",
10494
- onClick: editing ? onSubmit : () => {
10495
- setEditing(true);
10496
- },
10497
- disabled: isPending,
10498
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10499
- }
10500
- )
10501
- ] }) }) });
10502
- };
10503
- const StackedModalTrigger$1 = ({
10504
- type,
10505
- setModalContent
10506
- }) => {
10507
- const { setIsOpen } = useStackedModal();
10508
- const onClick = useCallback(() => {
10509
- setModalContent(type);
10510
- setIsOpen(STACKED_MODAL_ID, true);
10511
- }, [setModalContent, setIsOpen, type]);
10512
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10513
- };
10514
- const VARIANT_PREFIX = "items";
10515
- const LIMIT = 50;
10516
- const ExistingItemsForm = ({ orderId, items }) => {
10517
- const { setIsOpen } = useStackedModal();
10518
- const [rowSelection, setRowSelection] = useState(
10519
- items.reduce((acc, item) => {
10520
- acc[item.variant_id] = true;
10521
- return acc;
10522
- }, {})
10523
- );
10524
- useEffect(() => {
10525
- setRowSelection(
10526
- items.reduce((acc, item) => {
10527
- if (item.variant_id) {
10528
- acc[item.variant_id] = true;
10529
- }
10530
- return acc;
10531
- }, {})
10532
- );
10533
- }, [items]);
10534
- const { q, order, offset } = useQueryParams(
10535
- ["q", "order", "offset"],
10536
- VARIANT_PREFIX
10537
- );
10538
- const { variants, count, isPending, isError, error } = useProductVariants(
10539
- {
10540
- q,
10541
- order,
10542
- offset: offset ? parseInt(offset) : void 0,
10543
- limit: LIMIT
10544
- },
9929
+ }
9930
+ function insertRow(index, position) {
9931
+ insert(index + (position === "above" ? 0 : 1), {
9932
+ key: "",
9933
+ value: "",
9934
+ disabled: false
9935
+ });
9936
+ }
9937
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9938
+ KeyboundForm,
10545
9939
  {
10546
- placeholderData: keepPreviousData
10547
- }
10548
- );
10549
- const columns = useColumns();
10550
- const { mutateAsync } = useDraftOrderAddItems(orderId);
10551
- const onSubmit = async () => {
10552
- const ids = Object.keys(rowSelection).filter(
10553
- (id) => !items.find((i) => i.variant_id === id)
10554
- );
10555
- await mutateAsync(
10556
- {
10557
- items: ids.map((id) => ({
10558
- variant_id: id,
10559
- quantity: 1
10560
- }))
10561
- },
10562
- {
10563
- onSuccess: () => {
10564
- setRowSelection({});
10565
- setIsOpen(STACKED_MODAL_ID, false);
10566
- },
10567
- onError: (e) => {
10568
- toast.error(e.message);
10569
- }
10570
- }
10571
- );
10572
- };
10573
- if (isError) {
10574
- throw error;
10575
- }
10576
- return /* @__PURE__ */ jsxs(
10577
- StackedFocusModal.Content,
10578
- {
10579
- onOpenAutoFocus: (e) => {
10580
- e.preventDefault();
10581
- const searchInput = document.querySelector(
10582
- "[data-modal-id='modal-search-input']"
10583
- );
10584
- if (searchInput) {
10585
- searchInput.focus();
10586
- }
10587
- },
9940
+ onSubmit: handleSubmit,
9941
+ className: "flex flex-1 flex-col overflow-hidden",
10588
9942
  children: [
10589
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10590
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10591
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10592
- ] }),
10593
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10594
- DataTable,
10595
- {
10596
- data: variants,
10597
- columns,
10598
- isLoading: isPending,
10599
- getRowId: (row) => row.id,
10600
- rowCount: count,
10601
- prefix: VARIANT_PREFIX,
10602
- layout: "fill",
10603
- rowSelection: {
10604
- state: rowSelection,
10605
- onRowSelectionChange: setRowSelection,
10606
- enableRowSelection: (row) => {
10607
- return !items.find((i) => i.variant_id === row.original.id);
9943
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
9944
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
9945
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
9946
+ /* @__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" }) }),
9947
+ /* @__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" }) })
9948
+ ] }),
9949
+ fields.map((field, index) => {
9950
+ const isDisabled = field.disabled || false;
9951
+ let placeholder = "-";
9952
+ if (typeof field.value === "object") {
9953
+ placeholder = "{ ... }";
10608
9954
  }
10609
- },
10610
- autoFocusSearch: true
10611
- }
10612
- ) }),
10613
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10614
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10615
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
9955
+ if (Array.isArray(field.value)) {
9956
+ placeholder = "[ ... ]";
9957
+ }
9958
+ return /* @__PURE__ */ jsx(
9959
+ ConditionalTooltip,
9960
+ {
9961
+ showTooltip: isDisabled,
9962
+ content: "This row is disabled because it contains non-primitive data.",
9963
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
9964
+ /* @__PURE__ */ jsxs(
9965
+ "div",
9966
+ {
9967
+ className: clx("grid grid-cols-2 divide-x", {
9968
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
9969
+ }),
9970
+ children: [
9971
+ /* @__PURE__ */ jsx(
9972
+ Form$2.Field,
9973
+ {
9974
+ control: form.control,
9975
+ name: `metadata.${index}.key`,
9976
+ render: ({ field: field2 }) => {
9977
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
9978
+ GridInput,
9979
+ {
9980
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
9981
+ ...field2,
9982
+ disabled: isDisabled,
9983
+ placeholder: "Key"
9984
+ }
9985
+ ) }) });
9986
+ }
9987
+ }
9988
+ ),
9989
+ /* @__PURE__ */ jsx(
9990
+ Form$2.Field,
9991
+ {
9992
+ control: form.control,
9993
+ name: `metadata.${index}.value`,
9994
+ render: ({ field: { value, ...field2 } }) => {
9995
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
9996
+ GridInput,
9997
+ {
9998
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
9999
+ ...field2,
10000
+ value: isDisabled ? placeholder : value,
10001
+ disabled: isDisabled,
10002
+ placeholder: "Value"
10003
+ }
10004
+ ) }) });
10005
+ }
10006
+ }
10007
+ )
10008
+ ]
10009
+ }
10010
+ ),
10011
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10012
+ /* @__PURE__ */ jsx(
10013
+ DropdownMenu.Trigger,
10014
+ {
10015
+ className: clx(
10016
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10017
+ {
10018
+ hidden: isDisabled
10019
+ }
10020
+ ),
10021
+ disabled: isDisabled,
10022
+ asChild: true,
10023
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10024
+ }
10025
+ ),
10026
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10027
+ /* @__PURE__ */ jsxs(
10028
+ DropdownMenu.Item,
10029
+ {
10030
+ className: "gap-x-2",
10031
+ onClick: () => insertRow(index, "above"),
10032
+ children: [
10033
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10034
+ "Insert row above"
10035
+ ]
10036
+ }
10037
+ ),
10038
+ /* @__PURE__ */ jsxs(
10039
+ DropdownMenu.Item,
10040
+ {
10041
+ className: "gap-x-2",
10042
+ onClick: () => insertRow(index, "below"),
10043
+ children: [
10044
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10045
+ "Insert row below"
10046
+ ]
10047
+ }
10048
+ ),
10049
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10050
+ /* @__PURE__ */ jsxs(
10051
+ DropdownMenu.Item,
10052
+ {
10053
+ className: "gap-x-2",
10054
+ onClick: () => deleteRow(index),
10055
+ children: [
10056
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10057
+ "Delete row"
10058
+ ]
10059
+ }
10060
+ )
10061
+ ] })
10062
+ ] })
10063
+ ] })
10064
+ },
10065
+ field.id
10066
+ );
10067
+ })
10068
+ ] }),
10069
+ 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." })
10070
+ ] }),
10071
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10072
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10073
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10616
10074
  ] }) })
10617
10075
  ]
10618
10076
  }
10077
+ ) });
10078
+ };
10079
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
10080
+ return /* @__PURE__ */ jsx(
10081
+ "input",
10082
+ {
10083
+ ref,
10084
+ ...props,
10085
+ autoComplete: "off",
10086
+ className: clx(
10087
+ "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",
10088
+ className
10089
+ )
10090
+ }
10619
10091
  );
10092
+ });
10093
+ GridInput.displayName = "MetadataForm.GridInput";
10094
+ const PlaceholderInner = () => {
10095
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10096
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10097
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10098
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10099
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10100
+ ] }) })
10101
+ ] });
10620
10102
  };
10621
- const columnHelper = createDataTableColumnHelper();
10622
- const useColumns = () => {
10623
- return useMemo(() => {
10103
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
10104
+ function getDefaultValues(metadata) {
10105
+ if (!metadata || !Object.keys(metadata).length) {
10624
10106
  return [
10625
- columnHelper.select(),
10626
- columnHelper.accessor("product.title", {
10627
- header: "Product",
10628
- cell: ({ row }) => {
10629
- var _a, _b, _c;
10630
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10631
- /* @__PURE__ */ jsx(
10632
- Thumbnail,
10633
- {
10634
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10635
- alt: (_b = row.original.product) == null ? void 0 : _b.title
10636
- }
10637
- ),
10638
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10639
- ] });
10640
- },
10641
- enableSorting: true
10642
- }),
10643
- columnHelper.accessor("title", {
10644
- header: "Variant",
10645
- enableSorting: true
10646
- }),
10647
- columnHelper.accessor("sku", {
10648
- header: "SKU",
10649
- cell: ({ getValue }) => {
10650
- return getValue() ?? "-";
10651
- },
10652
- enableSorting: true
10653
- }),
10654
- columnHelper.accessor("updated_at", {
10655
- header: "Updated",
10656
- cell: ({ getValue }) => {
10657
- return /* @__PURE__ */ jsx(
10658
- Tooltip,
10659
- {
10660
- content: getFullDate({ date: getValue(), includeTime: true }),
10661
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10662
- }
10663
- );
10664
- },
10665
- enableSorting: true,
10666
- sortAscLabel: "Oldest first",
10667
- sortDescLabel: "Newest first"
10668
- }),
10669
- columnHelper.accessor("created_at", {
10670
- header: "Created",
10671
- cell: ({ getValue }) => {
10672
- return /* @__PURE__ */ jsx(
10673
- Tooltip,
10674
- {
10675
- content: getFullDate({ date: getValue(), includeTime: true }),
10676
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10677
- }
10678
- );
10679
- },
10680
- enableSorting: true,
10681
- sortAscLabel: "Oldest first",
10682
- sortDescLabel: "Newest first"
10683
- })
10107
+ {
10108
+ key: "",
10109
+ value: "",
10110
+ disabled: false
10111
+ }
10684
10112
  ];
10685
- }, []);
10113
+ }
10114
+ return Object.entries(metadata).map(([key, value]) => {
10115
+ if (!EDITABLE_TYPES.includes(typeof value)) {
10116
+ return {
10117
+ key,
10118
+ value,
10119
+ disabled: true
10120
+ };
10121
+ }
10122
+ let stringValue = value;
10123
+ if (typeof value !== "string") {
10124
+ stringValue = JSON.stringify(value);
10125
+ }
10126
+ return {
10127
+ key,
10128
+ value: stringValue,
10129
+ original_key: key
10130
+ };
10131
+ });
10132
+ }
10133
+ function parseValues(values) {
10134
+ const metadata = values.metadata;
10135
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10136
+ if (isEmpty) {
10137
+ return null;
10138
+ }
10139
+ const update = {};
10140
+ metadata.forEach((field) => {
10141
+ let key = field.key;
10142
+ let value = field.value;
10143
+ const disabled = field.disabled;
10144
+ if (!key || !value) {
10145
+ return;
10146
+ }
10147
+ if (disabled) {
10148
+ update[key] = value;
10149
+ return;
10150
+ }
10151
+ key = key.trim();
10152
+ value = value.trim();
10153
+ if (value === "true") {
10154
+ update[key] = true;
10155
+ } else if (value === "false") {
10156
+ update[key] = false;
10157
+ } else {
10158
+ const parsedNumber = parseFloat(value);
10159
+ if (!isNaN(parsedNumber)) {
10160
+ update[key] = parsedNumber;
10161
+ } else {
10162
+ update[key] = value;
10163
+ }
10164
+ }
10165
+ });
10166
+ return update;
10167
+ }
10168
+ function getHasUneditableRows(metadata) {
10169
+ if (!metadata) {
10170
+ return false;
10171
+ }
10172
+ return Object.values(metadata).some(
10173
+ (value) => !EDITABLE_TYPES.includes(typeof value)
10174
+ );
10175
+ }
10176
+ const PROMOTION_QUERY_KEY = "promotions";
10177
+ const promotionsQueryKeys = {
10178
+ list: (query2) => [
10179
+ PROMOTION_QUERY_KEY,
10180
+ query2 ? query2 : void 0
10181
+ ],
10182
+ detail: (id, query2) => [
10183
+ PROMOTION_QUERY_KEY,
10184
+ id,
10185
+ query2 ? query2 : void 0
10186
+ ]
10686
10187
  };
10687
- const CustomItemForm = ({ orderId, currencyCode }) => {
10688
- const { setIsOpen } = useStackedModal();
10689
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10690
- const form = useForm({
10691
- defaultValues: {
10692
- title: "",
10693
- quantity: 1,
10694
- unit_price: ""
10188
+ const usePromotions = (query2, options) => {
10189
+ const { data, ...rest } = useQuery({
10190
+ queryKey: promotionsQueryKeys.list(query2),
10191
+ queryFn: async () => sdk.admin.promotion.list(query2),
10192
+ ...options
10193
+ });
10194
+ return { ...data, ...rest };
10195
+ };
10196
+ const useCancelOrderEdit = ({ preview }) => {
10197
+ const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
10198
+ const onCancel = useCallback(async () => {
10199
+ if (!preview) {
10200
+ return true;
10201
+ }
10202
+ let res = false;
10203
+ await cancelOrderEdit(void 0, {
10204
+ onError: (e) => {
10205
+ toast.error(e.message);
10206
+ },
10207
+ onSuccess: () => {
10208
+ res = true;
10209
+ }
10210
+ });
10211
+ return res;
10212
+ }, [preview, cancelOrderEdit]);
10213
+ return { onCancel };
10214
+ };
10215
+ let IS_REQUEST_RUNNING = false;
10216
+ const useInitiateOrderEdit = ({
10217
+ preview
10218
+ }) => {
10219
+ const navigate = useNavigate();
10220
+ const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
10221
+ useEffect(() => {
10222
+ async function run() {
10223
+ if (IS_REQUEST_RUNNING || !preview) {
10224
+ return;
10225
+ }
10226
+ if (preview.order_change) {
10227
+ return;
10228
+ }
10229
+ IS_REQUEST_RUNNING = true;
10230
+ await mutateAsync(void 0, {
10231
+ onError: (e) => {
10232
+ toast.error(e.message);
10233
+ navigate(`/draft-orders/${preview.id}`, { replace: true });
10234
+ return;
10235
+ }
10236
+ });
10237
+ IS_REQUEST_RUNNING = false;
10238
+ }
10239
+ run();
10240
+ }, [preview, navigate, mutateAsync]);
10241
+ };
10242
+ const Promotions = () => {
10243
+ const { id } = useParams();
10244
+ const {
10245
+ order: preview,
10246
+ isError: isPreviewError,
10247
+ error: previewError
10248
+ } = useOrderPreview(id, void 0);
10249
+ useInitiateOrderEdit({ preview });
10250
+ const { onCancel } = useCancelOrderEdit({ preview });
10251
+ if (isPreviewError) {
10252
+ throw previewError;
10253
+ }
10254
+ const isReady = !!preview;
10255
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10256
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10257
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10258
+ ] });
10259
+ };
10260
+ const PromotionForm = ({ preview }) => {
10261
+ const { items, shipping_methods } = preview;
10262
+ const [isSubmitting, setIsSubmitting] = useState(false);
10263
+ const [comboboxValue, setComboboxValue] = useState("");
10264
+ const { handleSuccess } = useRouteModal();
10265
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10266
+ const promoIds = getPromotionIds(items, shipping_methods);
10267
+ const { promotions, isPending, isError, error } = usePromotions(
10268
+ {
10269
+ id: promoIds
10695
10270
  },
10696
- resolver: zodResolver(customItemSchema)
10271
+ {
10272
+ enabled: !!promoIds.length
10273
+ }
10274
+ );
10275
+ const comboboxData = useComboboxData({
10276
+ queryKey: ["promotions", "combobox", promoIds],
10277
+ queryFn: async (params) => {
10278
+ return await sdk.admin.promotion.list({
10279
+ ...params,
10280
+ id: {
10281
+ $nin: promoIds
10282
+ }
10283
+ });
10284
+ },
10285
+ getOptions: (data) => {
10286
+ return data.promotions.map((promotion) => ({
10287
+ label: promotion.code,
10288
+ value: promotion.code
10289
+ }));
10290
+ }
10697
10291
  });
10698
- const onSubmit = form.handleSubmit(async (data) => {
10699
- await addItems(
10292
+ const add = async (value) => {
10293
+ if (!value) {
10294
+ return;
10295
+ }
10296
+ addPromotions(
10700
10297
  {
10701
- items: [
10702
- {
10703
- title: data.title,
10704
- quantity: data.quantity,
10705
- unit_price: convertNumber(data.unit_price)
10706
- }
10707
- ]
10298
+ promo_codes: [value]
10708
10299
  },
10709
10300
  {
10710
- onSuccess: () => {
10711
- setIsOpen(STACKED_MODAL_ID, false);
10712
- },
10713
10301
  onError: (e) => {
10714
10302
  toast.error(e.message);
10303
+ comboboxData.onSearchValueChange("");
10304
+ setComboboxValue("");
10305
+ },
10306
+ onSuccess: () => {
10307
+ comboboxData.onSearchValueChange("");
10308
+ setComboboxValue("");
10715
10309
  }
10716
10310
  }
10717
10311
  );
10718
- });
10719
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10720
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10721
- /* @__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: [
10722
- /* @__PURE__ */ jsxs("div", { children: [
10723
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10724
- /* @__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." }) })
10725
- ] }),
10726
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10727
- /* @__PURE__ */ jsx(
10728
- Form$2.Field,
10729
- {
10730
- control: form.control,
10731
- name: "title",
10732
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10733
- /* @__PURE__ */ jsxs("div", { children: [
10734
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10735
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10736
- ] }),
10737
- /* @__PURE__ */ jsxs("div", { children: [
10738
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10739
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10740
- ] })
10741
- ] }) })
10742
- }
10743
- ),
10312
+ };
10313
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10314
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10315
+ const onSubmit = async () => {
10316
+ setIsSubmitting(true);
10317
+ let requestSucceeded = false;
10318
+ await requestOrderEdit(void 0, {
10319
+ onError: (e) => {
10320
+ toast.error(e.message);
10321
+ },
10322
+ onSuccess: () => {
10323
+ requestSucceeded = true;
10324
+ }
10325
+ });
10326
+ if (!requestSucceeded) {
10327
+ setIsSubmitting(false);
10328
+ return;
10329
+ }
10330
+ await confirmOrderEdit(void 0, {
10331
+ onError: (e) => {
10332
+ toast.error(e.message);
10333
+ },
10334
+ onSuccess: () => {
10335
+ handleSuccess();
10336
+ },
10337
+ onSettled: () => {
10338
+ setIsSubmitting(false);
10339
+ }
10340
+ });
10341
+ };
10342
+ if (isError) {
10343
+ throw error;
10344
+ }
10345
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10346
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10347
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10348
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10349
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10350
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10351
+ ] }),
10352
+ /* @__PURE__ */ jsx(
10353
+ Combobox,
10354
+ {
10355
+ id: "promotion-combobox",
10356
+ "aria-describedby": "promotion-combobox-hint",
10357
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
10358
+ fetchNextPage: comboboxData.fetchNextPage,
10359
+ options: comboboxData.options,
10360
+ onSearchValueChange: comboboxData.onSearchValueChange,
10361
+ searchValue: comboboxData.searchValue,
10362
+ disabled: comboboxData.disabled || isAddingPromotions,
10363
+ onChange: add,
10364
+ value: comboboxValue
10365
+ }
10366
+ )
10367
+ ] }),
10744
10368
  /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10745
- /* @__PURE__ */ jsx(
10746
- Form$2.Field,
10369
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10370
+ PromotionItem,
10747
10371
  {
10748
- control: form.control,
10749
- name: "unit_price",
10750
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10751
- /* @__PURE__ */ jsxs("div", { children: [
10752
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10753
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10754
- ] }),
10755
- /* @__PURE__ */ jsxs("div", { children: [
10756
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10757
- CurrencyInput,
10758
- {
10759
- symbol: getNativeSymbol(currencyCode),
10760
- code: currencyCode,
10761
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10762
- ...field
10763
- }
10764
- ) }),
10765
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10766
- ] })
10767
- ] }) })
10768
- }
10769
- ),
10770
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10372
+ promotion,
10373
+ orderId: preview.id,
10374
+ isLoading: isPending
10375
+ },
10376
+ promotion.id
10377
+ )) })
10378
+ ] }) }),
10379
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10380
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10771
10381
  /* @__PURE__ */ jsx(
10772
- Form$2.Field,
10382
+ Button,
10773
10383
  {
10774
- control: form.control,
10775
- name: "quantity",
10776
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10777
- /* @__PURE__ */ jsxs("div", { children: [
10778
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10779
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10780
- ] }),
10781
- /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
10782
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10783
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10784
- ] })
10785
- ] }) })
10384
+ size: "small",
10385
+ type: "submit",
10386
+ isLoading: isSubmitting || isAddingPromotions,
10387
+ children: "Save"
10786
10388
  }
10787
10389
  )
10788
- ] }) }) }),
10789
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10790
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10791
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10792
10390
  ] }) })
10793
- ] }) }) });
10794
- };
10795
- const customItemSchema = objectType({
10796
- title: stringType().min(1),
10797
- quantity: numberType(),
10798
- unit_price: unionType([numberType(), stringType()])
10799
- });
10800
- const InlineTip = forwardRef(
10801
- ({ variant = "tip", label, className, children, ...props }, ref) => {
10802
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10803
- return /* @__PURE__ */ jsxs(
10804
- "div",
10805
- {
10806
- ref,
10807
- className: clx(
10808
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10809
- className
10810
- ),
10811
- ...props,
10812
- children: [
10813
- /* @__PURE__ */ jsx(
10814
- "div",
10815
- {
10816
- role: "presentation",
10817
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10818
- "bg-ui-tag-orange-icon": variant === "warning"
10819
- })
10820
- }
10821
- ),
10822
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10823
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10824
- labelValue,
10825
- ":"
10826
- ] }),
10827
- " ",
10828
- children
10829
- ] })
10830
- ]
10831
- }
10832
- );
10833
- }
10834
- );
10835
- InlineTip.displayName = "InlineTip";
10836
- const MetadataFieldSchema = objectType({
10837
- key: stringType(),
10838
- disabled: booleanType().optional(),
10839
- value: anyType()
10840
- });
10841
- const MetadataSchema = objectType({
10842
- metadata: arrayType(MetadataFieldSchema)
10843
- });
10844
- const Metadata = () => {
10845
- const { id } = useParams();
10846
- const { order, isPending, isError, error } = useOrder(id, {
10847
- fields: "metadata"
10848
- });
10849
- if (isError) {
10850
- throw error;
10851
- }
10852
- const isReady = !isPending && !!order;
10853
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10854
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10855
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10856
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10857
- ] }),
10858
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10859
10391
  ] });
10860
10392
  };
10861
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10862
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10863
- const MetadataForm = ({ orderId, metadata }) => {
10864
- const { handleSuccess } = useRouteModal();
10865
- const hasUneditableRows = getHasUneditableRows(metadata);
10866
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10867
- const form = useForm({
10868
- defaultValues: {
10869
- metadata: getDefaultValues(metadata)
10870
- },
10871
- resolver: zodResolver(MetadataSchema)
10872
- });
10873
- const handleSubmit = form.handleSubmit(async (data) => {
10874
- const parsedData = parseValues(data);
10875
- await mutateAsync(
10393
+ const PromotionItem = ({
10394
+ promotion,
10395
+ orderId,
10396
+ isLoading
10397
+ }) => {
10398
+ var _a;
10399
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10400
+ const onRemove = async () => {
10401
+ removePromotions(
10876
10402
  {
10877
- metadata: parsedData
10403
+ promo_codes: [promotion.code]
10878
10404
  },
10879
10405
  {
10880
- onSuccess: () => {
10881
- toast.success("Metadata updated");
10882
- handleSuccess();
10883
- },
10884
- onError: (error) => {
10885
- toast.error(error.message);
10406
+ onError: (e) => {
10407
+ toast.error(e.message);
10886
10408
  }
10887
10409
  }
10888
10410
  );
10889
- });
10890
- const { fields, insert, remove } = useFieldArray({
10891
- control: form.control,
10892
- name: "metadata"
10893
- });
10894
- function deleteRow(index) {
10895
- remove(index);
10896
- if (fields.length === 1) {
10897
- insert(0, {
10898
- key: "",
10899
- value: "",
10900
- disabled: false
10901
- });
10902
- }
10903
- }
10904
- function insertRow(index, position) {
10905
- insert(index + (position === "above" ? 0 : 1), {
10906
- key: "",
10907
- value: "",
10908
- disabled: false
10909
- });
10910
- }
10911
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10912
- KeyboundForm,
10411
+ };
10412
+ const displayValue = getDisplayValue(promotion);
10413
+ return /* @__PURE__ */ jsxs(
10414
+ "div",
10913
10415
  {
10914
- onSubmit: handleSubmit,
10915
- className: "flex flex-1 flex-col overflow-hidden",
10416
+ className: clx(
10417
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
10418
+ {
10419
+ "animate-pulse": isLoading
10420
+ }
10421
+ ),
10916
10422
  children: [
10917
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10918
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10919
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10920
- /* @__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" }) }),
10921
- /* @__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" }) })
10423
+ /* @__PURE__ */ jsxs("div", { children: [
10424
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10425
+ /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
10426
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
10427
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
10428
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
10922
10429
  ] }),
10923
- fields.map((field, index) => {
10924
- const isDisabled = field.disabled || false;
10925
- let placeholder = "-";
10926
- if (typeof field.value === "object") {
10927
- placeholder = "{ ... }";
10928
- }
10929
- if (Array.isArray(field.value)) {
10930
- placeholder = "[ ... ]";
10931
- }
10932
- return /* @__PURE__ */ jsx(
10933
- ConditionalTooltip,
10934
- {
10935
- showTooltip: isDisabled,
10936
- content: "This row is disabled because it contains non-primitive data.",
10937
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10938
- /* @__PURE__ */ jsxs(
10939
- "div",
10940
- {
10941
- className: clx("grid grid-cols-2 divide-x", {
10942
- "overflow-hidden rounded-b-lg": index === fields.length - 1
10943
- }),
10944
- children: [
10945
- /* @__PURE__ */ jsx(
10946
- Form$2.Field,
10947
- {
10948
- control: form.control,
10949
- name: `metadata.${index}.key`,
10950
- render: ({ field: field2 }) => {
10951
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10952
- GridInput,
10953
- {
10954
- "aria-labelledby": METADATA_KEY_LABEL_ID,
10955
- ...field2,
10956
- disabled: isDisabled,
10957
- placeholder: "Key"
10958
- }
10959
- ) }) });
10960
- }
10961
- }
10962
- ),
10963
- /* @__PURE__ */ jsx(
10964
- Form$2.Field,
10965
- {
10966
- control: form.control,
10967
- name: `metadata.${index}.value`,
10968
- render: ({ field: { value, ...field2 } }) => {
10969
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10970
- GridInput,
10971
- {
10972
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10973
- ...field2,
10974
- value: isDisabled ? placeholder : value,
10975
- disabled: isDisabled,
10976
- placeholder: "Value"
10977
- }
10978
- ) }) });
10979
- }
10980
- }
10981
- )
10982
- ]
10983
- }
10984
- ),
10985
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10986
- /* @__PURE__ */ jsx(
10987
- DropdownMenu.Trigger,
10988
- {
10989
- className: clx(
10990
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10991
- {
10992
- hidden: isDisabled
10993
- }
10994
- ),
10995
- disabled: isDisabled,
10996
- asChild: true,
10997
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10998
- }
10999
- ),
11000
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
11001
- /* @__PURE__ */ jsxs(
11002
- DropdownMenu.Item,
11003
- {
11004
- className: "gap-x-2",
11005
- onClick: () => insertRow(index, "above"),
11006
- children: [
11007
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
11008
- "Insert row above"
11009
- ]
11010
- }
11011
- ),
11012
- /* @__PURE__ */ jsxs(
11013
- DropdownMenu.Item,
11014
- {
11015
- className: "gap-x-2",
11016
- onClick: () => insertRow(index, "below"),
11017
- children: [
11018
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
11019
- "Insert row below"
11020
- ]
11021
- }
11022
- ),
11023
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
11024
- /* @__PURE__ */ jsxs(
11025
- DropdownMenu.Item,
11026
- {
11027
- className: "gap-x-2",
11028
- onClick: () => deleteRow(index),
11029
- children: [
11030
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
11031
- "Delete row"
11032
- ]
11033
- }
11034
- )
11035
- ] })
11036
- ] })
11037
- ] })
11038
- },
11039
- field.id
11040
- );
11041
- })
11042
- ] }),
11043
- 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." })
10430
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10431
+ ] })
11044
10432
  ] }),
11045
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11046
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11047
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11048
- ] }) })
10433
+ /* @__PURE__ */ jsx(
10434
+ IconButton,
10435
+ {
10436
+ size: "small",
10437
+ type: "button",
10438
+ variant: "transparent",
10439
+ onClick: onRemove,
10440
+ isLoading: isPending || isLoading,
10441
+ children: /* @__PURE__ */ jsx(XMark, {})
10442
+ }
10443
+ )
11049
10444
  ]
11050
- }
11051
- ) });
11052
- };
11053
- const GridInput = forwardRef(({ className, ...props }, ref) => {
11054
- return /* @__PURE__ */ jsx(
11055
- "input",
11056
- {
11057
- ref,
11058
- ...props,
11059
- autoComplete: "off",
11060
- className: clx(
11061
- "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",
11062
- className
11063
- )
11064
- }
10445
+ },
10446
+ promotion.id
11065
10447
  );
11066
- });
11067
- GridInput.displayName = "MetadataForm.GridInput";
11068
- const PlaceholderInner = () => {
11069
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11070
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11071
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11072
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11073
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11074
- ] }) })
11075
- ] });
11076
10448
  };
11077
- const EDITABLE_TYPES = ["string", "number", "boolean"];
11078
- function getDefaultValues(metadata) {
11079
- if (!metadata || !Object.keys(metadata).length) {
11080
- return [
11081
- {
11082
- key: "",
11083
- value: "",
11084
- disabled: false
11085
- }
11086
- ];
10449
+ function getDisplayValue(promotion) {
10450
+ var _a, _b, _c, _d;
10451
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10452
+ if (!value) {
10453
+ return null;
11087
10454
  }
11088
- return Object.entries(metadata).map(([key, value]) => {
11089
- if (!EDITABLE_TYPES.includes(typeof value)) {
11090
- return {
11091
- key,
11092
- value,
11093
- disabled: true
11094
- };
11095
- }
11096
- let stringValue = value;
11097
- if (typeof value !== "string") {
11098
- stringValue = JSON.stringify(value);
10455
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10456
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10457
+ if (!currency) {
10458
+ return null;
11099
10459
  }
11100
- return {
11101
- key,
11102
- value: stringValue,
11103
- original_key: key
11104
- };
11105
- });
10460
+ return getLocaleAmount(value, currency);
10461
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10462
+ return formatPercentage(value);
10463
+ }
10464
+ return null;
11106
10465
  }
11107
- function parseValues(values) {
11108
- const metadata = values.metadata;
11109
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11110
- if (isEmpty) {
11111
- return null;
10466
+ const formatter = new Intl.NumberFormat([], {
10467
+ style: "percent",
10468
+ minimumFractionDigits: 2
10469
+ });
10470
+ const formatPercentage = (value, isPercentageValue = false) => {
10471
+ let val = value || 0;
10472
+ if (!isPercentageValue) {
10473
+ val = val / 100;
11112
10474
  }
11113
- const update = {};
11114
- metadata.forEach((field) => {
11115
- let key = field.key;
11116
- let value = field.value;
11117
- const disabled = field.disabled;
11118
- if (!key || !value) {
11119
- return;
10475
+ return formatter.format(val);
10476
+ };
10477
+ function getPromotionIds(items, shippingMethods) {
10478
+ const promotionIds = /* @__PURE__ */ new Set();
10479
+ for (const item of items) {
10480
+ if (item.adjustments) {
10481
+ for (const adjustment of item.adjustments) {
10482
+ if (adjustment.promotion_id) {
10483
+ promotionIds.add(adjustment.promotion_id);
10484
+ }
10485
+ }
11120
10486
  }
11121
- if (disabled) {
11122
- update[key] = value;
11123
- return;
10487
+ }
10488
+ for (const shippingMethod of shippingMethods) {
10489
+ if (shippingMethod.adjustments) {
10490
+ for (const adjustment of shippingMethod.adjustments) {
10491
+ if (adjustment.promotion_id) {
10492
+ promotionIds.add(adjustment.promotion_id);
10493
+ }
10494
+ }
11124
10495
  }
11125
- key = key.trim();
11126
- value = value.trim();
11127
- if (value === "true") {
11128
- update[key] = true;
11129
- } else if (value === "false") {
11130
- update[key] = false;
11131
- } else {
11132
- const parsedNumber = parseFloat(value);
11133
- if (!isNaN(parsedNumber)) {
11134
- update[key] = parsedNumber;
11135
- } else {
11136
- update[key] = value;
11137
- }
11138
- }
11139
- });
11140
- return update;
11141
- }
11142
- function getHasUneditableRows(metadata) {
11143
- if (!metadata) {
11144
- return false;
11145
10496
  }
11146
- return Object.values(metadata).some(
11147
- (value) => !EDITABLE_TYPES.includes(typeof value)
11148
- );
10497
+ return Array.from(promotionIds);
11149
10498
  }
11150
- const PROMOTION_QUERY_KEY = "promotions";
11151
- const promotionsQueryKeys = {
11152
- list: (query2) => [
11153
- PROMOTION_QUERY_KEY,
11154
- query2 ? query2 : void 0
11155
- ],
11156
- detail: (id, query2) => [
11157
- PROMOTION_QUERY_KEY,
10499
+ const SalesChannel = () => {
10500
+ const { id } = useParams();
10501
+ const { draft_order, isPending, isError, error } = useDraftOrder(
11158
10502
  id,
11159
- query2 ? query2 : void 0
11160
- ]
10503
+ {
10504
+ fields: "+sales_channel_id"
10505
+ },
10506
+ {
10507
+ enabled: !!id
10508
+ }
10509
+ );
10510
+ if (isError) {
10511
+ throw error;
10512
+ }
10513
+ const ISrEADY = !!draft_order && !isPending;
10514
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10515
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10516
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
10517
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
10518
+ ] }),
10519
+ ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
10520
+ ] });
11161
10521
  };
11162
- const usePromotions = (query2, options) => {
11163
- const { data, ...rest } = useQuery({
11164
- queryKey: promotionsQueryKeys.list(query2),
11165
- queryFn: async () => sdk.admin.promotion.list(query2),
11166
- ...options
10522
+ const SalesChannelForm = ({ order }) => {
10523
+ const form = useForm({
10524
+ defaultValues: {
10525
+ sales_channel_id: order.sales_channel_id || ""
10526
+ },
10527
+ resolver: zodResolver(schema$3)
11167
10528
  });
11168
- return { ...data, ...rest };
10529
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10530
+ const { handleSuccess } = useRouteModal();
10531
+ const onSubmit = form.handleSubmit(async (data) => {
10532
+ await mutateAsync(
10533
+ {
10534
+ sales_channel_id: data.sales_channel_id
10535
+ },
10536
+ {
10537
+ onSuccess: () => {
10538
+ toast.success("Sales channel updated");
10539
+ handleSuccess();
10540
+ },
10541
+ onError: (error) => {
10542
+ toast.error(error.message);
10543
+ }
10544
+ }
10545
+ );
10546
+ });
10547
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10548
+ KeyboundForm,
10549
+ {
10550
+ className: "flex flex-1 flex-col overflow-hidden",
10551
+ onSubmit,
10552
+ children: [
10553
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
10554
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10555
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10556
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10557
+ ] }) })
10558
+ ]
10559
+ }
10560
+ ) });
11169
10561
  };
11170
- const Promotions = () => {
10562
+ const SalesChannelField = ({ control, order }) => {
10563
+ const salesChannels = useComboboxData({
10564
+ queryFn: async (params) => {
10565
+ return await sdk.admin.salesChannel.list(params);
10566
+ },
10567
+ queryKey: ["sales-channels"],
10568
+ getOptions: (data) => {
10569
+ return data.sales_channels.map((salesChannel) => ({
10570
+ label: salesChannel.name,
10571
+ value: salesChannel.id
10572
+ }));
10573
+ },
10574
+ defaultValue: order.sales_channel_id || void 0
10575
+ });
10576
+ return /* @__PURE__ */ jsx(
10577
+ Form$2.Field,
10578
+ {
10579
+ control,
10580
+ name: "sales_channel_id",
10581
+ render: ({ field }) => {
10582
+ return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
10583
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
10584
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10585
+ Combobox,
10586
+ {
10587
+ options: salesChannels.options,
10588
+ fetchNextPage: salesChannels.fetchNextPage,
10589
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
10590
+ searchValue: salesChannels.searchValue,
10591
+ onSearchValueChange: salesChannels.onSearchValueChange,
10592
+ placeholder: "Select sales channel",
10593
+ ...field
10594
+ }
10595
+ ) }),
10596
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10597
+ ] });
10598
+ }
10599
+ }
10600
+ );
10601
+ };
10602
+ const schema$3 = objectType({
10603
+ sales_channel_id: stringType().min(1)
10604
+ });
10605
+ function convertNumber(value) {
10606
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10607
+ }
10608
+ const STACKED_FOCUS_MODAL_ID = "shipping-form";
10609
+ const Shipping = () => {
10610
+ var _a;
11171
10611
  const { id } = useParams();
10612
+ const { order, isPending, isError, error } = useOrder(id, {
10613
+ fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
10614
+ });
11172
10615
  const {
11173
10616
  order: preview,
10617
+ isPending: isPreviewPending,
11174
10618
  isError: isPreviewError,
11175
10619
  error: previewError
11176
- } = useOrderPreview(id, void 0);
10620
+ } = useOrderPreview(id);
11177
10621
  useInitiateOrderEdit({ preview });
11178
10622
  const { onCancel } = useCancelOrderEdit({ preview });
10623
+ if (isError) {
10624
+ throw error;
10625
+ }
11179
10626
  if (isPreviewError) {
11180
10627
  throw previewError;
11181
10628
  }
11182
- const isReady = !!preview;
11183
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
11184
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
11185
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
11186
- ] });
10629
+ const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
10630
+ const isReady = preview && !isPreviewPending && order && !isPending;
10631
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
10632
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10633
+ /* @__PURE__ */ jsx(RouteFocusModal.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 py-16 px-6", children: [
10634
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
10635
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
10636
+ ] }) }) }),
10637
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
10638
+ ] }) : isReady ? /* @__PURE__ */ jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxs("div", { children: [
10639
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
10640
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10641
+ ] }) });
11187
10642
  };
11188
- const PromotionForm = ({ preview }) => {
11189
- const { items, shipping_methods } = preview;
10643
+ const ShippingForm = ({ preview, order }) => {
10644
+ var _a;
10645
+ const { setIsOpen } = useStackedModal();
11190
10646
  const [isSubmitting, setIsSubmitting] = useState(false);
11191
- const [comboboxValue, setComboboxValue] = useState("");
11192
- const { handleSuccess } = useRouteModal();
11193
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11194
- const promoIds = getPromotionIds(items, shipping_methods);
11195
- const { promotions, isPending, isError, error } = usePromotions(
10647
+ const [data, setData] = useState(null);
10648
+ const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
10649
+ const { shipping_options } = useShippingOptions(
11196
10650
  {
11197
- id: promoIds
10651
+ id: appliedShippingOptionIds,
10652
+ fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
11198
10653
  },
11199
10654
  {
11200
- enabled: !!promoIds.length
10655
+ enabled: appliedShippingOptionIds.length > 0
11201
10656
  }
11202
10657
  );
11203
- const comboboxData = useComboboxData({
11204
- queryKey: ["promotions", "combobox", promoIds],
11205
- queryFn: async (params) => {
11206
- return await sdk.admin.promotion.list({
11207
- ...params,
11208
- id: {
11209
- $nin: promoIds
11210
- }
11211
- });
11212
- },
11213
- getOptions: (data) => {
11214
- return data.promotions.map((promotion) => ({
11215
- label: promotion.code,
11216
- value: promotion.code
11217
- }));
11218
- }
11219
- });
11220
- const add = async (value) => {
11221
- if (!value) {
11222
- return;
11223
- }
11224
- addPromotions(
11225
- {
11226
- promo_codes: [value]
11227
- },
11228
- {
11229
- onError: (e) => {
11230
- toast.error(e.message);
11231
- comboboxData.onSearchValueChange("");
11232
- setComboboxValue("");
11233
- },
11234
- onSuccess: () => {
11235
- comboboxData.onSearchValueChange("");
11236
- setComboboxValue("");
11237
- }
11238
- }
11239
- );
11240
- };
10658
+ const uniqueShippingProfiles = useMemo(() => {
10659
+ const profiles = /* @__PURE__ */ new Map();
10660
+ getUniqueShippingProfiles(order.items).forEach((profile) => {
10661
+ profiles.set(profile.id, profile);
10662
+ });
10663
+ shipping_options == null ? void 0 : shipping_options.forEach((option) => {
10664
+ profiles.set(option.shipping_profile_id, option.shipping_profile);
10665
+ });
10666
+ return Array.from(profiles.values());
10667
+ }, [order.items, shipping_options]);
10668
+ const { handleSuccess } = useRouteModal();
11241
10669
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11242
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10670
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10671
+ const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
10672
+ const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
11243
10673
  const onSubmit = async () => {
11244
10674
  setIsSubmitting(true);
11245
10675
  let requestSucceeded = false;
11246
10676
  await requestOrderEdit(void 0, {
11247
10677
  onError: (e) => {
11248
- toast.error(e.message);
10678
+ toast.error(`Failed to request order edit: ${e.message}`);
11249
10679
  },
11250
10680
  onSuccess: () => {
11251
10681
  requestSucceeded = true;
@@ -11257,7 +10687,7 @@ const PromotionForm = ({ preview }) => {
11257
10687
  }
11258
10688
  await confirmOrderEdit(void 0, {
11259
10689
  onError: (e) => {
11260
- toast.error(e.message);
10690
+ toast.error(`Failed to confirm order edit: ${e.message}`);
11261
10691
  },
11262
10692
  onSuccess: () => {
11263
10693
  handleSuccess();
@@ -11267,371 +10697,16 @@ const PromotionForm = ({ preview }) => {
11267
10697
  }
11268
10698
  });
11269
10699
  };
11270
- if (isError) {
11271
- throw error;
11272
- }
11273
- return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11274
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
11275
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
11276
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11277
- /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
11278
- /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11279
- ] }),
11280
- /* @__PURE__ */ jsx(
11281
- Combobox,
11282
- {
11283
- id: "promotion-combobox",
11284
- "aria-describedby": "promotion-combobox-hint",
11285
- isFetchingNextPage: comboboxData.isFetchingNextPage,
11286
- fetchNextPage: comboboxData.fetchNextPage,
11287
- options: comboboxData.options,
11288
- onSearchValueChange: comboboxData.onSearchValueChange,
11289
- searchValue: comboboxData.searchValue,
11290
- disabled: comboboxData.disabled || isAddingPromotions,
11291
- onChange: add,
11292
- value: comboboxValue
11293
- }
11294
- )
11295
- ] }),
11296
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11297
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
11298
- PromotionItem,
11299
- {
11300
- promotion,
11301
- orderId: preview.id,
11302
- isLoading: isPending
11303
- },
11304
- promotion.id
11305
- )) })
11306
- ] }) }),
11307
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11308
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11309
- /* @__PURE__ */ jsx(
11310
- Button,
11311
- {
11312
- size: "small",
11313
- type: "submit",
11314
- isLoading: isSubmitting || isAddingPromotions,
11315
- children: "Save"
11316
- }
11317
- )
11318
- ] }) })
11319
- ] });
11320
- };
11321
- const PromotionItem = ({
11322
- promotion,
11323
- orderId,
11324
- isLoading
11325
- }) => {
11326
- var _a;
11327
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
11328
- const onRemove = async () => {
11329
- removePromotions(
11330
- {
11331
- promo_codes: [promotion.code]
11332
- },
11333
- {
11334
- onError: (e) => {
11335
- toast.error(e.message);
11336
- }
11337
- }
11338
- );
11339
- };
11340
- const displayValue = getDisplayValue(promotion);
11341
- return /* @__PURE__ */ jsxs(
11342
- "div",
11343
- {
11344
- className: clx(
11345
- "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11346
- {
11347
- "animate-pulse": isLoading
11348
- }
11349
- ),
11350
- children: [
11351
- /* @__PURE__ */ jsxs("div", { children: [
11352
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11353
- /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11354
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11355
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11356
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11357
- ] }),
11358
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11359
- ] })
11360
- ] }),
11361
- /* @__PURE__ */ jsx(
11362
- IconButton,
11363
- {
11364
- size: "small",
11365
- type: "button",
11366
- variant: "transparent",
11367
- onClick: onRemove,
11368
- isLoading: isPending || isLoading,
11369
- children: /* @__PURE__ */ jsx(XMark, {})
11370
- }
11371
- )
11372
- ]
11373
- },
11374
- promotion.id
11375
- );
11376
- };
11377
- function getDisplayValue(promotion) {
11378
- var _a, _b, _c, _d;
11379
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11380
- if (!value) {
11381
- return null;
11382
- }
11383
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11384
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11385
- if (!currency) {
11386
- return null;
11387
- }
11388
- return getLocaleAmount(value, currency);
11389
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11390
- return formatPercentage(value);
11391
- }
11392
- return null;
11393
- }
11394
- const formatter = new Intl.NumberFormat([], {
11395
- style: "percent",
11396
- minimumFractionDigits: 2
11397
- });
11398
- const formatPercentage = (value, isPercentageValue = false) => {
11399
- let val = value || 0;
11400
- if (!isPercentageValue) {
11401
- val = val / 100;
11402
- }
11403
- return formatter.format(val);
11404
- };
11405
- function getPromotionIds(items, shippingMethods) {
11406
- const promotionIds = /* @__PURE__ */ new Set();
11407
- for (const item of items) {
11408
- if (item.adjustments) {
11409
- for (const adjustment of item.adjustments) {
11410
- if (adjustment.promotion_id) {
11411
- promotionIds.add(adjustment.promotion_id);
11412
- }
11413
- }
11414
- }
11415
- }
11416
- for (const shippingMethod of shippingMethods) {
11417
- if (shippingMethod.adjustments) {
11418
- for (const adjustment of shippingMethod.adjustments) {
11419
- if (adjustment.promotion_id) {
11420
- promotionIds.add(adjustment.promotion_id);
11421
- }
11422
- }
11423
- }
11424
- }
11425
- return Array.from(promotionIds);
11426
- }
11427
- const SalesChannel = () => {
11428
- const { id } = useParams();
11429
- const { draft_order, isPending, isError, error } = useDraftOrder(
11430
- id,
11431
- {
11432
- fields: "+sales_channel_id"
11433
- },
11434
- {
11435
- enabled: !!id
11436
- }
11437
- );
11438
- if (isError) {
11439
- throw error;
11440
- }
11441
- const ISrEADY = !!draft_order && !isPending;
11442
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11443
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11444
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
11445
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
11446
- ] }),
11447
- ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
11448
- ] });
11449
- };
11450
- const SalesChannelForm = ({ order }) => {
11451
- const form = useForm({
11452
- defaultValues: {
11453
- sales_channel_id: order.sales_channel_id || ""
11454
- },
11455
- resolver: zodResolver(schema$3)
11456
- });
11457
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11458
- const { handleSuccess } = useRouteModal();
11459
- const onSubmit = form.handleSubmit(async (data) => {
11460
- await mutateAsync(
11461
- {
11462
- sales_channel_id: data.sales_channel_id
11463
- },
11464
- {
11465
- onSuccess: () => {
11466
- toast.success("Sales channel updated");
11467
- handleSuccess();
11468
- },
11469
- onError: (error) => {
11470
- toast.error(error.message);
10700
+ const onKeydown = useCallback(
10701
+ (e) => {
10702
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10703
+ if (data || isSubmitting) {
10704
+ return;
11471
10705
  }
10706
+ onSubmit();
11472
10707
  }
11473
- );
11474
- });
11475
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11476
- KeyboundForm,
11477
- {
11478
- className: "flex flex-1 flex-col overflow-hidden",
11479
- onSubmit,
11480
- children: [
11481
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
11482
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11483
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11484
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11485
- ] }) })
11486
- ]
11487
- }
11488
- ) });
11489
- };
11490
- const SalesChannelField = ({ control, order }) => {
11491
- const salesChannels = useComboboxData({
11492
- queryFn: async (params) => {
11493
- return await sdk.admin.salesChannel.list(params);
11494
- },
11495
- queryKey: ["sales-channels"],
11496
- getOptions: (data) => {
11497
- return data.sales_channels.map((salesChannel) => ({
11498
- label: salesChannel.name,
11499
- value: salesChannel.id
11500
- }));
11501
10708
  },
11502
- defaultValue: order.sales_channel_id || void 0
11503
- });
11504
- return /* @__PURE__ */ jsx(
11505
- Form$2.Field,
11506
- {
11507
- control,
11508
- name: "sales_channel_id",
11509
- render: ({ field }) => {
11510
- return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11511
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
11512
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11513
- Combobox,
11514
- {
11515
- options: salesChannels.options,
11516
- fetchNextPage: salesChannels.fetchNextPage,
11517
- isFetchingNextPage: salesChannels.isFetchingNextPage,
11518
- searchValue: salesChannels.searchValue,
11519
- onSearchValueChange: salesChannels.onSearchValueChange,
11520
- placeholder: "Select sales channel",
11521
- ...field
11522
- }
11523
- ) }),
11524
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11525
- ] });
11526
- }
11527
- }
11528
- );
11529
- };
11530
- const schema$3 = objectType({
11531
- sales_channel_id: stringType().min(1)
11532
- });
11533
- const STACKED_FOCUS_MODAL_ID = "shipping-form";
11534
- const Shipping = () => {
11535
- var _a;
11536
- const { id } = useParams();
11537
- const { order, isPending, isError, error } = useOrder(id, {
11538
- fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
11539
- });
11540
- const {
11541
- order: preview,
11542
- isPending: isPreviewPending,
11543
- isError: isPreviewError,
11544
- error: previewError
11545
- } = useOrderPreview(id);
11546
- useInitiateOrderEdit({ preview });
11547
- const { onCancel } = useCancelOrderEdit({ preview });
11548
- if (isError) {
11549
- throw error;
11550
- }
11551
- if (isPreviewError) {
11552
- throw previewError;
11553
- }
11554
- const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
11555
- const isReady = preview && !isPreviewPending && order && !isPending;
11556
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
11557
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
11558
- /* @__PURE__ */ jsx(RouteFocusModal.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 py-16 px-6", children: [
11559
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
11560
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
11561
- ] }) }) }),
11562
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
11563
- ] }) : isReady ? /* @__PURE__ */ jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxs("div", { children: [
11564
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
11565
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
11566
- ] }) });
11567
- };
11568
- const ShippingForm = ({ preview, order }) => {
11569
- var _a;
11570
- const { setIsOpen } = useStackedModal();
11571
- const [isSubmitting, setIsSubmitting] = useState(false);
11572
- const [data, setData] = useState(null);
11573
- const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
11574
- const { shipping_options } = useShippingOptions(
11575
- {
11576
- id: appliedShippingOptionIds,
11577
- fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
11578
- },
11579
- {
11580
- enabled: appliedShippingOptionIds.length > 0
11581
- }
11582
- );
11583
- const uniqueShippingProfiles = useMemo(() => {
11584
- const profiles = /* @__PURE__ */ new Map();
11585
- getUniqueShippingProfiles(order.items).forEach((profile) => {
11586
- profiles.set(profile.id, profile);
11587
- });
11588
- shipping_options == null ? void 0 : shipping_options.forEach((option) => {
11589
- profiles.set(option.shipping_profile_id, option.shipping_profile);
11590
- });
11591
- return Array.from(profiles.values());
11592
- }, [order.items, shipping_options]);
11593
- const { handleSuccess } = useRouteModal();
11594
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11595
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
11596
- const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
11597
- const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
11598
- const onSubmit = async () => {
11599
- setIsSubmitting(true);
11600
- let requestSucceeded = false;
11601
- await requestOrderEdit(void 0, {
11602
- onError: (e) => {
11603
- toast.error(`Failed to request order edit: ${e.message}`);
11604
- },
11605
- onSuccess: () => {
11606
- requestSucceeded = true;
11607
- }
11608
- });
11609
- if (!requestSucceeded) {
11610
- setIsSubmitting(false);
11611
- return;
11612
- }
11613
- await confirmOrderEdit(void 0, {
11614
- onError: (e) => {
11615
- toast.error(`Failed to confirm order edit: ${e.message}`);
11616
- },
11617
- onSuccess: () => {
11618
- handleSuccess();
11619
- },
11620
- onSettled: () => {
11621
- setIsSubmitting(false);
11622
- }
11623
- });
11624
- };
11625
- const onKeydown = useCallback(
11626
- (e) => {
11627
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11628
- if (data || isSubmitting) {
11629
- return;
11630
- }
11631
- onSubmit();
11632
- }
11633
- },
11634
- [data, isSubmitting, onSubmit]
10709
+ [data, isSubmitting, onSubmit]
11635
10710
  );
11636
10711
  useEffect(() => {
11637
10712
  document.addEventListener("keydown", onKeydown);
@@ -11837,7 +10912,7 @@ const ShippingForm = ({ preview, order }) => {
11837
10912
  ]
11838
10913
  }
11839
10914
  ) : /* @__PURE__ */ jsx(
11840
- StackedModalTrigger,
10915
+ StackedModalTrigger$1,
11841
10916
  {
11842
10917
  shippingProfileId: profile.id,
11843
10918
  shippingOption,
@@ -11948,7 +11023,7 @@ const ShippingForm = ({ preview, order }) => {
11948
11023
  ] }) })
11949
11024
  ] });
11950
11025
  };
11951
- const StackedModalTrigger = ({
11026
+ const StackedModalTrigger$1 = ({
11952
11027
  shippingProfileId,
11953
11028
  shippingOption,
11954
11029
  shippingMethod,
@@ -12953,68 +12028,993 @@ const Illustration = () => {
12953
12028
  strokeLinejoin: "round"
12954
12029
  }
12955
12030
  ) }),
12956
- /* @__PURE__ */ jsxs("defs", { children: [
12957
- /* @__PURE__ */ jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsx(
12958
- "rect",
12959
- {
12960
- width: "12",
12961
- height: "12",
12962
- fill: "white",
12963
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
12964
- }
12965
- ) }),
12966
- /* @__PURE__ */ jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsx(
12967
- "rect",
12968
- {
12969
- width: "12",
12970
- height: "12",
12971
- fill: "white",
12972
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12973
- }
12974
- ) }),
12975
- /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12976
- "rect",
12977
- {
12978
- width: "12",
12979
- height: "12",
12980
- fill: "white",
12981
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12982
- }
12983
- ) }),
12984
- /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12985
- "rect",
12986
- {
12987
- width: "12",
12988
- height: "12",
12989
- fill: "white",
12990
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12991
- }
12992
- ) }),
12993
- /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
12994
- "rect",
12031
+ /* @__PURE__ */ jsxs("defs", { children: [
12032
+ /* @__PURE__ */ jsx("clipPath", { id: "clip0_20915_38670", children: /* @__PURE__ */ jsx(
12033
+ "rect",
12034
+ {
12035
+ width: "12",
12036
+ height: "12",
12037
+ fill: "white",
12038
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 138.36 74.6508)"
12039
+ }
12040
+ ) }),
12041
+ /* @__PURE__ */ jsx("clipPath", { id: "clip1_20915_38670", children: /* @__PURE__ */ jsx(
12042
+ "rect",
12043
+ {
12044
+ width: "12",
12045
+ height: "12",
12046
+ fill: "white",
12047
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12048
+ }
12049
+ ) }),
12050
+ /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12051
+ "rect",
12052
+ {
12053
+ width: "12",
12054
+ height: "12",
12055
+ fill: "white",
12056
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12057
+ }
12058
+ ) }),
12059
+ /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12060
+ "rect",
12061
+ {
12062
+ width: "12",
12063
+ height: "12",
12064
+ fill: "white",
12065
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12066
+ }
12067
+ ) }),
12068
+ /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
12069
+ "rect",
12070
+ {
12071
+ width: "12",
12072
+ height: "12",
12073
+ fill: "white",
12074
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12075
+ }
12076
+ ) }),
12077
+ /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
12078
+ "rect",
12079
+ {
12080
+ width: "12",
12081
+ height: "12",
12082
+ fill: "white",
12083
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
12084
+ }
12085
+ ) })
12086
+ ] })
12087
+ ]
12088
+ }
12089
+ );
12090
+ };
12091
+ const schema$1 = objectType({
12092
+ customer_id: stringType().min(1)
12093
+ });
12094
+ const NumberInput = forwardRef(
12095
+ ({
12096
+ value,
12097
+ onChange,
12098
+ size = "base",
12099
+ min = 0,
12100
+ max = 100,
12101
+ step = 1,
12102
+ className,
12103
+ disabled,
12104
+ ...props
12105
+ }, ref) => {
12106
+ const handleChange = (event) => {
12107
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
12108
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
12109
+ onChange(newValue);
12110
+ }
12111
+ };
12112
+ const handleIncrement = () => {
12113
+ const newValue = value + step;
12114
+ if (max === void 0 || newValue <= max) {
12115
+ onChange(newValue);
12116
+ }
12117
+ };
12118
+ const handleDecrement = () => {
12119
+ const newValue = value - step;
12120
+ if (min === void 0 || newValue >= min) {
12121
+ onChange(newValue);
12122
+ }
12123
+ };
12124
+ return /* @__PURE__ */ jsxs(
12125
+ "div",
12126
+ {
12127
+ className: clx(
12128
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
12129
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
12130
+ {
12131
+ "h-7": size === "small",
12132
+ "h-8": size === "base"
12133
+ },
12134
+ className
12135
+ ),
12136
+ children: [
12137
+ /* @__PURE__ */ jsx(
12138
+ "input",
12139
+ {
12140
+ ref,
12141
+ type: "number",
12142
+ value,
12143
+ onChange: handleChange,
12144
+ min,
12145
+ max,
12146
+ step,
12147
+ className: clx(
12148
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
12149
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
12150
+ "placeholder:text-ui-fg-muted"
12151
+ ),
12152
+ ...props
12153
+ }
12154
+ ),
12155
+ /* @__PURE__ */ jsxs(
12156
+ "button",
12157
+ {
12158
+ className: clx(
12159
+ "flex items-center justify-center outline-none transition-fg",
12160
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
12161
+ "focus:bg-ui-bg-field-component-hover",
12162
+ "hover:bg-ui-bg-field-component-hover",
12163
+ {
12164
+ "size-7": size === "small",
12165
+ "size-8": size === "base"
12166
+ }
12167
+ ),
12168
+ type: "button",
12169
+ onClick: handleDecrement,
12170
+ disabled: min !== void 0 && value <= min || disabled,
12171
+ children: [
12172
+ /* @__PURE__ */ jsx(Minus, {}),
12173
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
12174
+ ]
12175
+ }
12176
+ ),
12177
+ /* @__PURE__ */ jsxs(
12178
+ "button",
12179
+ {
12180
+ className: clx(
12181
+ "flex items-center justify-center outline-none transition-fg",
12182
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
12183
+ "focus:bg-ui-bg-field-hover",
12184
+ "hover:bg-ui-bg-field-hover",
12185
+ {
12186
+ "size-7": size === "small",
12187
+ "size-8": size === "base"
12188
+ }
12189
+ ),
12190
+ type: "button",
12191
+ onClick: handleIncrement,
12192
+ disabled: max !== void 0 && value >= max || disabled,
12193
+ children: [
12194
+ /* @__PURE__ */ jsx(Plus, {}),
12195
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
12196
+ ]
12197
+ }
12198
+ )
12199
+ ]
12200
+ }
12201
+ );
12202
+ }
12203
+ );
12204
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
12205
+ const productVariantsQueryKeys = {
12206
+ list: (query2) => [
12207
+ PRODUCT_VARIANTS_QUERY_KEY,
12208
+ query2 ? query2 : void 0
12209
+ ]
12210
+ };
12211
+ const useProductVariants = (query2, options) => {
12212
+ const { data, ...rest } = useQuery({
12213
+ queryKey: productVariantsQueryKeys.list(query2),
12214
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
12215
+ ...options
12216
+ });
12217
+ return { ...data, ...rest };
12218
+ };
12219
+ const STACKED_MODAL_ID = "items_stacked_modal";
12220
+ const Items = () => {
12221
+ const { id } = useParams();
12222
+ const {
12223
+ order: preview,
12224
+ isPending: isPreviewPending,
12225
+ isError: isPreviewError,
12226
+ error: previewError
12227
+ } = useOrderPreview(id, void 0, {
12228
+ placeholderData: keepPreviousData
12229
+ });
12230
+ useInitiateOrderEdit({ preview });
12231
+ const { draft_order, isPending, isError, error } = useDraftOrder(
12232
+ id,
12233
+ {
12234
+ fields: "currency_code"
12235
+ },
12236
+ {
12237
+ enabled: !!id
12238
+ }
12239
+ );
12240
+ const { onCancel } = useCancelOrderEdit({ preview });
12241
+ if (isError) {
12242
+ throw error;
12243
+ }
12244
+ if (isPreviewError) {
12245
+ throw previewError;
12246
+ }
12247
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
12248
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
12249
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
12250
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
12251
+ ] }) });
12252
+ };
12253
+ const ItemsForm = ({ preview, currencyCode }) => {
12254
+ var _a;
12255
+ const [isSubmitting, setIsSubmitting] = useState(false);
12256
+ const [modalContent, setModalContent] = useState(
12257
+ null
12258
+ );
12259
+ const { handleSuccess } = useRouteModal();
12260
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
12261
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
12262
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
12263
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
12264
+ const matches = useMemo(() => {
12265
+ return matchSorter(preview.items, query2, {
12266
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
12267
+ });
12268
+ }, [preview.items, query2]);
12269
+ const onSubmit = async () => {
12270
+ setIsSubmitting(true);
12271
+ let requestSucceeded = false;
12272
+ await requestOrderEdit(void 0, {
12273
+ onError: (e) => {
12274
+ toast.error(`Failed to request order edit: ${e.message}`);
12275
+ },
12276
+ onSuccess: () => {
12277
+ requestSucceeded = true;
12278
+ }
12279
+ });
12280
+ if (!requestSucceeded) {
12281
+ setIsSubmitting(false);
12282
+ return;
12283
+ }
12284
+ await confirmOrderEdit(void 0, {
12285
+ onError: (e) => {
12286
+ toast.error(`Failed to confirm order edit: ${e.message}`);
12287
+ },
12288
+ onSuccess: () => {
12289
+ handleSuccess();
12290
+ },
12291
+ onSettled: () => {
12292
+ setIsSubmitting(false);
12293
+ }
12294
+ });
12295
+ };
12296
+ const onKeyDown = useCallback(
12297
+ (e) => {
12298
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
12299
+ if (modalContent || isSubmitting) {
12300
+ return;
12301
+ }
12302
+ onSubmit();
12303
+ }
12304
+ },
12305
+ [modalContent, isSubmitting, onSubmit]
12306
+ );
12307
+ useEffect(() => {
12308
+ document.addEventListener("keydown", onKeyDown);
12309
+ return () => {
12310
+ document.removeEventListener("keydown", onKeyDown);
12311
+ };
12312
+ }, [onKeyDown]);
12313
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
12314
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
12315
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
12316
+ StackedFocusModal,
12317
+ {
12318
+ id: STACKED_MODAL_ID,
12319
+ onOpenChangeCallback: (open) => {
12320
+ if (!open) {
12321
+ setModalContent(null);
12322
+ }
12323
+ },
12324
+ children: [
12325
+ /* @__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: [
12326
+ /* @__PURE__ */ jsxs("div", { children: [
12327
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
12328
+ /* @__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" }) })
12329
+ ] }),
12330
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12331
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
12332
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
12333
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12334
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
12335
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
12336
+ ] }),
12337
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
12338
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
12339
+ Input,
12340
+ {
12341
+ type: "search",
12342
+ placeholder: "Search items",
12343
+ value: searchValue,
12344
+ onChange: (e) => onSearchValueChange(e.target.value)
12345
+ }
12346
+ ) }),
12347
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
12348
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
12349
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
12350
+ /* @__PURE__ */ jsx(
12351
+ StackedModalTrigger,
12352
+ {
12353
+ type: "add-items",
12354
+ setModalContent
12355
+ }
12356
+ ),
12357
+ /* @__PURE__ */ jsx(
12358
+ StackedModalTrigger,
12359
+ {
12360
+ type: "add-custom-item",
12361
+ setModalContent
12362
+ }
12363
+ )
12364
+ ] })
12365
+ ] })
12366
+ ] })
12367
+ ] }),
12368
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
12369
+ /* @__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: [
12370
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
12371
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
12372
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
12373
+ /* @__PURE__ */ jsx("div", {})
12374
+ ] }) }),
12375
+ /* @__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: [
12376
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
12377
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
12378
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
12379
+ Item,
12380
+ {
12381
+ item,
12382
+ preview,
12383
+ currencyCode
12384
+ },
12385
+ item.id
12386
+ )) : /* @__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: [
12387
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
12388
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
12389
+ 'No items found for "',
12390
+ query2,
12391
+ '".'
12392
+ ] })
12393
+ ] }) })
12394
+ ] })
12395
+ ] }),
12396
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12397
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
12398
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
12399
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
12400
+ Text,
12401
+ {
12402
+ size: "small",
12403
+ leading: "compact",
12404
+ className: "text-ui-fg-subtle",
12405
+ children: [
12406
+ itemCount,
12407
+ " ",
12408
+ itemCount === 1 ? "item" : "items"
12409
+ ]
12410
+ }
12411
+ ) }),
12412
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
12413
+ ] })
12414
+ ] }) }),
12415
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
12416
+ CustomItemForm,
12417
+ {
12418
+ orderId: preview.id,
12419
+ currencyCode
12420
+ }
12421
+ ) : null)
12422
+ ]
12423
+ }
12424
+ ) }),
12425
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12426
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12427
+ /* @__PURE__ */ jsx(
12428
+ Button,
12429
+ {
12430
+ size: "small",
12431
+ type: "button",
12432
+ onClick: onSubmit,
12433
+ isLoading: isSubmitting,
12434
+ children: "Save"
12435
+ }
12436
+ )
12437
+ ] }) })
12438
+ ] });
12439
+ };
12440
+ const Item = ({ item, preview, currencyCode }) => {
12441
+ if (item.variant_id) {
12442
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
12443
+ }
12444
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
12445
+ };
12446
+ const VariantItem = ({ item, preview, currencyCode }) => {
12447
+ const [editing, setEditing] = useState(false);
12448
+ const form = useForm({
12449
+ defaultValues: {
12450
+ quantity: item.quantity,
12451
+ unit_price: item.unit_price
12452
+ },
12453
+ resolver: zodResolver(variantItemSchema)
12454
+ });
12455
+ const actionId = useMemo(() => {
12456
+ var _a, _b;
12457
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12458
+ }, [item]);
12459
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12460
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12461
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12462
+ const onSubmit = form.handleSubmit(async (data) => {
12463
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
12464
+ setEditing(false);
12465
+ return;
12466
+ }
12467
+ if (!actionId) {
12468
+ await updateOriginalItem(
12469
+ {
12470
+ item_id: item.id,
12471
+ quantity: data.quantity,
12472
+ unit_price: convertNumber(data.unit_price)
12473
+ },
12474
+ {
12475
+ onSuccess: () => {
12476
+ setEditing(false);
12477
+ },
12478
+ onError: (e) => {
12479
+ toast.error(e.message);
12480
+ }
12481
+ }
12482
+ );
12483
+ return;
12484
+ }
12485
+ await updateActionItem(
12486
+ {
12487
+ action_id: actionId,
12488
+ quantity: data.quantity,
12489
+ unit_price: convertNumber(data.unit_price)
12490
+ },
12491
+ {
12492
+ onSuccess: () => {
12493
+ setEditing(false);
12494
+ },
12495
+ onError: (e) => {
12496
+ toast.error(e.message);
12497
+ }
12498
+ }
12499
+ );
12500
+ });
12501
+ 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: [
12502
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
12503
+ /* @__PURE__ */ jsx(
12504
+ Thumbnail,
12505
+ {
12506
+ thumbnail: item.thumbnail,
12507
+ alt: item.product_title ?? void 0
12508
+ }
12509
+ ),
12510
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12511
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
12512
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
12513
+ /* @__PURE__ */ jsxs(
12514
+ Text,
12515
+ {
12516
+ size: "small",
12517
+ leading: "compact",
12518
+ className: "text-ui-fg-subtle",
12519
+ children: [
12520
+ "(",
12521
+ item.variant_title,
12522
+ ")"
12523
+ ]
12524
+ }
12525
+ )
12526
+ ] }),
12527
+ /* @__PURE__ */ jsx(
12528
+ Text,
12529
+ {
12530
+ size: "small",
12531
+ leading: "compact",
12532
+ className: "text-ui-fg-subtle",
12533
+ children: item.variant_sku
12534
+ }
12535
+ )
12536
+ ] })
12537
+ ] }),
12538
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
12539
+ Form$2.Field,
12540
+ {
12541
+ control: form.control,
12542
+ name: "quantity",
12543
+ render: ({ field }) => {
12544
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
12545
+ }
12546
+ }
12547
+ ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
12548
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
12549
+ Form$2.Field,
12550
+ {
12551
+ control: form.control,
12552
+ name: "unit_price",
12553
+ render: ({ field: { onChange, ...field } }) => {
12554
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12555
+ CurrencyInput,
12556
+ {
12557
+ ...field,
12558
+ symbol: getNativeSymbol(currencyCode),
12559
+ code: currencyCode,
12560
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12561
+ }
12562
+ ) }) });
12563
+ }
12564
+ }
12565
+ ) }) : /* @__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) }) }),
12566
+ /* @__PURE__ */ jsx(
12567
+ IconButton,
12568
+ {
12569
+ type: "button",
12570
+ size: "small",
12571
+ onClick: editing ? onSubmit : () => {
12572
+ setEditing(true);
12573
+ },
12574
+ disabled: isPending,
12575
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
12576
+ }
12577
+ )
12578
+ ] }) }) });
12579
+ };
12580
+ const variantItemSchema = objectType({
12581
+ quantity: numberType(),
12582
+ unit_price: unionType([numberType(), stringType()])
12583
+ });
12584
+ const CustomItem = ({ item, preview, currencyCode }) => {
12585
+ const [editing, setEditing] = useState(false);
12586
+ const { quantity, unit_price, title } = item;
12587
+ const form = useForm({
12588
+ defaultValues: {
12589
+ title,
12590
+ quantity,
12591
+ unit_price
12592
+ },
12593
+ resolver: zodResolver(customItemSchema)
12594
+ });
12595
+ useEffect(() => {
12596
+ form.reset({
12597
+ title,
12598
+ quantity,
12599
+ unit_price
12600
+ });
12601
+ }, [form, title, quantity, unit_price]);
12602
+ const actionId = useMemo(() => {
12603
+ var _a, _b;
12604
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12605
+ }, [item]);
12606
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12607
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
12608
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12609
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12610
+ const onSubmit = form.handleSubmit(async (data) => {
12611
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
12612
+ setEditing(false);
12613
+ return;
12614
+ }
12615
+ if (!actionId) {
12616
+ await updateOriginalItem(
12617
+ {
12618
+ item_id: item.id,
12619
+ quantity: data.quantity,
12620
+ unit_price: convertNumber(data.unit_price)
12621
+ },
12622
+ {
12623
+ onSuccess: () => {
12624
+ setEditing(false);
12625
+ },
12626
+ onError: (e) => {
12627
+ toast.error(e.message);
12628
+ }
12629
+ }
12630
+ );
12631
+ return;
12632
+ }
12633
+ if (data.quantity === 0) {
12634
+ await removeActionItem(actionId, {
12635
+ onSuccess: () => {
12636
+ setEditing(false);
12637
+ },
12638
+ onError: (e) => {
12639
+ toast.error(e.message);
12640
+ }
12641
+ });
12642
+ return;
12643
+ }
12644
+ await updateActionItem(
12645
+ {
12646
+ action_id: actionId,
12647
+ quantity: data.quantity,
12648
+ unit_price: convertNumber(data.unit_price)
12649
+ },
12650
+ {
12651
+ onSuccess: () => {
12652
+ setEditing(false);
12653
+ },
12654
+ onError: (e) => {
12655
+ toast.error(e.message);
12656
+ }
12657
+ }
12658
+ );
12659
+ });
12660
+ 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: [
12661
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
12662
+ /* @__PURE__ */ jsx(
12663
+ Thumbnail,
12664
+ {
12665
+ thumbnail: item.thumbnail,
12666
+ alt: item.title ?? void 0
12667
+ }
12668
+ ),
12669
+ editing ? /* @__PURE__ */ jsx(
12670
+ Form$2.Field,
12671
+ {
12672
+ control: form.control,
12673
+ name: "title",
12674
+ render: ({ field }) => {
12675
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
12676
+ }
12677
+ }
12678
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
12679
+ ] }),
12680
+ editing ? /* @__PURE__ */ jsx(
12681
+ Form$2.Field,
12682
+ {
12683
+ control: form.control,
12684
+ name: "quantity",
12685
+ render: ({ field }) => {
12686
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
12687
+ }
12688
+ }
12689
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
12690
+ editing ? /* @__PURE__ */ jsx(
12691
+ Form$2.Field,
12692
+ {
12693
+ control: form.control,
12694
+ name: "unit_price",
12695
+ render: ({ field: { onChange, ...field } }) => {
12696
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12697
+ CurrencyInput,
12698
+ {
12699
+ ...field,
12700
+ symbol: getNativeSymbol(currencyCode),
12701
+ code: currencyCode,
12702
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12703
+ }
12704
+ ) }) });
12705
+ }
12706
+ }
12707
+ ) : /* @__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) }) }),
12708
+ /* @__PURE__ */ jsx(
12709
+ IconButton,
12710
+ {
12711
+ type: "button",
12712
+ size: "small",
12713
+ onClick: editing ? onSubmit : () => {
12714
+ setEditing(true);
12715
+ },
12716
+ disabled: isPending,
12717
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
12718
+ }
12719
+ )
12720
+ ] }) }) });
12721
+ };
12722
+ const StackedModalTrigger = ({
12723
+ type,
12724
+ setModalContent
12725
+ }) => {
12726
+ const { setIsOpen } = useStackedModal();
12727
+ const onClick = useCallback(() => {
12728
+ setModalContent(type);
12729
+ setIsOpen(STACKED_MODAL_ID, true);
12730
+ }, [setModalContent, setIsOpen, type]);
12731
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
12732
+ };
12733
+ const VARIANT_PREFIX = "items";
12734
+ const LIMIT = 50;
12735
+ const ExistingItemsForm = ({ orderId, items }) => {
12736
+ const { setIsOpen } = useStackedModal();
12737
+ const [rowSelection, setRowSelection] = useState(
12738
+ items.reduce((acc, item) => {
12739
+ acc[item.variant_id] = true;
12740
+ return acc;
12741
+ }, {})
12742
+ );
12743
+ useEffect(() => {
12744
+ setRowSelection(
12745
+ items.reduce((acc, item) => {
12746
+ if (item.variant_id) {
12747
+ acc[item.variant_id] = true;
12748
+ }
12749
+ return acc;
12750
+ }, {})
12751
+ );
12752
+ }, [items]);
12753
+ const { q, order, offset } = useQueryParams(
12754
+ ["q", "order", "offset"],
12755
+ VARIANT_PREFIX
12756
+ );
12757
+ const { variants, count, isPending, isError, error } = useProductVariants(
12758
+ {
12759
+ q,
12760
+ order,
12761
+ offset: offset ? parseInt(offset) : void 0,
12762
+ limit: LIMIT
12763
+ },
12764
+ {
12765
+ placeholderData: keepPreviousData
12766
+ }
12767
+ );
12768
+ const columns = useColumns();
12769
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
12770
+ const onSubmit = async () => {
12771
+ const ids = Object.keys(rowSelection).filter(
12772
+ (id) => !items.find((i) => i.variant_id === id)
12773
+ );
12774
+ await mutateAsync(
12775
+ {
12776
+ items: ids.map((id) => ({
12777
+ variant_id: id,
12778
+ quantity: 1
12779
+ }))
12780
+ },
12781
+ {
12782
+ onSuccess: () => {
12783
+ setRowSelection({});
12784
+ setIsOpen(STACKED_MODAL_ID, false);
12785
+ },
12786
+ onError: (e) => {
12787
+ toast.error(e.message);
12788
+ }
12789
+ }
12790
+ );
12791
+ };
12792
+ if (isError) {
12793
+ throw error;
12794
+ }
12795
+ return /* @__PURE__ */ jsxs(
12796
+ StackedFocusModal.Content,
12797
+ {
12798
+ onOpenAutoFocus: (e) => {
12799
+ e.preventDefault();
12800
+ const searchInput = document.querySelector(
12801
+ "[data-modal-id='modal-search-input']"
12802
+ );
12803
+ if (searchInput) {
12804
+ searchInput.focus();
12805
+ }
12806
+ },
12807
+ children: [
12808
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
12809
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
12810
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
12811
+ ] }),
12812
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
12813
+ DataTable,
12814
+ {
12815
+ data: variants,
12816
+ columns,
12817
+ isLoading: isPending,
12818
+ getRowId: (row) => row.id,
12819
+ rowCount: count,
12820
+ prefix: VARIANT_PREFIX,
12821
+ layout: "fill",
12822
+ rowSelection: {
12823
+ state: rowSelection,
12824
+ onRowSelectionChange: setRowSelection,
12825
+ enableRowSelection: (row) => {
12826
+ return !items.find((i) => i.variant_id === row.original.id);
12827
+ }
12828
+ },
12829
+ autoFocusSearch: true
12830
+ }
12831
+ ) }),
12832
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12833
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12834
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
12835
+ ] }) })
12836
+ ]
12837
+ }
12838
+ );
12839
+ };
12840
+ const columnHelper = createDataTableColumnHelper();
12841
+ const useColumns = () => {
12842
+ return useMemo(() => {
12843
+ return [
12844
+ columnHelper.select(),
12845
+ columnHelper.accessor("product.title", {
12846
+ header: "Product",
12847
+ cell: ({ row }) => {
12848
+ var _a, _b, _c;
12849
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
12850
+ /* @__PURE__ */ jsx(
12851
+ Thumbnail,
12852
+ {
12853
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
12854
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
12855
+ }
12856
+ ),
12857
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
12858
+ ] });
12859
+ },
12860
+ enableSorting: true
12861
+ }),
12862
+ columnHelper.accessor("title", {
12863
+ header: "Variant",
12864
+ enableSorting: true
12865
+ }),
12866
+ columnHelper.accessor("sku", {
12867
+ header: "SKU",
12868
+ cell: ({ getValue }) => {
12869
+ return getValue() ?? "-";
12870
+ },
12871
+ enableSorting: true
12872
+ }),
12873
+ columnHelper.accessor("updated_at", {
12874
+ header: "Updated",
12875
+ cell: ({ getValue }) => {
12876
+ return /* @__PURE__ */ jsx(
12877
+ Tooltip,
12995
12878
  {
12996
- width: "12",
12997
- height: "12",
12998
- fill: "white",
12999
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12879
+ content: getFullDate({ date: getValue(), includeTime: true }),
12880
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
13000
12881
  }
13001
- ) }),
13002
- /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
13003
- "rect",
12882
+ );
12883
+ },
12884
+ enableSorting: true,
12885
+ sortAscLabel: "Oldest first",
12886
+ sortDescLabel: "Newest first"
12887
+ }),
12888
+ columnHelper.accessor("created_at", {
12889
+ header: "Created",
12890
+ cell: ({ getValue }) => {
12891
+ return /* @__PURE__ */ jsx(
12892
+ Tooltip,
13004
12893
  {
13005
- width: "12",
13006
- height: "12",
13007
- fill: "white",
13008
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
12894
+ content: getFullDate({ date: getValue(), includeTime: true }),
12895
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
13009
12896
  }
13010
- ) })
13011
- ] })
13012
- ]
13013
- }
13014
- );
12897
+ );
12898
+ },
12899
+ enableSorting: true,
12900
+ sortAscLabel: "Oldest first",
12901
+ sortDescLabel: "Newest first"
12902
+ })
12903
+ ];
12904
+ }, []);
13015
12905
  };
13016
- const schema$1 = objectType({
13017
- customer_id: stringType().min(1)
12906
+ const CustomItemForm = ({ orderId, currencyCode }) => {
12907
+ const { setIsOpen } = useStackedModal();
12908
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
12909
+ const form = useForm({
12910
+ defaultValues: {
12911
+ title: "",
12912
+ quantity: 1,
12913
+ unit_price: ""
12914
+ },
12915
+ resolver: zodResolver(customItemSchema)
12916
+ });
12917
+ const onSubmit = form.handleSubmit(async (data) => {
12918
+ await addItems(
12919
+ {
12920
+ items: [
12921
+ {
12922
+ title: data.title,
12923
+ quantity: data.quantity,
12924
+ unit_price: convertNumber(data.unit_price)
12925
+ }
12926
+ ]
12927
+ },
12928
+ {
12929
+ onSuccess: () => {
12930
+ setIsOpen(STACKED_MODAL_ID, false);
12931
+ },
12932
+ onError: (e) => {
12933
+ toast.error(e.message);
12934
+ }
12935
+ }
12936
+ );
12937
+ });
12938
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
12939
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
12940
+ /* @__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: [
12941
+ /* @__PURE__ */ jsxs("div", { children: [
12942
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
12943
+ /* @__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." }) })
12944
+ ] }),
12945
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12946
+ /* @__PURE__ */ jsx(
12947
+ Form$2.Field,
12948
+ {
12949
+ control: form.control,
12950
+ name: "title",
12951
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12952
+ /* @__PURE__ */ jsxs("div", { children: [
12953
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
12954
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
12955
+ ] }),
12956
+ /* @__PURE__ */ jsxs("div", { children: [
12957
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12958
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12959
+ ] })
12960
+ ] }) })
12961
+ }
12962
+ ),
12963
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12964
+ /* @__PURE__ */ jsx(
12965
+ Form$2.Field,
12966
+ {
12967
+ control: form.control,
12968
+ name: "unit_price",
12969
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12970
+ /* @__PURE__ */ jsxs("div", { children: [
12971
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
12972
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
12973
+ ] }),
12974
+ /* @__PURE__ */ jsxs("div", { children: [
12975
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12976
+ CurrencyInput,
12977
+ {
12978
+ symbol: getNativeSymbol(currencyCode),
12979
+ code: currencyCode,
12980
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
12981
+ ...field
12982
+ }
12983
+ ) }),
12984
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12985
+ ] })
12986
+ ] }) })
12987
+ }
12988
+ ),
12989
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12990
+ /* @__PURE__ */ jsx(
12991
+ Form$2.Field,
12992
+ {
12993
+ control: form.control,
12994
+ name: "quantity",
12995
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12996
+ /* @__PURE__ */ jsxs("div", { children: [
12997
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
12998
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
12999
+ ] }),
13000
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
13001
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
13002
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13003
+ ] })
13004
+ ] }) })
13005
+ }
13006
+ )
13007
+ ] }) }) }),
13008
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
13009
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
13010
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
13011
+ ] }) })
13012
+ ] }) }) });
13013
+ };
13014
+ const customItemSchema = objectType({
13015
+ title: stringType().min(1),
13016
+ quantity: numberType(),
13017
+ unit_price: unionType([numberType(), stringType()])
13018
13018
  });
13019
13019
  const CustomItems = () => {
13020
13020
  return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
@@ -13065,10 +13065,6 @@ const routeModule = {
13065
13065
  Component: Email,
13066
13066
  path: "/draft-orders/:id/email"
13067
13067
  },
13068
- {
13069
- Component: Items,
13070
- path: "/draft-orders/:id/items"
13071
- },
13072
13068
  {
13073
13069
  Component: Metadata,
13074
13070
  path: "/draft-orders/:id/metadata"
@@ -13093,6 +13089,10 @@ const routeModule = {
13093
13089
  Component: TransferOwnership,
13094
13090
  path: "/draft-orders/:id/transfer-ownership"
13095
13091
  },
13092
+ {
13093
+ Component: Items,
13094
+ path: "/draft-orders/:id/items"
13095
+ },
13096
13096
  {
13097
13097
  Component: CustomItems,
13098
13098
  path: "/draft-orders/:id/custom-items"