@medusajs/draft-order 2.10.4-preview-20251004000335 → 2.10.4-preview-20251004060158

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