@medusajs/draft-order 2.10.0-snapshot-20250828141006 → 2.10.0-snapshot-20250904125819

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