@medusajs/draft-order 0.0.7 → 0.0.9

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, EllipsisVertical, ArrowUpMini, ArrowDownMini, Minus, PencilSquare } 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, Minus, PencilSquare, EllipsisVertical, ArrowUpMini, ArrowDownMini } 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";
@@ -9896,90 +9896,148 @@ const BillingAddressForm = ({ order }) => {
9896
9896
  ) });
9897
9897
  };
9898
9898
  const schema$5 = addressSchema;
9899
- const Email = () => {
9900
- const { id } = useParams();
9901
- const { order, isPending, isError, error } = useOrder(id, {
9902
- fields: "+email"
9903
- });
9904
- if (isError) {
9905
- throw error;
9906
- }
9907
- const isReady = !isPending && !!order;
9899
+ const CustomItems = () => {
9908
9900
  return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9909
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9910
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
9911
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
9912
- ] }),
9913
- isReady && /* @__PURE__ */ jsx(EmailForm, { order })
9901
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
9902
+ /* @__PURE__ */ jsx(CustomItemsForm, {})
9914
9903
  ] });
9915
9904
  };
9916
- const EmailForm = ({ order }) => {
9905
+ const CustomItemsForm = () => {
9917
9906
  const form = useForm({
9918
- defaultValues: {
9919
- email: order.email ?? ""
9920
- },
9921
9907
  resolver: zodResolver(schema$4)
9922
9908
  });
9923
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9924
- const { handleSuccess } = useRouteModal();
9925
- const onSubmit = form.handleSubmit(async (data) => {
9926
- await mutateAsync(
9927
- { email: data.email },
9928
- {
9929
- onSuccess: () => {
9930
- handleSuccess();
9931
- },
9932
- onError: (error) => {
9933
- toast.error(error.message);
9934
- }
9935
- }
9936
- );
9937
- });
9938
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9939
- KeyboundForm,
9940
- {
9941
- className: "flex flex-1 flex-col overflow-hidden",
9942
- onSubmit,
9943
- children: [
9944
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
9945
- Form$2.Field,
9946
- {
9947
- control: form.control,
9948
- name: "email",
9949
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9950
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
9951
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9952
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9953
- ] })
9954
- }
9955
- ) }),
9956
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9957
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9958
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9959
- ] }) })
9960
- ]
9961
- }
9962
- ) });
9909
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9910
+ /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
9911
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9912
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9913
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
9914
+ ] }) })
9915
+ ] }) });
9963
9916
  };
9964
9917
  const schema$4 = z.object({
9965
9918
  email: z.string().email()
9966
9919
  });
9967
- const PROMOTION_QUERY_KEY = "promotions";
9968
- const promotionsQueryKeys = {
9920
+ const NumberInput = forwardRef(
9921
+ ({
9922
+ value,
9923
+ onChange,
9924
+ size = "base",
9925
+ min = 0,
9926
+ max = 100,
9927
+ step = 1,
9928
+ className,
9929
+ disabled,
9930
+ ...props
9931
+ }, ref) => {
9932
+ const handleChange = (event) => {
9933
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
9934
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9935
+ onChange(newValue);
9936
+ }
9937
+ };
9938
+ const handleIncrement = () => {
9939
+ const newValue = value + step;
9940
+ if (max === void 0 || newValue <= max) {
9941
+ onChange(newValue);
9942
+ }
9943
+ };
9944
+ const handleDecrement = () => {
9945
+ const newValue = value - step;
9946
+ if (min === void 0 || newValue >= min) {
9947
+ onChange(newValue);
9948
+ }
9949
+ };
9950
+ return /* @__PURE__ */ jsxs(
9951
+ "div",
9952
+ {
9953
+ className: clx(
9954
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9955
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9956
+ {
9957
+ "h-7": size === "small",
9958
+ "h-8": size === "base"
9959
+ },
9960
+ className
9961
+ ),
9962
+ children: [
9963
+ /* @__PURE__ */ jsx(
9964
+ "input",
9965
+ {
9966
+ ref,
9967
+ type: "number",
9968
+ value,
9969
+ onChange: handleChange,
9970
+ min,
9971
+ max,
9972
+ step,
9973
+ className: clx(
9974
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9975
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9976
+ "placeholder:text-ui-fg-muted"
9977
+ ),
9978
+ ...props
9979
+ }
9980
+ ),
9981
+ /* @__PURE__ */ jsxs(
9982
+ "button",
9983
+ {
9984
+ className: clx(
9985
+ "flex items-center justify-center outline-none transition-fg",
9986
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9987
+ "focus:bg-ui-bg-field-component-hover",
9988
+ "hover:bg-ui-bg-field-component-hover",
9989
+ {
9990
+ "size-7": size === "small",
9991
+ "size-8": size === "base"
9992
+ }
9993
+ ),
9994
+ type: "button",
9995
+ onClick: handleDecrement,
9996
+ disabled: min !== void 0 && value <= min || disabled,
9997
+ children: [
9998
+ /* @__PURE__ */ jsx(Minus, {}),
9999
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
10000
+ ]
10001
+ }
10002
+ ),
10003
+ /* @__PURE__ */ jsxs(
10004
+ "button",
10005
+ {
10006
+ className: clx(
10007
+ "flex items-center justify-center outline-none transition-fg",
10008
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10009
+ "focus:bg-ui-bg-field-hover",
10010
+ "hover:bg-ui-bg-field-hover",
10011
+ {
10012
+ "size-7": size === "small",
10013
+ "size-8": size === "base"
10014
+ }
10015
+ ),
10016
+ type: "button",
10017
+ onClick: handleIncrement,
10018
+ disabled: max !== void 0 && value >= max || disabled,
10019
+ children: [
10020
+ /* @__PURE__ */ jsx(Plus, {}),
10021
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
10022
+ ]
10023
+ }
10024
+ )
10025
+ ]
10026
+ }
10027
+ );
10028
+ }
10029
+ );
10030
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
10031
+ const productVariantsQueryKeys = {
9969
10032
  list: (query2) => [
9970
- PROMOTION_QUERY_KEY,
9971
- query2 ? query2 : void 0
9972
- ],
9973
- detail: (id, query2) => [
9974
- PROMOTION_QUERY_KEY,
9975
- id,
10033
+ PRODUCT_VARIANTS_QUERY_KEY,
9976
10034
  query2 ? query2 : void 0
9977
10035
  ]
9978
10036
  };
9979
- const usePromotions = (query2, options) => {
10037
+ const useProductVariants = (query2, options) => {
9980
10038
  const { data, ...rest } = useQuery({
9981
- queryKey: promotionsQueryKeys.list(query2),
9982
- queryFn: async () => sdk.admin.promotion.list(query2),
10039
+ queryKey: productVariantsQueryKeys.list(query2),
10040
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
9983
10041
  ...options
9984
10042
  });
9985
10043
  return { ...data, ...rest };
@@ -10030,85 +10088,65 @@ const useInitiateOrderEdit = ({
10030
10088
  run();
10031
10089
  }, [preview, navigate, mutateAsync]);
10032
10090
  };
10033
- const Promotions = () => {
10091
+ function convertNumber(value) {
10092
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10093
+ }
10094
+ const STACKED_MODAL_ID = "items_stacked_modal";
10095
+ const Items = () => {
10034
10096
  const { id } = useParams();
10035
10097
  const {
10036
10098
  order: preview,
10099
+ isPending: isPreviewPending,
10037
10100
  isError: isPreviewError,
10038
10101
  error: previewError
10039
- } = useOrderPreview(id, void 0);
10102
+ } = useOrderPreview(id, void 0, {
10103
+ placeholderData: keepPreviousData
10104
+ });
10040
10105
  useInitiateOrderEdit({ preview });
10106
+ const { draft_order, isPending, isError, error } = useDraftOrder(
10107
+ id,
10108
+ {
10109
+ fields: "currency_code"
10110
+ },
10111
+ {
10112
+ enabled: !!id
10113
+ }
10114
+ );
10041
10115
  const { onCancel } = useCancelOrderEdit({ preview });
10116
+ if (isError) {
10117
+ throw error;
10118
+ }
10042
10119
  if (isPreviewError) {
10043
10120
  throw previewError;
10044
10121
  }
10045
- const isReady = !!preview;
10046
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10047
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10048
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10049
- ] });
10122
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10123
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10124
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10125
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10126
+ ] }) });
10050
10127
  };
10051
- const PromotionForm = ({ preview }) => {
10052
- const { items, shipping_methods } = preview;
10128
+ const ItemsForm = ({ preview, currencyCode }) => {
10129
+ var _a;
10053
10130
  const [isSubmitting, setIsSubmitting] = useState(false);
10054
- const [comboboxValue, setComboboxValue] = useState("");
10055
- const { handleSuccess } = useRouteModal();
10056
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10057
- const promoCodes = getPromotionCodes(items, shipping_methods);
10058
- const { promotions, isPending, isError, error } = usePromotions(
10059
- {
10060
- code: promoCodes
10061
- },
10062
- {
10063
- enabled: !!promoCodes.length
10064
- }
10131
+ const [modalContent, setModalContent] = useState(
10132
+ null
10065
10133
  );
10066
- const comboboxData = useComboboxData({
10067
- queryKey: ["promotions", "combobox", promoCodes],
10068
- queryFn: async (params) => {
10069
- return await sdk.admin.promotion.list({
10070
- ...params,
10071
- code: {
10072
- $nin: promoCodes
10073
- }
10074
- });
10075
- },
10076
- getOptions: (data) => {
10077
- return data.promotions.map((promotion) => ({
10078
- label: promotion.code,
10079
- value: promotion.code
10080
- }));
10081
- }
10082
- });
10083
- const add = async (value) => {
10084
- if (!value) {
10085
- return;
10086
- }
10087
- addPromotions(
10088
- {
10089
- promo_codes: [value]
10090
- },
10091
- {
10092
- onError: (e) => {
10093
- toast.error(e.message);
10094
- comboboxData.onSearchValueChange("");
10095
- setComboboxValue("");
10096
- },
10097
- onSuccess: () => {
10098
- comboboxData.onSearchValueChange("");
10099
- setComboboxValue("");
10100
- }
10101
- }
10102
- );
10103
- };
10134
+ const { handleSuccess } = useRouteModal();
10135
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10104
10136
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10105
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10137
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10138
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10139
+ const matches = useMemo(() => {
10140
+ return matchSorter(preview.items, query2, {
10141
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
10142
+ });
10143
+ }, [preview.items, query2]);
10106
10144
  const onSubmit = async () => {
10107
10145
  setIsSubmitting(true);
10108
10146
  let requestSucceeded = false;
10109
10147
  await requestOrderEdit(void 0, {
10110
10148
  onError: (e) => {
10111
- toast.error(e.message);
10149
+ toast.error(`Failed to request order edit: ${e.message}`);
10112
10150
  },
10113
10151
  onSuccess: () => {
10114
10152
  requestSucceeded = true;
@@ -10120,7 +10158,7 @@ const PromotionForm = ({ preview }) => {
10120
10158
  }
10121
10159
  await confirmOrderEdit(void 0, {
10122
10160
  onError: (e) => {
10123
- toast.error(e.message);
10161
+ toast.error(`Failed to confirm order edit: ${e.message}`);
10124
10162
  },
10125
10163
  onSuccess: () => {
10126
10164
  handleSuccess();
@@ -10130,1079 +10168,903 @@ const PromotionForm = ({ preview }) => {
10130
10168
  }
10131
10169
  });
10132
10170
  };
10133
- if (isError) {
10134
- throw error;
10135
- }
10136
- return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10137
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10138
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10139
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10140
- /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10141
- /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10142
- ] }),
10143
- /* @__PURE__ */ jsx(
10144
- Combobox,
10145
- {
10146
- id: "promotion-combobox",
10147
- "aria-describedby": "promotion-combobox-hint",
10148
- isFetchingNextPage: comboboxData.isFetchingNextPage,
10149
- fetchNextPage: comboboxData.fetchNextPage,
10150
- options: comboboxData.options,
10151
- onSearchValueChange: comboboxData.onSearchValueChange,
10152
- searchValue: comboboxData.searchValue,
10153
- disabled: comboboxData.disabled || isAddingPromotions,
10154
- onChange: add,
10155
- value: comboboxValue
10171
+ const onKeyDown = useCallback(
10172
+ (e) => {
10173
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10174
+ if (modalContent || isSubmitting) {
10175
+ return;
10176
+ }
10177
+ onSubmit();
10178
+ }
10179
+ },
10180
+ [modalContent, isSubmitting, onSubmit]
10181
+ );
10182
+ useEffect(() => {
10183
+ document.addEventListener("keydown", onKeyDown);
10184
+ return () => {
10185
+ document.removeEventListener("keydown", onKeyDown);
10186
+ };
10187
+ }, [onKeyDown]);
10188
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10189
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10190
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10191
+ StackedFocusModal,
10192
+ {
10193
+ id: STACKED_MODAL_ID,
10194
+ onOpenChangeCallback: (open) => {
10195
+ if (!open) {
10196
+ setModalContent(null);
10156
10197
  }
10157
- )
10158
- ] }),
10159
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10160
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10161
- PromotionItem,
10162
- {
10163
- promotion,
10164
- orderId: preview.id,
10165
- isLoading: isPending
10166
10198
  },
10167
- promotion.id
10168
- )) })
10169
- ] }) }),
10170
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10171
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10199
+ children: [
10200
+ /* @__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: [
10201
+ /* @__PURE__ */ jsxs("div", { children: [
10202
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10203
+ /* @__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." }) })
10204
+ ] }),
10205
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10206
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10207
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10208
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10209
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10210
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10211
+ ] }),
10212
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10213
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10214
+ Input,
10215
+ {
10216
+ type: "search",
10217
+ placeholder: "Search items",
10218
+ value: searchValue,
10219
+ onChange: (e) => onSearchValueChange(e.target.value)
10220
+ }
10221
+ ) }),
10222
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10223
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10224
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10225
+ /* @__PURE__ */ jsx(
10226
+ StackedModalTrigger$1,
10227
+ {
10228
+ type: "add-items",
10229
+ setModalContent
10230
+ }
10231
+ ),
10232
+ /* @__PURE__ */ jsx(
10233
+ StackedModalTrigger$1,
10234
+ {
10235
+ type: "add-custom-item",
10236
+ setModalContent
10237
+ }
10238
+ )
10239
+ ] })
10240
+ ] })
10241
+ ] })
10242
+ ] }),
10243
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10244
+ /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
10245
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10246
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10247
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10248
+ /* @__PURE__ */ jsx("div", {})
10249
+ ] }) }),
10250
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10251
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10252
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10253
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10254
+ Item,
10255
+ {
10256
+ item,
10257
+ preview,
10258
+ currencyCode
10259
+ },
10260
+ item.id
10261
+ )) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10262
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10263
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10264
+ 'No items found for "',
10265
+ query2,
10266
+ '".'
10267
+ ] })
10268
+ ] }) })
10269
+ ] })
10270
+ ] }),
10271
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10272
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10273
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10274
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10275
+ Text,
10276
+ {
10277
+ size: "small",
10278
+ leading: "compact",
10279
+ className: "text-ui-fg-subtle",
10280
+ children: [
10281
+ itemCount,
10282
+ " ",
10283
+ itemCount === 1 ? "item" : "items"
10284
+ ]
10285
+ }
10286
+ ) }),
10287
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10288
+ ] })
10289
+ ] }) }),
10290
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10291
+ CustomItemForm,
10292
+ {
10293
+ orderId: preview.id,
10294
+ currencyCode
10295
+ }
10296
+ ) : null)
10297
+ ]
10298
+ }
10299
+ ) }),
10300
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10301
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10172
10302
  /* @__PURE__ */ jsx(
10173
10303
  Button,
10174
10304
  {
10175
10305
  size: "small",
10176
- type: "submit",
10177
- isLoading: isSubmitting || isAddingPromotions,
10306
+ type: "button",
10307
+ onClick: onSubmit,
10308
+ isLoading: isSubmitting,
10178
10309
  children: "Save"
10179
10310
  }
10180
10311
  )
10181
10312
  ] }) })
10182
10313
  ] });
10183
10314
  };
10184
- const PromotionItem = ({
10185
- promotion,
10186
- orderId,
10187
- isLoading
10188
- }) => {
10189
- var _a;
10190
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10191
- const onRemove = async () => {
10192
- removePromotions(
10193
- {
10194
- promo_codes: [promotion.code]
10195
- },
10196
- {
10197
- onError: (e) => {
10198
- toast.error(e.message);
10199
- }
10200
- }
10201
- );
10202
- };
10203
- const displayValue = getDisplayValue(promotion);
10204
- return /* @__PURE__ */ jsxs(
10205
- "div",
10206
- {
10207
- className: clx(
10208
- "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
10209
- {
10210
- "animate-pulse": isLoading
10211
- }
10212
- ),
10213
- children: [
10214
- /* @__PURE__ */ jsxs("div", { children: [
10215
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10216
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
10217
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
10218
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
10219
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
10220
- ] }),
10221
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10222
- ] })
10223
- ] }),
10224
- /* @__PURE__ */ jsx(
10225
- IconButton,
10226
- {
10227
- size: "small",
10228
- type: "button",
10229
- variant: "transparent",
10230
- onClick: onRemove,
10231
- isLoading: isPending || isLoading,
10232
- children: /* @__PURE__ */ jsx(XMark, {})
10233
- }
10234
- )
10235
- ]
10236
- },
10237
- promotion.id
10238
- );
10239
- };
10240
- function getDisplayValue(promotion) {
10241
- var _a, _b, _c, _d;
10242
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10243
- if (!value) {
10244
- return null;
10245
- }
10246
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10247
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10248
- if (!currency) {
10249
- return null;
10250
- }
10251
- return getLocaleAmount(value, currency);
10252
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10253
- return formatPercentage(value);
10254
- }
10255
- return null;
10256
- }
10257
- const formatter = new Intl.NumberFormat([], {
10258
- style: "percent",
10259
- minimumFractionDigits: 2
10260
- });
10261
- const formatPercentage = (value, isPercentageValue = false) => {
10262
- let val = value || 0;
10263
- if (!isPercentageValue) {
10264
- val = val / 100;
10265
- }
10266
- return formatter.format(val);
10267
- };
10268
- function getPromotionCodes(items, shippingMethods) {
10269
- const codes = /* @__PURE__ */ new Set();
10270
- for (const item of items) {
10271
- if (item.adjustments) {
10272
- for (const adjustment of item.adjustments) {
10273
- if (adjustment.code) {
10274
- codes.add(adjustment.code);
10275
- }
10276
- }
10277
- }
10278
- }
10279
- for (const shippingMethod of shippingMethods) {
10280
- if (shippingMethod.adjustments) {
10281
- for (const adjustment of shippingMethod.adjustments) {
10282
- if (adjustment.code) {
10283
- codes.add(adjustment.code);
10284
- }
10285
- }
10286
- }
10287
- }
10288
- return Array.from(codes);
10289
- }
10290
- const SalesChannel = () => {
10291
- const { id } = useParams();
10292
- const { draft_order, isPending, isError, error } = useDraftOrder(
10293
- id,
10294
- {
10295
- fields: "+sales_channel_id"
10296
- },
10297
- {
10298
- enabled: !!id
10299
- }
10300
- );
10301
- if (isError) {
10302
- throw error;
10315
+ const Item = ({ item, preview, currencyCode }) => {
10316
+ if (item.variant_id) {
10317
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10303
10318
  }
10304
- const ISrEADY = !!draft_order && !isPending;
10305
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10306
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10307
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
10308
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
10309
- ] }),
10310
- ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
10311
- ] });
10319
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10312
10320
  };
10313
- const SalesChannelForm = ({ order }) => {
10321
+ const VariantItem = ({ item, preview, currencyCode }) => {
10322
+ const [editing, setEditing] = useState(false);
10314
10323
  const form = useForm({
10315
10324
  defaultValues: {
10316
- sales_channel_id: order.sales_channel_id || ""
10325
+ quantity: item.quantity,
10326
+ unit_price: item.unit_price
10317
10327
  },
10318
- resolver: zodResolver(schema$3)
10328
+ resolver: zodResolver(variantItemSchema)
10319
10329
  });
10320
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10321
- const { handleSuccess } = useRouteModal();
10330
+ const actionId = useMemo(() => {
10331
+ var _a, _b;
10332
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10333
+ }, [item]);
10334
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10335
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10336
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10322
10337
  const onSubmit = form.handleSubmit(async (data) => {
10323
- await mutateAsync(
10338
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10339
+ setEditing(false);
10340
+ return;
10341
+ }
10342
+ if (!actionId) {
10343
+ await updateOriginalItem(
10344
+ {
10345
+ item_id: item.id,
10346
+ quantity: data.quantity,
10347
+ unit_price: convertNumber(data.unit_price)
10348
+ },
10349
+ {
10350
+ onSuccess: () => {
10351
+ setEditing(false);
10352
+ },
10353
+ onError: (e) => {
10354
+ toast.error(e.message);
10355
+ }
10356
+ }
10357
+ );
10358
+ return;
10359
+ }
10360
+ await updateActionItem(
10324
10361
  {
10325
- sales_channel_id: data.sales_channel_id
10362
+ action_id: actionId,
10363
+ quantity: data.quantity,
10364
+ unit_price: convertNumber(data.unit_price)
10326
10365
  },
10327
10366
  {
10328
10367
  onSuccess: () => {
10329
- toast.success("Sales channel updated");
10330
- handleSuccess();
10368
+ setEditing(false);
10331
10369
  },
10332
- onError: (error) => {
10333
- toast.error(error.message);
10370
+ onError: (e) => {
10371
+ toast.error(e.message);
10334
10372
  }
10335
10373
  }
10336
10374
  );
10337
10375
  });
10338
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10339
- KeyboundForm,
10340
- {
10341
- className: "flex flex-1 flex-col overflow-hidden",
10342
- onSubmit,
10343
- children: [
10344
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
10345
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10346
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10347
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10348
- ] }) })
10349
- ]
10350
- }
10351
- ) });
10352
- };
10353
- const SalesChannelField = ({ control, order }) => {
10354
- const salesChannels = useComboboxData({
10355
- queryFn: async (params) => {
10356
- return await sdk.admin.salesChannel.list(params);
10357
- },
10358
- queryKey: ["sales-channels"],
10359
- getOptions: (data) => {
10360
- return data.sales_channels.map((salesChannel) => ({
10361
- label: salesChannel.name,
10362
- value: salesChannel.id
10363
- }));
10364
- },
10365
- defaultValue: order.sales_channel_id || void 0
10366
- });
10367
- return /* @__PURE__ */ jsx(
10368
- Form$2.Field,
10369
- {
10370
- control,
10371
- name: "sales_channel_id",
10372
- render: ({ field }) => {
10373
- return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
10374
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
10375
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10376
- Combobox,
10376
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10377
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
10378
+ /* @__PURE__ */ jsx(
10379
+ Thumbnail,
10380
+ {
10381
+ thumbnail: item.thumbnail,
10382
+ alt: item.product_title ?? void 0
10383
+ }
10384
+ ),
10385
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10386
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10387
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10388
+ /* @__PURE__ */ jsxs(
10389
+ Text,
10377
10390
  {
10378
- options: salesChannels.options,
10379
- fetchNextPage: salesChannels.fetchNextPage,
10380
- isFetchingNextPage: salesChannels.isFetchingNextPage,
10381
- searchValue: salesChannels.searchValue,
10382
- onSearchValueChange: salesChannels.onSearchValueChange,
10383
- placeholder: "Select sales channel",
10384
- ...field
10391
+ size: "small",
10392
+ leading: "compact",
10393
+ className: "text-ui-fg-subtle",
10394
+ children: [
10395
+ "(",
10396
+ item.variant_title,
10397
+ ")"
10398
+ ]
10385
10399
  }
10386
- ) }),
10387
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10388
- ] });
10400
+ )
10401
+ ] }),
10402
+ /* @__PURE__ */ jsx(
10403
+ Text,
10404
+ {
10405
+ size: "small",
10406
+ leading: "compact",
10407
+ className: "text-ui-fg-subtle",
10408
+ children: item.variant_sku
10409
+ }
10410
+ )
10411
+ ] })
10412
+ ] }),
10413
+ editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
10414
+ Form$2.Field,
10415
+ {
10416
+ control: form.control,
10417
+ name: "quantity",
10418
+ render: ({ field }) => {
10419
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10420
+ }
10389
10421
  }
10390
- }
10391
- );
10392
- };
10393
- const schema$3 = z.object({
10394
- sales_channel_id: z.string().min(1)
10395
- });
10396
- function convertNumber(value) {
10397
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10398
- }
10399
- const STACKED_FOCUS_MODAL_ID = "shipping-form";
10400
- const Shipping = () => {
10401
- var _a;
10402
- const { id } = useParams();
10403
- const { order, isPending, isError, error } = useOrder(id, {
10404
- fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
10405
- });
10406
- const {
10407
- order: preview,
10408
- isPending: isPreviewPending,
10409
- isError: isPreviewError,
10410
- error: previewError
10411
- } = useOrderPreview(id);
10412
- useInitiateOrderEdit({ preview });
10413
- const { onCancel } = useCancelOrderEdit({ preview });
10414
- if (isError) {
10415
- throw error;
10416
- }
10417
- if (isPreviewError) {
10418
- throw previewError;
10419
- }
10420
- const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
10421
- const isReady = preview && !isPreviewPending && order && !isPending;
10422
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
10423
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10424
- /* @__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: [
10425
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
10426
- /* @__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." }) })
10427
- ] }) }) }),
10428
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
10429
- ] }) : isReady ? /* @__PURE__ */ jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxs("div", { children: [
10430
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
10431
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10432
- ] }) });
10422
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10423
+ editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
10424
+ Form$2.Field,
10425
+ {
10426
+ control: form.control,
10427
+ name: "unit_price",
10428
+ render: ({ field: { onChange, ...field } }) => {
10429
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10430
+ CurrencyInput,
10431
+ {
10432
+ ...field,
10433
+ symbol: getNativeSymbol(currencyCode),
10434
+ code: currencyCode,
10435
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10436
+ }
10437
+ ) }) });
10438
+ }
10439
+ }
10440
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10441
+ /* @__PURE__ */ jsx(
10442
+ IconButton,
10443
+ {
10444
+ type: "button",
10445
+ size: "small",
10446
+ onClick: editing ? onSubmit : () => {
10447
+ setEditing(true);
10448
+ },
10449
+ disabled: isPending,
10450
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10451
+ }
10452
+ )
10453
+ ] }) }) });
10433
10454
  };
10434
- const ShippingForm = ({ preview, order }) => {
10435
- var _a;
10436
- const { setIsOpen } = useStackedModal();
10437
- const [isSubmitting, setIsSubmitting] = useState(false);
10438
- const [data, setData] = useState(null);
10439
- const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
10440
- const { shipping_options } = useShippingOptions(
10441
- {
10442
- id: appliedShippingOptionIds,
10443
- fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
10455
+ const variantItemSchema = z.object({
10456
+ quantity: z.number(),
10457
+ unit_price: z.union([z.number(), z.string()])
10458
+ });
10459
+ const CustomItem = ({ item, preview, currencyCode }) => {
10460
+ const [editing, setEditing] = useState(false);
10461
+ const { quantity, unit_price, title } = item;
10462
+ const form = useForm({
10463
+ defaultValues: {
10464
+ title,
10465
+ quantity,
10466
+ unit_price
10444
10467
  },
10445
- {
10446
- enabled: appliedShippingOptionIds.length > 0
10447
- }
10448
- );
10449
- const uniqueShippingProfiles = useMemo(() => {
10450
- const profiles = /* @__PURE__ */ new Map();
10451
- getUniqueShippingProfiles(order.items).forEach((profile) => {
10452
- profiles.set(profile.id, profile);
10453
- });
10454
- shipping_options == null ? void 0 : shipping_options.forEach((option) => {
10455
- profiles.set(option.shipping_profile_id, option.shipping_profile);
10456
- });
10457
- return Array.from(profiles.values());
10458
- }, [order.items, shipping_options]);
10459
- const { handleSuccess } = useRouteModal();
10460
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10461
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10462
- const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
10463
- const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
10464
- const onSubmit = async () => {
10465
- setIsSubmitting(true);
10466
- let requestSucceeded = false;
10467
- await requestOrderEdit(void 0, {
10468
- onError: (e) => {
10469
- toast.error(`Failed to request order edit: ${e.message}`);
10470
- },
10471
- onSuccess: () => {
10472
- requestSucceeded = true;
10473
- }
10468
+ resolver: zodResolver(customItemSchema)
10469
+ });
10470
+ useEffect(() => {
10471
+ form.reset({
10472
+ title,
10473
+ quantity,
10474
+ unit_price
10474
10475
  });
10475
- if (!requestSucceeded) {
10476
- setIsSubmitting(false);
10476
+ }, [form, title, quantity, unit_price]);
10477
+ const actionId = useMemo(() => {
10478
+ var _a, _b;
10479
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10480
+ }, [item]);
10481
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10482
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10483
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10484
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10485
+ const onSubmit = form.handleSubmit(async (data) => {
10486
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10487
+ setEditing(false);
10477
10488
  return;
10478
10489
  }
10479
- await confirmOrderEdit(void 0, {
10480
- onError: (e) => {
10481
- toast.error(`Failed to confirm order edit: ${e.message}`);
10482
- },
10483
- onSuccess: () => {
10484
- handleSuccess();
10490
+ if (!actionId) {
10491
+ await updateOriginalItem(
10492
+ {
10493
+ item_id: item.id,
10494
+ quantity: data.quantity,
10495
+ unit_price: convertNumber(data.unit_price)
10496
+ },
10497
+ {
10498
+ onSuccess: () => {
10499
+ setEditing(false);
10500
+ },
10501
+ onError: (e) => {
10502
+ toast.error(e.message);
10503
+ }
10504
+ }
10505
+ );
10506
+ return;
10507
+ }
10508
+ if (data.quantity === 0) {
10509
+ await removeActionItem(actionId, {
10510
+ onSuccess: () => {
10511
+ setEditing(false);
10512
+ },
10513
+ onError: (e) => {
10514
+ toast.error(e.message);
10515
+ }
10516
+ });
10517
+ return;
10518
+ }
10519
+ await updateActionItem(
10520
+ {
10521
+ action_id: actionId,
10522
+ quantity: data.quantity,
10523
+ unit_price: convertNumber(data.unit_price)
10485
10524
  },
10486
- onSettled: () => {
10487
- setIsSubmitting(false);
10525
+ {
10526
+ onSuccess: () => {
10527
+ setEditing(false);
10528
+ },
10529
+ onError: (e) => {
10530
+ toast.error(e.message);
10531
+ }
10488
10532
  }
10489
- });
10490
- };
10491
- const onKeydown = useCallback(
10492
- (e) => {
10493
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10494
- if (data || isSubmitting) {
10495
- return;
10533
+ );
10534
+ });
10535
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10536
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10537
+ /* @__PURE__ */ jsx(
10538
+ Thumbnail,
10539
+ {
10540
+ thumbnail: item.thumbnail,
10541
+ alt: item.title ?? void 0
10542
+ }
10543
+ ),
10544
+ editing ? /* @__PURE__ */ jsx(
10545
+ Form$2.Field,
10546
+ {
10547
+ control: form.control,
10548
+ name: "title",
10549
+ render: ({ field }) => {
10550
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10551
+ }
10552
+ }
10553
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10554
+ ] }),
10555
+ editing ? /* @__PURE__ */ jsx(
10556
+ Form$2.Field,
10557
+ {
10558
+ control: form.control,
10559
+ name: "quantity",
10560
+ render: ({ field }) => {
10561
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10496
10562
  }
10497
- onSubmit();
10498
10563
  }
10499
- },
10500
- [data, isSubmitting, onSubmit]
10501
- );
10502
- useEffect(() => {
10503
- document.addEventListener("keydown", onKeydown);
10504
- return () => {
10505
- document.removeEventListener("keydown", onKeydown);
10506
- };
10507
- }, [onKeydown]);
10508
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10509
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10510
- /* @__PURE__ */ jsxs(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: [
10511
- /* @__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: [
10512
- /* @__PURE__ */ jsxs("div", { children: [
10513
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
10514
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose which shipping method(s) to use for the items in the order." }) })
10515
- ] }),
10516
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10517
- /* @__PURE__ */ jsx(Accordion.Root, { type: "multiple", children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle rounded-xl shadow-elevation-card-rest", children: [
10518
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 flex items-center justify-between", children: [
10519
- /* @__PURE__ */ jsx(
10520
- Text,
10521
- {
10522
- size: "xsmall",
10523
- weight: "plus",
10524
- className: "text-ui-fg-muted",
10525
- children: "Shipping profile"
10526
- }
10527
- ),
10528
- /* @__PURE__ */ jsx(
10529
- Text,
10530
- {
10531
- size: "xsmall",
10532
- weight: "plus",
10533
- className: "text-ui-fg-muted",
10534
- children: "Action"
10535
- }
10536
- )
10537
- ] }),
10538
- /* @__PURE__ */ jsx("div", { className: "px-[5px] pb-[5px]", children: uniqueShippingProfiles.map((profile) => {
10539
- var _a2, _b, _c, _d, _e, _f, _g;
10540
- const items = getItemsWithShippingProfile(
10541
- profile.id,
10542
- order.items
10543
- );
10544
- const hasItems = items.length > 0;
10545
- const shippingOption = shipping_options == null ? void 0 : shipping_options.find(
10546
- (option) => option.shipping_profile_id === profile.id
10547
- );
10548
- const shippingMethod = preview.shipping_methods.find(
10549
- (method) => method.shipping_option_id === (shippingOption == null ? void 0 : shippingOption.id)
10550
- );
10551
- const addShippingMethodAction = (_a2 = shippingMethod == null ? void 0 : shippingMethod.actions) == null ? void 0 : _a2.find(
10552
- (action) => action.action === "SHIPPING_ADD"
10553
- );
10554
- return /* @__PURE__ */ jsxs(
10555
- Accordion.Item,
10556
- {
10557
- value: profile.id,
10558
- className: "bg-ui-bg-base shadow-elevation-card-rest rounded-lg",
10559
- children: [
10560
- /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 flex items-center justify-between gap-3", children: [
10561
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 w-full overflow-hidden", children: [
10562
- /* @__PURE__ */ jsx(Accordion.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
10563
- IconButton,
10564
- {
10565
- size: "2xsmall",
10566
- variant: "transparent",
10567
- className: "group/trigger",
10568
- disabled: !hasItems,
10569
- children: /* @__PURE__ */ jsx(TriangleRightMini, { className: "group-data-[state=open]/trigger:rotate-90 transition-transform" })
10570
- }
10571
- ) }),
10572
- !shippingOption ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10573
- /* @__PURE__ */ jsx("div", { className: "size-7 rounded-md shadow-borders-base flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "size-6 rounded bg-ui-bg-component-hover flex items-center justify-center", children: /* @__PURE__ */ jsx(Shopping, { className: "text-ui-fg-subtle" }) }) }),
10574
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1", children: [
10575
- /* @__PURE__ */ jsx(
10576
- Text,
10577
- {
10578
- size: "small",
10579
- weight: "plus",
10580
- leading: "compact",
10581
- children: profile.name
10582
- }
10583
- ),
10584
- /* @__PURE__ */ jsxs(
10585
- Text,
10586
- {
10587
- size: "small",
10588
- leading: "compact",
10589
- className: "text-ui-fg-subtle",
10590
- children: [
10591
- items.length,
10592
- " ",
10593
- pluralize(items.length, "items", "item")
10594
- ]
10595
- }
10596
- )
10597
- ] })
10598
- ] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[5px] max-sm:flex-col max-sm:items-start flex-1 w-full overflow-hidden", children: [
10599
- /* @__PURE__ */ jsx(
10600
- Tooltip,
10601
- {
10602
- content: /* @__PURE__ */ jsx("ul", { children: items.map((item) => {
10603
- var _a3, _b2, _c2;
10604
- return /* @__PURE__ */ jsx(
10605
- "li",
10606
- {
10607
- children: `${item.quantity}x ${(_b2 = (_a3 = item.variant) == null ? void 0 : _a3.product) == null ? void 0 : _b2.title} (${(_c2 = item.variant) == null ? void 0 : _c2.title})`
10608
- },
10609
- item.id
10610
- );
10611
- }) }),
10612
- children: /* @__PURE__ */ jsxs(
10613
- Badge,
10614
- {
10615
- className: "flex items-center gap-x-[3px] overflow-hidden cursor-default",
10616
- size: "xsmall",
10617
- children: [
10618
- /* @__PURE__ */ jsx(Shopping, { className: "shrink-0" }),
10619
- /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
10620
- items.reduce(
10621
- (acc, item) => acc + item.quantity,
10622
- 0
10623
- ),
10624
- "x",
10625
- " ",
10626
- pluralize(items.length, "items", "item")
10627
- ] })
10628
- ]
10629
- }
10630
- )
10631
- }
10632
- ),
10633
- /* @__PURE__ */ jsx(
10634
- Tooltip,
10635
- {
10636
- content: (_d = (_c = (_b = shippingOption.service_zone) == null ? void 0 : _b.fulfillment_set) == null ? void 0 : _c.location) == null ? void 0 : _d.name,
10637
- children: /* @__PURE__ */ jsxs(
10638
- Badge,
10639
- {
10640
- className: "flex items-center gap-x-[3px] overflow-hidden cursor-default",
10641
- size: "xsmall",
10642
- children: [
10643
- /* @__PURE__ */ jsx(Buildings, { className: "shrink-0" }),
10644
- /* @__PURE__ */ jsx("span", { className: "truncate", children: (_g = (_f = (_e = shippingOption.service_zone) == null ? void 0 : _e.fulfillment_set) == null ? void 0 : _f.location) == null ? void 0 : _g.name })
10645
- ]
10646
- }
10647
- )
10648
- }
10649
- ),
10650
- /* @__PURE__ */ jsx(Tooltip, { content: shippingOption.name, children: /* @__PURE__ */ jsxs(
10651
- Badge,
10652
- {
10653
- className: "flex items-center gap-x-[3px] overflow-hidden cursor-default",
10654
- size: "xsmall",
10655
- children: [
10656
- /* @__PURE__ */ jsx(TruckFast, { className: "shrink-0" }),
10657
- /* @__PURE__ */ jsx("span", { className: "truncate", children: shippingOption.name })
10658
- ]
10659
- }
10660
- ) })
10661
- ] })
10662
- ] }),
10663
- shippingOption ? /* @__PURE__ */ jsx(
10664
- ActionMenu,
10665
- {
10666
- groups: [
10667
- {
10668
- actions: [
10669
- hasItems ? {
10670
- label: "Edit shipping option",
10671
- icon: /* @__PURE__ */ jsx(Channels, {}),
10672
- onClick: () => {
10673
- setIsOpen(
10674
- STACKED_FOCUS_MODAL_ID,
10675
- true
10676
- );
10677
- setData({
10678
- shippingProfileId: profile.id,
10679
- shippingOption,
10680
- shippingMethod
10681
- });
10682
- }
10683
- } : void 0,
10684
- {
10685
- label: "Remove shipping option",
10686
- icon: /* @__PURE__ */ jsx(Trash, {}),
10687
- onClick: () => {
10688
- if (shippingMethod) {
10689
- if (addShippingMethodAction) {
10690
- removeActionShippingMethod(
10691
- addShippingMethodAction.id
10692
- );
10693
- } else {
10694
- removeShippingMethod(
10695
- shippingMethod.id
10696
- );
10697
- }
10698
- }
10699
- }
10700
- }
10701
- ].filter(Boolean)
10702
- }
10703
- ]
10704
- }
10705
- ) : /* @__PURE__ */ jsx(
10706
- StackedModalTrigger$1,
10707
- {
10708
- shippingProfileId: profile.id,
10709
- shippingOption,
10710
- shippingMethod,
10711
- setData,
10712
- children: "Add shipping option"
10713
- }
10714
- )
10715
- ] }),
10716
- /* @__PURE__ */ jsxs(Accordion.Content, { children: [
10717
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10718
- items.map((item, idx) => {
10719
- var _a3, _b2, _c2, _d2, _e2;
10720
- return /* @__PURE__ */ jsxs("div", { children: [
10721
- /* @__PURE__ */ jsxs(
10722
- "div",
10723
- {
10724
- className: "px-3 flex items-center gap-x-3",
10725
- children: [
10726
- /* @__PURE__ */ jsx("div", { className: "w-5 h-[56px] flex flex-col justify-center items-center", children: /* @__PURE__ */ jsx(
10727
- Divider,
10728
- {
10729
- variant: "dashed",
10730
- orientation: "vertical"
10731
- }
10732
- ) }),
10733
- /* @__PURE__ */ jsxs("div", { className: "py-2 flex items-center gap-x-3", children: [
10734
- /* @__PURE__ */ jsx("div", { className: "size-7 flex items-center justify-center tabular-nums", children: /* @__PURE__ */ jsxs(
10735
- Text,
10736
- {
10737
- size: "small",
10738
- leading: "compact",
10739
- className: "text-ui-fg-subtle",
10740
- children: [
10741
- item.quantity,
10742
- "x"
10743
- ]
10744
- }
10745
- ) }),
10746
- /* @__PURE__ */ jsx(Thumbnail, { thumbnail: item.thumbnail }),
10747
- /* @__PURE__ */ jsxs("div", { children: [
10748
- /* @__PURE__ */ jsxs(
10749
- Text,
10750
- {
10751
- size: "small",
10752
- leading: "compact",
10753
- weight: "plus",
10754
- children: [
10755
- (_b2 = (_a3 = item.variant) == null ? void 0 : _a3.product) == null ? void 0 : _b2.title,
10756
- " (",
10757
- (_c2 = item.variant) == null ? void 0 : _c2.title,
10758
- ")"
10759
- ]
10760
- }
10761
- ),
10762
- /* @__PURE__ */ jsx(
10763
- Text,
10764
- {
10765
- size: "small",
10766
- leading: "compact",
10767
- className: "text-ui-fg-subtle",
10768
- children: (_e2 = (_d2 = item.variant) == null ? void 0 : _d2.options) == null ? void 0 : _e2.map((option) => option.value).join(" · ")
10769
- }
10770
- )
10771
- ] })
10772
- ] })
10773
- ]
10774
- },
10775
- item.id
10776
- ),
10777
- idx !== items.length - 1 && /* @__PURE__ */ jsx(Divider, { variant: "dashed" })
10778
- ] }, item.id);
10779
- })
10780
- ] })
10781
- ]
10782
- },
10783
- profile.id
10784
- );
10785
- }) })
10564
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10565
+ editing ? /* @__PURE__ */ jsx(
10566
+ Form$2.Field,
10567
+ {
10568
+ control: form.control,
10569
+ name: "unit_price",
10570
+ render: ({ field: { onChange, ...field } }) => {
10571
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10572
+ CurrencyInput,
10573
+ {
10574
+ ...field,
10575
+ symbol: getNativeSymbol(currencyCode),
10576
+ code: currencyCode,
10577
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10578
+ }
10579
+ ) }) });
10580
+ }
10581
+ }
10582
+ ) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10583
+ /* @__PURE__ */ jsx(
10584
+ IconButton,
10585
+ {
10586
+ type: "button",
10587
+ size: "small",
10588
+ onClick: editing ? onSubmit : () => {
10589
+ setEditing(true);
10590
+ },
10591
+ disabled: isPending,
10592
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10593
+ }
10594
+ )
10595
+ ] }) }) });
10596
+ };
10597
+ const StackedModalTrigger$1 = ({
10598
+ type,
10599
+ setModalContent
10600
+ }) => {
10601
+ const { setIsOpen } = useStackedModal();
10602
+ const onClick = useCallback(() => {
10603
+ setModalContent(type);
10604
+ setIsOpen(STACKED_MODAL_ID, true);
10605
+ }, [setModalContent, setIsOpen, type]);
10606
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10607
+ };
10608
+ const VARIANT_PREFIX = "items";
10609
+ const LIMIT = 50;
10610
+ const ExistingItemsForm = ({ orderId, items }) => {
10611
+ const { setIsOpen } = useStackedModal();
10612
+ const [rowSelection, setRowSelection] = useState(
10613
+ items.reduce((acc, item) => {
10614
+ acc[item.variant_id] = true;
10615
+ return acc;
10616
+ }, {})
10617
+ );
10618
+ useEffect(() => {
10619
+ setRowSelection(
10620
+ items.reduce((acc, item) => {
10621
+ if (item.variant_id) {
10622
+ acc[item.variant_id] = true;
10623
+ }
10624
+ return acc;
10625
+ }, {})
10626
+ );
10627
+ }, [items]);
10628
+ const { q, order, offset } = useQueryParams(
10629
+ ["q", "order", "offset"],
10630
+ VARIANT_PREFIX
10631
+ );
10632
+ const { variants, count, isPending, isError, error } = useProductVariants(
10633
+ {
10634
+ q,
10635
+ order,
10636
+ offset: offset ? parseInt(offset) : void 0,
10637
+ limit: LIMIT
10638
+ },
10639
+ {
10640
+ placeholderData: keepPreviousData
10641
+ }
10642
+ );
10643
+ const columns = useColumns();
10644
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10645
+ const onSubmit = async () => {
10646
+ const ids = Object.keys(rowSelection).filter(
10647
+ (id) => !items.find((i) => i.variant_id === id)
10648
+ );
10649
+ await mutateAsync(
10650
+ {
10651
+ items: ids.map((id) => ({
10652
+ variant_id: id,
10653
+ quantity: 1
10654
+ }))
10655
+ },
10656
+ {
10657
+ onSuccess: () => {
10658
+ setRowSelection({});
10659
+ setIsOpen(STACKED_MODAL_ID, false);
10660
+ },
10661
+ onError: (e) => {
10662
+ toast.error(e.message);
10663
+ }
10664
+ }
10665
+ );
10666
+ };
10667
+ if (isError) {
10668
+ throw error;
10669
+ }
10670
+ return /* @__PURE__ */ jsxs(
10671
+ StackedFocusModal.Content,
10672
+ {
10673
+ onOpenAutoFocus: (e) => {
10674
+ e.preventDefault();
10675
+ const searchInput = document.querySelector(
10676
+ "[data-modal-id='modal-search-input']"
10677
+ );
10678
+ if (searchInput) {
10679
+ searchInput.focus();
10680
+ }
10681
+ },
10682
+ children: [
10683
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10684
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10685
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10686
+ ] }),
10687
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10688
+ DataTable,
10689
+ {
10690
+ data: variants,
10691
+ columns,
10692
+ isLoading: isPending,
10693
+ getRowId: (row) => row.id,
10694
+ rowCount: count,
10695
+ prefix: VARIANT_PREFIX,
10696
+ layout: "fill",
10697
+ rowSelection: {
10698
+ state: rowSelection,
10699
+ onRowSelectionChange: setRowSelection,
10700
+ enableRowSelection: (row) => {
10701
+ return !items.find((i) => i.variant_id === row.original.id);
10702
+ }
10703
+ },
10704
+ autoFocusSearch: true
10705
+ }
10706
+ ) }),
10707
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10708
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10709
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10786
10710
  ] }) })
10787
- ] }) }),
10711
+ ]
10712
+ }
10713
+ );
10714
+ };
10715
+ const columnHelper = createDataTableColumnHelper();
10716
+ const useColumns = () => {
10717
+ return useMemo(() => {
10718
+ return [
10719
+ columnHelper.select(),
10720
+ columnHelper.accessor("product.title", {
10721
+ header: "Product",
10722
+ cell: ({ row }) => {
10723
+ var _a, _b, _c;
10724
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10725
+ /* @__PURE__ */ jsx(
10726
+ Thumbnail,
10727
+ {
10728
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10729
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
10730
+ }
10731
+ ),
10732
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10733
+ ] });
10734
+ },
10735
+ enableSorting: true
10736
+ }),
10737
+ columnHelper.accessor("title", {
10738
+ header: "Variant",
10739
+ enableSorting: true
10740
+ }),
10741
+ columnHelper.accessor("sku", {
10742
+ header: "SKU",
10743
+ cell: ({ getValue }) => {
10744
+ return getValue() ?? "-";
10745
+ },
10746
+ enableSorting: true
10747
+ }),
10748
+ columnHelper.accessor("updated_at", {
10749
+ header: "Updated",
10750
+ cell: ({ getValue }) => {
10751
+ return /* @__PURE__ */ jsx(
10752
+ Tooltip,
10753
+ {
10754
+ content: getFullDate({ date: getValue(), includeTime: true }),
10755
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10756
+ }
10757
+ );
10758
+ },
10759
+ enableSorting: true,
10760
+ sortAscLabel: "Oldest first",
10761
+ sortDescLabel: "Newest first"
10762
+ }),
10763
+ columnHelper.accessor("created_at", {
10764
+ header: "Created",
10765
+ cell: ({ getValue }) => {
10766
+ return /* @__PURE__ */ jsx(
10767
+ Tooltip,
10768
+ {
10769
+ content: getFullDate({ date: getValue(), includeTime: true }),
10770
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10771
+ }
10772
+ );
10773
+ },
10774
+ enableSorting: true,
10775
+ sortAscLabel: "Oldest first",
10776
+ sortDescLabel: "Newest first"
10777
+ })
10778
+ ];
10779
+ }, []);
10780
+ };
10781
+ const CustomItemForm = ({ orderId, currencyCode }) => {
10782
+ const { setIsOpen } = useStackedModal();
10783
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10784
+ const form = useForm({
10785
+ defaultValues: {
10786
+ title: "",
10787
+ quantity: 1,
10788
+ unit_price: ""
10789
+ },
10790
+ resolver: zodResolver(customItemSchema)
10791
+ });
10792
+ const onSubmit = form.handleSubmit(async (data) => {
10793
+ await addItems(
10794
+ {
10795
+ items: [
10796
+ {
10797
+ title: data.title,
10798
+ quantity: data.quantity,
10799
+ unit_price: convertNumber(data.unit_price)
10800
+ }
10801
+ ]
10802
+ },
10803
+ {
10804
+ onSuccess: () => {
10805
+ setIsOpen(STACKED_MODAL_ID, false);
10806
+ },
10807
+ onError: (e) => {
10808
+ toast.error(e.message);
10809
+ }
10810
+ }
10811
+ );
10812
+ });
10813
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10814
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10815
+ /* @__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: [
10816
+ /* @__PURE__ */ jsxs("div", { children: [
10817
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10818
+ /* @__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." }) })
10819
+ ] }),
10820
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10788
10821
  /* @__PURE__ */ jsx(
10789
- StackedFocusModal,
10822
+ Form$2.Field,
10790
10823
  {
10791
- id: STACKED_FOCUS_MODAL_ID,
10792
- onOpenChangeCallback: (open) => {
10793
- if (!open) {
10794
- setData(null);
10795
- }
10796
- return open;
10797
- },
10798
- children: data && /* @__PURE__ */ jsx(ShippingProfileForm, { data, order, preview })
10824
+ control: form.control,
10825
+ name: "title",
10826
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10827
+ /* @__PURE__ */ jsxs("div", { children: [
10828
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10829
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10830
+ ] }),
10831
+ /* @__PURE__ */ jsxs("div", { children: [
10832
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10833
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10834
+ ] })
10835
+ ] }) })
10836
+ }
10837
+ ),
10838
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10839
+ /* @__PURE__ */ jsx(
10840
+ Form$2.Field,
10841
+ {
10842
+ control: form.control,
10843
+ name: "unit_price",
10844
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10845
+ /* @__PURE__ */ jsxs("div", { children: [
10846
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10847
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10848
+ ] }),
10849
+ /* @__PURE__ */ jsxs("div", { children: [
10850
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10851
+ CurrencyInput,
10852
+ {
10853
+ symbol: getNativeSymbol(currencyCode),
10854
+ code: currencyCode,
10855
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10856
+ ...field
10857
+ }
10858
+ ) }),
10859
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10860
+ ] })
10861
+ ] }) })
10799
10862
  }
10800
- )
10801
- ] }),
10802
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-x-2", children: [
10803
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10863
+ ),
10864
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10804
10865
  /* @__PURE__ */ jsx(
10805
- Button,
10866
+ Form$2.Field,
10806
10867
  {
10807
- size: "small",
10808
- type: "button",
10809
- isLoading: isSubmitting,
10810
- onClick: onSubmit,
10811
- children: "Save"
10868
+ control: form.control,
10869
+ name: "quantity",
10870
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10871
+ /* @__PURE__ */ jsxs("div", { children: [
10872
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10873
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10874
+ ] }),
10875
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 w-full", children: [
10876
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10877
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10878
+ ] })
10879
+ ] }) })
10812
10880
  }
10813
10881
  )
10882
+ ] }) }) }),
10883
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10884
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10885
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10814
10886
  ] }) })
10815
- ] });
10887
+ ] }) }) });
10816
10888
  };
10817
- const StackedModalTrigger$1 = ({
10818
- shippingProfileId,
10819
- shippingOption,
10820
- shippingMethod,
10821
- setData,
10822
- children
10823
- }) => {
10824
- const { setIsOpen, getIsOpen } = useStackedModal();
10825
- const isOpen = getIsOpen(STACKED_FOCUS_MODAL_ID);
10826
- const onToggle = () => {
10827
- if (isOpen) {
10828
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
10829
- setData(null);
10830
- } else {
10831
- setIsOpen(STACKED_FOCUS_MODAL_ID, true);
10832
- setData({
10833
- shippingProfileId,
10834
- shippingOption,
10835
- shippingMethod
10836
- });
10837
- }
10838
- };
10839
- return /* @__PURE__ */ jsx(
10840
- Button,
10841
- {
10842
- size: "small",
10843
- variant: "secondary",
10844
- onClick: onToggle,
10845
- className: "text-ui-fg-primary shrink-0",
10846
- children
10847
- }
10848
- );
10889
+ const customItemSchema = z.object({
10890
+ title: z.string().min(1),
10891
+ quantity: z.number(),
10892
+ unit_price: z.union([z.number(), z.string()])
10893
+ });
10894
+ const Email = () => {
10895
+ const { id } = useParams();
10896
+ const { order, isPending, isError, error } = useOrder(id, {
10897
+ fields: "+email"
10898
+ });
10899
+ if (isError) {
10900
+ throw error;
10901
+ }
10902
+ const isReady = !isPending && !!order;
10903
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10904
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10905
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
10906
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
10907
+ ] }),
10908
+ isReady && /* @__PURE__ */ jsx(EmailForm, { order })
10909
+ ] });
10849
10910
  };
10850
- const ShippingProfileForm = ({
10851
- data,
10852
- order,
10853
- preview
10854
- }) => {
10855
- var _a, _b, _c, _d, _e, _f;
10856
- const { setIsOpen } = useStackedModal();
10911
+ const EmailForm = ({ order }) => {
10857
10912
  const form = useForm({
10858
- resolver: zodResolver(shippingMethodSchema),
10859
10913
  defaultValues: {
10860
- location_id: (_d = (_c = (_b = (_a = data.shippingOption) == null ? void 0 : _a.service_zone) == null ? void 0 : _b.fulfillment_set) == null ? void 0 : _c.location) == null ? void 0 : _d.id,
10861
- shipping_option_id: (_e = data.shippingOption) == null ? void 0 : _e.id,
10862
- custom_amount: (_f = data.shippingMethod) == null ? void 0 : _f.amount
10863
- }
10914
+ email: order.email ?? ""
10915
+ },
10916
+ resolver: zodResolver(schema$3)
10864
10917
  });
10865
- const { mutateAsync: addShippingMethod, isPending } = useDraftOrderAddShippingMethod(order.id);
10866
- const {
10867
- mutateAsync: updateShippingMethod,
10868
- isPending: isUpdatingShippingMethod
10869
- } = useDraftOrderUpdateShippingMethod(order.id);
10870
- const onSubmit = form.handleSubmit(async (values) => {
10871
- if (isEqual(values, form.formState.defaultValues)) {
10872
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
10873
- return;
10874
- }
10875
- if (data.shippingMethod) {
10876
- await updateShippingMethod(
10877
- {
10878
- method_id: data.shippingMethod.id,
10879
- shipping_option_id: values.shipping_option_id,
10880
- custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
10881
- },
10882
- {
10883
- onError: (e) => {
10884
- toast.error(e.message);
10885
- },
10886
- onSuccess: () => {
10887
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
10888
- }
10889
- }
10890
- );
10891
- return;
10892
- }
10893
- await addShippingMethod(
10894
- {
10895
- shipping_option_id: values.shipping_option_id,
10896
- custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
10897
- },
10918
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10919
+ const { handleSuccess } = useRouteModal();
10920
+ const onSubmit = form.handleSubmit(async (data) => {
10921
+ await mutateAsync(
10922
+ { email: data.email },
10898
10923
  {
10899
- onError: (e) => {
10900
- toast.error(e.message);
10901
- },
10902
10924
  onSuccess: () => {
10903
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
10925
+ handleSuccess();
10926
+ },
10927
+ onError: (error) => {
10928
+ toast.error(error.message);
10904
10929
  }
10905
10930
  }
10906
10931
  );
10907
10932
  });
10908
- return /* @__PURE__ */ jsx(StackedFocusModal.Content, { children: /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxs(
10933
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10909
10934
  KeyboundForm,
10910
10935
  {
10911
- className: "flex h-full flex-col overflow-hidden",
10936
+ className: "flex flex-1 flex-col overflow-hidden",
10912
10937
  onSubmit,
10913
10938
  children: [
10914
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10915
- /* @__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 py-16 px-6", children: [
10916
- /* @__PURE__ */ jsxs("div", { children: [
10917
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
10918
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a shipping method for the selected shipping profile. You can see the items that will be shipped using this method in the preview below." }) })
10919
- ] }),
10920
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10921
- /* @__PURE__ */ jsx(
10922
- LocationField,
10923
- {
10924
- control: form.control,
10925
- setValue: form.setValue
10926
- }
10927
- ),
10928
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10929
- /* @__PURE__ */ jsx(
10930
- ShippingOptionField,
10931
- {
10932
- shippingProfileId: data.shippingProfileId,
10933
- preview,
10934
- control: form.control
10935
- }
10936
- ),
10937
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10938
- /* @__PURE__ */ jsx(
10939
- CustomAmountField,
10940
- {
10941
- control: form.control,
10942
- currencyCode: order.currency_code
10943
- }
10944
- ),
10945
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10946
- /* @__PURE__ */ jsx(
10947
- ItemsPreview,
10948
- {
10949
- order,
10950
- shippingProfileId: data.shippingProfileId
10951
- }
10952
- )
10953
- ] }) }) }),
10954
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-x-2", children: [
10955
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10956
- /* @__PURE__ */ jsx(
10957
- Button,
10958
- {
10959
- size: "small",
10960
- type: "submit",
10961
- isLoading: isPending || isUpdatingShippingMethod,
10962
- children: data.shippingMethod ? "Update" : "Add"
10963
- }
10964
- )
10939
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
10940
+ Form$2.Field,
10941
+ {
10942
+ control: form.control,
10943
+ name: "email",
10944
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
10945
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
10946
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10947
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10948
+ ] })
10949
+ }
10950
+ ) }),
10951
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10952
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10953
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10965
10954
  ] }) })
10966
10955
  ]
10967
10956
  }
10968
- ) }) });
10957
+ ) });
10969
10958
  };
10970
- const shippingMethodSchema = z.object({
10971
- location_id: z.string(),
10972
- shipping_option_id: z.string(),
10973
- custom_amount: z.union([z.number(), z.string()]).optional()
10959
+ const schema$3 = z.object({
10960
+ email: z.string().email()
10974
10961
  });
10975
- const ItemsPreview = ({ order, shippingProfileId }) => {
10976
- const matches = order.items.filter(
10977
- (item) => {
10978
- var _a, _b, _c;
10979
- return ((_c = (_b = (_a = item.variant) == null ? void 0 : _a.product) == null ? void 0 : _b.shipping_profile) == null ? void 0 : _c.id) === shippingProfileId;
10962
+ const SalesChannel = () => {
10963
+ const { id } = useParams();
10964
+ const { draft_order, isPending, isError, error } = useDraftOrder(
10965
+ id,
10966
+ {
10967
+ fields: "+sales_channel_id"
10968
+ },
10969
+ {
10970
+ enabled: !!id
10980
10971
  }
10981
10972
  );
10982
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10983
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 items-center gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10984
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items to ship" }),
10985
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Items with the selected shipping profile." })
10986
- ] }) }),
10987
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10988
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 px-4 py-2 text-ui-fg-muted", children: [
10989
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10990
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) })
10991
- ] }),
10992
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxs(
10993
- "div",
10994
- {
10995
- className: "grid grid-cols-2 gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center",
10996
- children: [
10997
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10998
- /* @__PURE__ */ jsx(
10999
- Thumbnail,
11000
- {
11001
- thumbnail: item.thumbnail,
11002
- alt: item.product_title ?? void 0
11003
- }
11004
- ),
11005
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11006
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
11007
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
11008
- /* @__PURE__ */ jsxs(
11009
- Text,
11010
- {
11011
- size: "small",
11012
- leading: "compact",
11013
- className: "text-ui-fg-subtle",
11014
- children: [
11015
- "(",
11016
- item.variant_title,
11017
- ")"
11018
- ]
11019
- }
11020
- )
11021
- ] }),
11022
- /* @__PURE__ */ jsx(
11023
- Text,
11024
- {
11025
- size: "small",
11026
- leading: "compact",
11027
- className: "text-ui-fg-subtle",
11028
- children: item.variant_sku
11029
- }
11030
- )
11031
- ] })
11032
- ] }),
11033
- /* @__PURE__ */ jsxs(
11034
- Text,
11035
- {
11036
- size: "small",
11037
- leading: "compact",
11038
- className: "text-ui-fg-subtle",
11039
- children: [
11040
- item.quantity,
11041
- "x"
11042
- ]
11043
- }
11044
- )
11045
- ]
11046
- },
11047
- item.id
11048
- )) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
11049
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
11050
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
11051
- 'No items found for "',
11052
- query,
11053
- '".'
11054
- ] })
11055
- ] }) })
11056
- ] })
10973
+ if (isError) {
10974
+ throw error;
10975
+ }
10976
+ const ISrEADY = !!draft_order && !isPending;
10977
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10978
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10979
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
10980
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
10981
+ ] }),
10982
+ ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
11057
10983
  ] });
11058
10984
  };
11059
- const LocationField = ({ control, setValue }) => {
11060
- const locations = useComboboxData({
11061
- queryKey: ["locations"],
11062
- queryFn: async (params) => {
11063
- return await sdk.admin.stockLocation.list(params);
10985
+ const SalesChannelForm = ({ order }) => {
10986
+ const form = useForm({
10987
+ defaultValues: {
10988
+ sales_channel_id: order.sales_channel_id || ""
11064
10989
  },
11065
- getOptions: (data) => {
11066
- return data.stock_locations.map((location) => ({
11067
- label: location.name,
11068
- value: location.id
11069
- }));
11070
- }
10990
+ resolver: zodResolver(schema$2)
11071
10991
  });
11072
- return /* @__PURE__ */ jsx(
11073
- Form$2.Field,
11074
- {
11075
- control,
11076
- name: "location_id",
11077
- render: ({ field: { onChange, ...field } }) => {
11078
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11079
- /* @__PURE__ */ jsxs("div", { children: [
11080
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Location" }),
11081
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Choose where you want to ship the items from." })
11082
- ] }),
11083
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11084
- Combobox,
11085
- {
11086
- options: locations.options,
11087
- fetchNextPage: locations.fetchNextPage,
11088
- isFetchingNextPage: locations.isFetchingNextPage,
11089
- searchValue: locations.searchValue,
11090
- onSearchValueChange: locations.onSearchValueChange,
11091
- placeholder: "Select location",
11092
- onChange: (value) => {
11093
- setValue("shipping_option_id", "", {
11094
- shouldDirty: true,
11095
- shouldTouch: true
11096
- });
11097
- onChange(value);
11098
- },
11099
- ...field
11100
- }
11101
- ) })
11102
- ] }) });
10992
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
10993
+ const { handleSuccess } = useRouteModal();
10994
+ const onSubmit = form.handleSubmit(async (data) => {
10995
+ await mutateAsync(
10996
+ {
10997
+ sales_channel_id: data.sales_channel_id
10998
+ },
10999
+ {
11000
+ onSuccess: () => {
11001
+ toast.success("Sales channel updated");
11002
+ handleSuccess();
11003
+ },
11004
+ onError: (error) => {
11005
+ toast.error(error.message);
11006
+ }
11103
11007
  }
11008
+ );
11009
+ });
11010
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11011
+ KeyboundForm,
11012
+ {
11013
+ className: "flex flex-1 flex-col overflow-hidden",
11014
+ onSubmit,
11015
+ children: [
11016
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
11017
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11018
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11019
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11020
+ ] }) })
11021
+ ]
11104
11022
  }
11105
- );
11023
+ ) });
11106
11024
  };
11107
- const ShippingOptionField = ({
11108
- shippingProfileId,
11109
- preview,
11110
- control
11111
- }) => {
11112
- var _a;
11113
- const locationId = useWatch({ control, name: "location_id" });
11114
- const shippingOptions = useComboboxData({
11115
- queryKey: ["shipping_options", locationId, shippingProfileId],
11025
+ const SalesChannelField = ({ control, order }) => {
11026
+ const salesChannels = useComboboxData({
11116
11027
  queryFn: async (params) => {
11117
- return await sdk.admin.shippingOption.list({
11118
- ...params,
11119
- stock_location_id: locationId,
11120
- shipping_profile_id: shippingProfileId
11121
- });
11028
+ return await sdk.admin.salesChannel.list(params);
11122
11029
  },
11030
+ queryKey: ["sales-channels"],
11123
11031
  getOptions: (data) => {
11124
- return data.shipping_options.map((option) => {
11125
- var _a2;
11126
- if ((_a2 = option.rules) == null ? void 0 : _a2.find(
11127
- (r) => r.attribute === "is_return" && r.value === "true"
11128
- )) {
11129
- return void 0;
11130
- }
11131
- return {
11132
- label: option.name,
11133
- value: option.id
11134
- };
11135
- }).filter(Boolean);
11032
+ return data.sales_channels.map((salesChannel) => ({
11033
+ label: salesChannel.name,
11034
+ value: salesChannel.id
11035
+ }));
11136
11036
  },
11137
- enabled: !!locationId && !!shippingProfileId,
11138
- defaultValue: ((_a = preview.shipping_methods[0]) == null ? void 0 : _a.shipping_option_id) || void 0
11037
+ defaultValue: order.sales_channel_id || void 0
11139
11038
  });
11140
- const tooltipContent = !locationId && !shippingProfileId ? "Choose a location and shipping profile first." : !locationId ? "Choose a location first." : "Choose a shipping profile first.";
11141
11039
  return /* @__PURE__ */ jsx(
11142
11040
  Form$2.Field,
11143
11041
  {
11144
11042
  control,
11145
- name: "shipping_option_id",
11043
+ name: "sales_channel_id",
11146
11044
  render: ({ field }) => {
11147
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11148
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11149
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Shipping option" }),
11150
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Choose the shipping option to use." })
11151
- ] }),
11152
- /* @__PURE__ */ jsx(
11153
- ConditionalTooltip,
11154
- {
11155
- content: tooltipContent,
11156
- showTooltip: !locationId || !shippingProfileId,
11157
- children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11158
- Combobox,
11159
- {
11160
- options: shippingOptions.options,
11161
- fetchNextPage: shippingOptions.fetchNextPage,
11162
- isFetchingNextPage: shippingOptions.isFetchingNextPage,
11163
- searchValue: shippingOptions.searchValue,
11164
- onSearchValueChange: shippingOptions.onSearchValueChange,
11165
- placeholder: "Select shipping option",
11166
- ...field,
11167
- disabled: !locationId || !shippingProfileId
11168
- }
11169
- ) }) })
11170
- }
11171
- )
11172
- ] }) });
11173
- }
11174
- }
11175
- );
11176
- };
11177
- const CustomAmountField = ({
11178
- control,
11179
- currencyCode
11180
- }) => {
11181
- return /* @__PURE__ */ jsx(
11182
- Form$2.Field,
11183
- {
11184
- control,
11185
- name: "custom_amount",
11186
- render: ({ field: { onChange, ...field } }) => {
11187
- return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11188
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11189
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Custom amount" }),
11190
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
11191
- ] }),
11045
+ return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11046
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
11192
11047
  /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11193
- CurrencyInput,
11194
- {
11195
- ...field,
11196
- onValueChange: (value) => onChange(value),
11197
- symbol: getNativeSymbol(currencyCode),
11198
- code: currencyCode
11048
+ Combobox,
11049
+ {
11050
+ options: salesChannels.options,
11051
+ fetchNextPage: salesChannels.fetchNextPage,
11052
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
11053
+ searchValue: salesChannels.searchValue,
11054
+ onSearchValueChange: salesChannels.onSearchValueChange,
11055
+ placeholder: "Select sales channel",
11056
+ ...field
11199
11057
  }
11200
- ) })
11058
+ ) }),
11059
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11201
11060
  ] });
11202
11061
  }
11203
11062
  }
11204
11063
  );
11205
11064
  };
11065
+ const schema$2 = z.object({
11066
+ sales_channel_id: z.string().min(1)
11067
+ });
11206
11068
  const InlineTip = forwardRef(
11207
11069
  ({ variant = "tip", label, className, children, ...props }, ref) => {
11208
11070
  const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
@@ -11480,78 +11342,355 @@ const PlaceholderInner = () => {
11480
11342
  ] }) })
11481
11343
  ] });
11482
11344
  };
11483
- const EDITABLE_TYPES = ["string", "number", "boolean"];
11484
- function getDefaultValues(metadata) {
11485
- if (!metadata || !Object.keys(metadata).length) {
11486
- return [
11345
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
11346
+ function getDefaultValues(metadata) {
11347
+ if (!metadata || !Object.keys(metadata).length) {
11348
+ return [
11349
+ {
11350
+ key: "",
11351
+ value: "",
11352
+ disabled: false
11353
+ }
11354
+ ];
11355
+ }
11356
+ return Object.entries(metadata).map(([key, value]) => {
11357
+ if (!EDITABLE_TYPES.includes(typeof value)) {
11358
+ return {
11359
+ key,
11360
+ value,
11361
+ disabled: true
11362
+ };
11363
+ }
11364
+ let stringValue = value;
11365
+ if (typeof value !== "string") {
11366
+ stringValue = JSON.stringify(value);
11367
+ }
11368
+ return {
11369
+ key,
11370
+ value: stringValue,
11371
+ original_key: key
11372
+ };
11373
+ });
11374
+ }
11375
+ function parseValues(values) {
11376
+ const metadata = values.metadata;
11377
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11378
+ if (isEmpty) {
11379
+ return null;
11380
+ }
11381
+ const update = {};
11382
+ metadata.forEach((field) => {
11383
+ let key = field.key;
11384
+ let value = field.value;
11385
+ const disabled = field.disabled;
11386
+ if (!key || !value) {
11387
+ return;
11388
+ }
11389
+ if (disabled) {
11390
+ update[key] = value;
11391
+ return;
11392
+ }
11393
+ key = key.trim();
11394
+ value = value.trim();
11395
+ if (value === "true") {
11396
+ update[key] = true;
11397
+ } else if (value === "false") {
11398
+ update[key] = false;
11399
+ } else {
11400
+ const parsedNumber = parseFloat(value);
11401
+ if (!isNaN(parsedNumber)) {
11402
+ update[key] = parsedNumber;
11403
+ } else {
11404
+ update[key] = value;
11405
+ }
11406
+ }
11407
+ });
11408
+ return update;
11409
+ }
11410
+ function getHasUneditableRows(metadata) {
11411
+ if (!metadata) {
11412
+ return false;
11413
+ }
11414
+ return Object.values(metadata).some(
11415
+ (value) => !EDITABLE_TYPES.includes(typeof value)
11416
+ );
11417
+ }
11418
+ const PROMOTION_QUERY_KEY = "promotions";
11419
+ const promotionsQueryKeys = {
11420
+ list: (query2) => [
11421
+ PROMOTION_QUERY_KEY,
11422
+ query2 ? query2 : void 0
11423
+ ],
11424
+ detail: (id, query2) => [
11425
+ PROMOTION_QUERY_KEY,
11426
+ id,
11427
+ query2 ? query2 : void 0
11428
+ ]
11429
+ };
11430
+ const usePromotions = (query2, options) => {
11431
+ const { data, ...rest } = useQuery({
11432
+ queryKey: promotionsQueryKeys.list(query2),
11433
+ queryFn: async () => sdk.admin.promotion.list(query2),
11434
+ ...options
11435
+ });
11436
+ return { ...data, ...rest };
11437
+ };
11438
+ const Promotions = () => {
11439
+ const { id } = useParams();
11440
+ const {
11441
+ order: preview,
11442
+ isError: isPreviewError,
11443
+ error: previewError
11444
+ } = useOrderPreview(id, void 0);
11445
+ useInitiateOrderEdit({ preview });
11446
+ const { onCancel } = useCancelOrderEdit({ preview });
11447
+ if (isPreviewError) {
11448
+ throw previewError;
11449
+ }
11450
+ const isReady = !!preview;
11451
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
11452
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
11453
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
11454
+ ] });
11455
+ };
11456
+ const PromotionForm = ({ preview }) => {
11457
+ const { items, shipping_methods } = preview;
11458
+ const [isSubmitting, setIsSubmitting] = useState(false);
11459
+ const [comboboxValue, setComboboxValue] = useState("");
11460
+ const { handleSuccess } = useRouteModal();
11461
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11462
+ const promoCodes = getPromotionCodes(items, shipping_methods);
11463
+ const { promotions, isPending, isError, error } = usePromotions(
11464
+ {
11465
+ code: promoCodes
11466
+ },
11467
+ {
11468
+ enabled: !!promoCodes.length
11469
+ }
11470
+ );
11471
+ const comboboxData = useComboboxData({
11472
+ queryKey: ["promotions", "combobox", promoCodes],
11473
+ queryFn: async (params) => {
11474
+ return await sdk.admin.promotion.list({
11475
+ ...params,
11476
+ code: {
11477
+ $nin: promoCodes
11478
+ }
11479
+ });
11480
+ },
11481
+ getOptions: (data) => {
11482
+ return data.promotions.map((promotion) => ({
11483
+ label: promotion.code,
11484
+ value: promotion.code
11485
+ }));
11486
+ }
11487
+ });
11488
+ const add = async (value) => {
11489
+ if (!value) {
11490
+ return;
11491
+ }
11492
+ addPromotions(
11493
+ {
11494
+ promo_codes: [value]
11495
+ },
11496
+ {
11497
+ onError: (e) => {
11498
+ toast.error(e.message);
11499
+ comboboxData.onSearchValueChange("");
11500
+ setComboboxValue("");
11501
+ },
11502
+ onSuccess: () => {
11503
+ comboboxData.onSearchValueChange("");
11504
+ setComboboxValue("");
11505
+ }
11506
+ }
11507
+ );
11508
+ };
11509
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11510
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
11511
+ const onSubmit = async () => {
11512
+ setIsSubmitting(true);
11513
+ let requestSucceeded = false;
11514
+ await requestOrderEdit(void 0, {
11515
+ onError: (e) => {
11516
+ toast.error(e.message);
11517
+ },
11518
+ onSuccess: () => {
11519
+ requestSucceeded = true;
11520
+ }
11521
+ });
11522
+ if (!requestSucceeded) {
11523
+ setIsSubmitting(false);
11524
+ return;
11525
+ }
11526
+ await confirmOrderEdit(void 0, {
11527
+ onError: (e) => {
11528
+ toast.error(e.message);
11529
+ },
11530
+ onSuccess: () => {
11531
+ handleSuccess();
11532
+ },
11533
+ onSettled: () => {
11534
+ setIsSubmitting(false);
11535
+ }
11536
+ });
11537
+ };
11538
+ if (isError) {
11539
+ throw error;
11540
+ }
11541
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11542
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
11543
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
11544
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11545
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
11546
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11547
+ ] }),
11548
+ /* @__PURE__ */ jsx(
11549
+ Combobox,
11550
+ {
11551
+ id: "promotion-combobox",
11552
+ "aria-describedby": "promotion-combobox-hint",
11553
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
11554
+ fetchNextPage: comboboxData.fetchNextPage,
11555
+ options: comboboxData.options,
11556
+ onSearchValueChange: comboboxData.onSearchValueChange,
11557
+ searchValue: comboboxData.searchValue,
11558
+ disabled: comboboxData.disabled || isAddingPromotions,
11559
+ onChange: add,
11560
+ value: comboboxValue
11561
+ }
11562
+ )
11563
+ ] }),
11564
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11565
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
11566
+ PromotionItem,
11567
+ {
11568
+ promotion,
11569
+ orderId: preview.id,
11570
+ isLoading: isPending
11571
+ },
11572
+ promotion.id
11573
+ )) })
11574
+ ] }) }),
11575
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11576
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11577
+ /* @__PURE__ */ jsx(
11578
+ Button,
11579
+ {
11580
+ size: "small",
11581
+ type: "submit",
11582
+ isLoading: isSubmitting || isAddingPromotions,
11583
+ children: "Save"
11584
+ }
11585
+ )
11586
+ ] }) })
11587
+ ] });
11588
+ };
11589
+ const PromotionItem = ({
11590
+ promotion,
11591
+ orderId,
11592
+ isLoading
11593
+ }) => {
11594
+ var _a;
11595
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
11596
+ const onRemove = async () => {
11597
+ removePromotions(
11487
11598
  {
11488
- key: "",
11489
- value: "",
11490
- disabled: false
11599
+ promo_codes: [promotion.code]
11600
+ },
11601
+ {
11602
+ onError: (e) => {
11603
+ toast.error(e.message);
11604
+ }
11491
11605
  }
11492
- ];
11606
+ );
11607
+ };
11608
+ const displayValue = getDisplayValue(promotion);
11609
+ return /* @__PURE__ */ jsxs(
11610
+ "div",
11611
+ {
11612
+ className: clx(
11613
+ "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
11614
+ {
11615
+ "animate-pulse": isLoading
11616
+ }
11617
+ ),
11618
+ children: [
11619
+ /* @__PURE__ */ jsxs("div", { children: [
11620
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11621
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
11622
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11623
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11624
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11625
+ ] }),
11626
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11627
+ ] })
11628
+ ] }),
11629
+ /* @__PURE__ */ jsx(
11630
+ IconButton,
11631
+ {
11632
+ size: "small",
11633
+ type: "button",
11634
+ variant: "transparent",
11635
+ onClick: onRemove,
11636
+ isLoading: isPending || isLoading,
11637
+ children: /* @__PURE__ */ jsx(XMark, {})
11638
+ }
11639
+ )
11640
+ ]
11641
+ },
11642
+ promotion.id
11643
+ );
11644
+ };
11645
+ function getDisplayValue(promotion) {
11646
+ var _a, _b, _c, _d;
11647
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11648
+ if (!value) {
11649
+ return null;
11493
11650
  }
11494
- return Object.entries(metadata).map(([key, value]) => {
11495
- if (!EDITABLE_TYPES.includes(typeof value)) {
11496
- return {
11497
- key,
11498
- value,
11499
- disabled: true
11500
- };
11501
- }
11502
- let stringValue = value;
11503
- if (typeof value !== "string") {
11504
- stringValue = JSON.stringify(value);
11651
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11652
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11653
+ if (!currency) {
11654
+ return null;
11505
11655
  }
11506
- return {
11507
- key,
11508
- value: stringValue,
11509
- original_key: key
11510
- };
11511
- });
11656
+ return getLocaleAmount(value, currency);
11657
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11658
+ return formatPercentage(value);
11659
+ }
11660
+ return null;
11512
11661
  }
11513
- function parseValues(values) {
11514
- const metadata = values.metadata;
11515
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11516
- if (isEmpty) {
11517
- return null;
11662
+ const formatter = new Intl.NumberFormat([], {
11663
+ style: "percent",
11664
+ minimumFractionDigits: 2
11665
+ });
11666
+ const formatPercentage = (value, isPercentageValue = false) => {
11667
+ let val = value || 0;
11668
+ if (!isPercentageValue) {
11669
+ val = val / 100;
11518
11670
  }
11519
- const update = {};
11520
- metadata.forEach((field) => {
11521
- let key = field.key;
11522
- let value = field.value;
11523
- const disabled = field.disabled;
11524
- if (!key || !value) {
11525
- return;
11526
- }
11527
- if (disabled) {
11528
- update[key] = value;
11529
- return;
11671
+ return formatter.format(val);
11672
+ };
11673
+ function getPromotionCodes(items, shippingMethods) {
11674
+ const codes = /* @__PURE__ */ new Set();
11675
+ for (const item of items) {
11676
+ if (item.adjustments) {
11677
+ for (const adjustment of item.adjustments) {
11678
+ if (adjustment.code) {
11679
+ codes.add(adjustment.code);
11680
+ }
11681
+ }
11530
11682
  }
11531
- key = key.trim();
11532
- value = value.trim();
11533
- if (value === "true") {
11534
- update[key] = true;
11535
- } else if (value === "false") {
11536
- update[key] = false;
11537
- } else {
11538
- const parsedNumber = parseFloat(value);
11539
- if (!isNaN(parsedNumber)) {
11540
- update[key] = parsedNumber;
11541
- } else {
11542
- update[key] = value;
11683
+ }
11684
+ for (const shippingMethod of shippingMethods) {
11685
+ if (shippingMethod.adjustments) {
11686
+ for (const adjustment of shippingMethod.adjustments) {
11687
+ if (adjustment.code) {
11688
+ codes.add(adjustment.code);
11689
+ }
11543
11690
  }
11544
11691
  }
11545
- });
11546
- return update;
11547
- }
11548
- function getHasUneditableRows(metadata) {
11549
- if (!metadata) {
11550
- return false;
11551
11692
  }
11552
- return Object.values(metadata).some(
11553
- (value) => !EDITABLE_TYPES.includes(typeof value)
11554
- );
11693
+ return Array.from(codes);
11555
11694
  }
11556
11695
  const ShippingAddress = () => {
11557
11696
  const { id } = useParams();
@@ -11585,7 +11724,7 @@ const ShippingAddressForm = ({ order }) => {
11585
11724
  postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
11586
11725
  phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
11587
11726
  },
11588
- resolver: zodResolver(schema$2)
11727
+ resolver: zodResolver(schema$1)
11589
11728
  });
11590
11729
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11591
11730
  const { handleSuccess } = useRouteModal();
@@ -11755,7 +11894,7 @@ const ShippingAddressForm = ({ order }) => {
11755
11894
  }
11756
11895
  ) });
11757
11896
  };
11758
- const schema$2 = addressSchema;
11897
+ const schema$1 = addressSchema;
11759
11898
  const TransferOwnership = () => {
11760
11899
  const { id } = useParams();
11761
11900
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -11779,7 +11918,7 @@ const TransferOwnershipForm = ({ order }) => {
11779
11918
  defaultValues: {
11780
11919
  customer_id: order.customer_id || ""
11781
11920
  },
11782
- resolver: zodResolver(schema$1)
11921
+ resolver: zodResolver(schema)
11783
11922
  });
11784
11923
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11785
11924
  const { handleSuccess } = useRouteModal();
@@ -12183,201 +12322,69 @@ const Illustration = () => {
12183
12322
  "rect",
12184
12323
  {
12185
12324
  width: "12",
12186
- height: "12",
12187
- fill: "white",
12188
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12189
- }
12190
- ) }),
12191
- /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12192
- "rect",
12193
- {
12194
- width: "12",
12195
- height: "12",
12196
- fill: "white",
12197
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12198
- }
12199
- ) }),
12200
- /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12201
- "rect",
12202
- {
12203
- width: "12",
12204
- height: "12",
12205
- fill: "white",
12206
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12207
- }
12208
- ) }),
12209
- /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
12210
- "rect",
12211
- {
12212
- width: "12",
12213
- height: "12",
12214
- fill: "white",
12215
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12216
- }
12217
- ) }),
12218
- /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
12219
- "rect",
12220
- {
12221
- width: "12",
12222
- height: "12",
12223
- fill: "white",
12224
- transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
12225
- }
12226
- ) })
12227
- ] })
12228
- ]
12229
- }
12230
- );
12231
- };
12232
- const schema$1 = z.object({
12233
- customer_id: z.string().min(1)
12234
- });
12235
- const NumberInput = forwardRef(
12236
- ({
12237
- value,
12238
- onChange,
12239
- size = "base",
12240
- min = 0,
12241
- max = 100,
12242
- step = 1,
12243
- className,
12244
- disabled,
12245
- ...props
12246
- }, ref) => {
12247
- const handleChange = (event) => {
12248
- const newValue = event.target.value === "" ? min : Number(event.target.value);
12249
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
12250
- onChange(newValue);
12251
- }
12252
- };
12253
- const handleIncrement = () => {
12254
- const newValue = value + step;
12255
- if (max === void 0 || newValue <= max) {
12256
- onChange(newValue);
12257
- }
12258
- };
12259
- const handleDecrement = () => {
12260
- const newValue = value - step;
12261
- if (min === void 0 || newValue >= min) {
12262
- onChange(newValue);
12263
- }
12264
- };
12265
- return /* @__PURE__ */ jsxs(
12266
- "div",
12267
- {
12268
- className: clx(
12269
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
12270
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
12271
- {
12272
- "h-7": size === "small",
12273
- "h-8": size === "base"
12274
- },
12275
- className
12276
- ),
12277
- children: [
12278
- /* @__PURE__ */ jsx(
12279
- "input",
12325
+ height: "12",
12326
+ fill: "white",
12327
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 148.75 80.6541)"
12328
+ }
12329
+ ) }),
12330
+ /* @__PURE__ */ jsx("clipPath", { id: "clip2_20915_38670", children: /* @__PURE__ */ jsx(
12331
+ "rect",
12280
12332
  {
12281
- ref,
12282
- type: "number",
12283
- value,
12284
- onChange: handleChange,
12285
- min,
12286
- max,
12287
- step,
12288
- className: clx(
12289
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
12290
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
12291
- "placeholder:text-ui-fg-muted"
12292
- ),
12293
- ...props
12333
+ width: "12",
12334
+ height: "12",
12335
+ fill: "white",
12336
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 159.141 86.6575)"
12294
12337
  }
12295
- ),
12296
- /* @__PURE__ */ jsxs(
12297
- "button",
12338
+ ) }),
12339
+ /* @__PURE__ */ jsx("clipPath", { id: "clip3_20915_38670", children: /* @__PURE__ */ jsx(
12340
+ "rect",
12298
12341
  {
12299
- className: clx(
12300
- "flex items-center justify-center outline-none transition-fg",
12301
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
12302
- "focus:bg-ui-bg-field-component-hover",
12303
- "hover:bg-ui-bg-field-component-hover",
12304
- {
12305
- "size-7": size === "small",
12306
- "size-8": size === "base"
12307
- }
12308
- ),
12309
- type: "button",
12310
- onClick: handleDecrement,
12311
- disabled: min !== void 0 && value <= min || disabled,
12312
- children: [
12313
- /* @__PURE__ */ jsx(Minus, {}),
12314
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
12315
- ]
12342
+ width: "12",
12343
+ height: "12",
12344
+ fill: "white",
12345
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 120.928 84.4561)"
12316
12346
  }
12317
- ),
12318
- /* @__PURE__ */ jsxs(
12319
- "button",
12347
+ ) }),
12348
+ /* @__PURE__ */ jsx("clipPath", { id: "clip4_20915_38670", children: /* @__PURE__ */ jsx(
12349
+ "rect",
12320
12350
  {
12321
- className: clx(
12322
- "flex items-center justify-center outline-none transition-fg",
12323
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
12324
- "focus:bg-ui-bg-field-hover",
12325
- "hover:bg-ui-bg-field-hover",
12326
- {
12327
- "size-7": size === "small",
12328
- "size-8": size === "base"
12329
- }
12330
- ),
12331
- type: "button",
12332
- onClick: handleIncrement,
12333
- disabled: max !== void 0 && value >= max || disabled,
12334
- children: [
12335
- /* @__PURE__ */ jsx(Plus, {}),
12336
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
12337
- ]
12351
+ width: "12",
12352
+ height: "12",
12353
+ fill: "white",
12354
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 131.318 90.4594)"
12338
12355
  }
12339
- )
12340
- ]
12341
- }
12342
- );
12343
- }
12344
- );
12345
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
12346
- const productVariantsQueryKeys = {
12347
- list: (query2) => [
12348
- PRODUCT_VARIANTS_QUERY_KEY,
12349
- query2 ? query2 : void 0
12350
- ]
12351
- };
12352
- const useProductVariants = (query2, options) => {
12353
- const { data, ...rest } = useQuery({
12354
- queryKey: productVariantsQueryKeys.list(query2),
12355
- queryFn: async () => await sdk.admin.productVariant.list(query2),
12356
- ...options
12357
- });
12358
- return { ...data, ...rest };
12356
+ ) }),
12357
+ /* @__PURE__ */ jsx("clipPath", { id: "clip5_20915_38670", children: /* @__PURE__ */ jsx(
12358
+ "rect",
12359
+ {
12360
+ width: "12",
12361
+ height: "12",
12362
+ fill: "white",
12363
+ transform: "matrix(0.865865 0.500278 -0.871576 0.490261 141.709 96.4627)"
12364
+ }
12365
+ ) })
12366
+ ] })
12367
+ ]
12368
+ }
12369
+ );
12359
12370
  };
12360
- const STACKED_MODAL_ID = "items_stacked_modal";
12361
- const Items = () => {
12371
+ const schema = z.object({
12372
+ customer_id: z.string().min(1)
12373
+ });
12374
+ const STACKED_FOCUS_MODAL_ID = "shipping-form";
12375
+ const Shipping = () => {
12376
+ var _a;
12362
12377
  const { id } = useParams();
12378
+ const { order, isPending, isError, error } = useOrder(id, {
12379
+ fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
12380
+ });
12363
12381
  const {
12364
12382
  order: preview,
12365
12383
  isPending: isPreviewPending,
12366
12384
  isError: isPreviewError,
12367
12385
  error: previewError
12368
- } = useOrderPreview(id, void 0, {
12369
- placeholderData: keepPreviousData
12370
- });
12386
+ } = useOrderPreview(id);
12371
12387
  useInitiateOrderEdit({ preview });
12372
- const { draft_order, isPending, isError, error } = useDraftOrder(
12373
- id,
12374
- {
12375
- fields: "currency_code"
12376
- },
12377
- {
12378
- enabled: !!id
12379
- }
12380
- );
12381
12388
  const { onCancel } = useCancelOrderEdit({ preview });
12382
12389
  if (isError) {
12383
12390
  throw error;
@@ -12385,28 +12392,50 @@ const Items = () => {
12385
12392
  if (isPreviewError) {
12386
12393
  throw previewError;
12387
12394
  }
12388
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
12389
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
12390
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
12395
+ const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
12396
+ const isReady = preview && !isPreviewPending && order && !isPending;
12397
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
12398
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
12399
+ /* @__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: [
12400
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
12401
+ /* @__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." }) })
12402
+ ] }) }) }),
12403
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
12404
+ ] }) : isReady ? /* @__PURE__ */ jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxs("div", { children: [
12405
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
12391
12406
  /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
12392
12407
  ] }) });
12393
12408
  };
12394
- const ItemsForm = ({ preview, currencyCode }) => {
12409
+ const ShippingForm = ({ preview, order }) => {
12395
12410
  var _a;
12411
+ const { setIsOpen } = useStackedModal();
12396
12412
  const [isSubmitting, setIsSubmitting] = useState(false);
12397
- const [modalContent, setModalContent] = useState(
12398
- null
12413
+ const [data, setData] = useState(null);
12414
+ const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
12415
+ const { shipping_options } = useShippingOptions(
12416
+ {
12417
+ id: appliedShippingOptionIds,
12418
+ fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
12419
+ },
12420
+ {
12421
+ enabled: appliedShippingOptionIds.length > 0
12422
+ }
12399
12423
  );
12424
+ const uniqueShippingProfiles = useMemo(() => {
12425
+ const profiles = /* @__PURE__ */ new Map();
12426
+ getUniqueShippingProfiles(order.items).forEach((profile) => {
12427
+ profiles.set(profile.id, profile);
12428
+ });
12429
+ shipping_options == null ? void 0 : shipping_options.forEach((option) => {
12430
+ profiles.set(option.shipping_profile_id, option.shipping_profile);
12431
+ });
12432
+ return Array.from(profiles.values());
12433
+ }, [order.items, shipping_options]);
12400
12434
  const { handleSuccess } = useRouteModal();
12401
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
12402
12435
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
12403
12436
  const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
12404
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
12405
- const matches = useMemo(() => {
12406
- return matchSorter(preview.items, query2, {
12407
- keys: ["product_title", "variant_title", "variant_sku", "title"]
12408
- });
12409
- }, [preview.items, query2]);
12437
+ const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
12438
+ const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
12410
12439
  const onSubmit = async () => {
12411
12440
  setIsSubmitting(true);
12412
12441
  let requestSucceeded = false;
@@ -12434,750 +12463,721 @@ const ItemsForm = ({ preview, currencyCode }) => {
12434
12463
  }
12435
12464
  });
12436
12465
  };
12437
- const onKeyDown = useCallback(
12466
+ const onKeydown = useCallback(
12438
12467
  (e) => {
12439
12468
  if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
12440
- if (modalContent || isSubmitting) {
12469
+ if (data || isSubmitting) {
12441
12470
  return;
12442
12471
  }
12443
12472
  onSubmit();
12444
12473
  }
12445
12474
  },
12446
- [modalContent, isSubmitting, onSubmit]
12475
+ [data, isSubmitting, onSubmit]
12447
12476
  );
12448
12477
  useEffect(() => {
12449
- document.addEventListener("keydown", onKeyDown);
12478
+ document.addEventListener("keydown", onKeydown);
12450
12479
  return () => {
12451
- document.removeEventListener("keydown", onKeyDown);
12480
+ document.removeEventListener("keydown", onKeydown);
12452
12481
  };
12453
- }, [onKeyDown]);
12482
+ }, [onKeydown]);
12454
12483
  return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
12455
12484
  /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
12456
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
12457
- StackedFocusModal,
12458
- {
12459
- id: STACKED_MODAL_ID,
12460
- onOpenChangeCallback: (open) => {
12461
- if (!open) {
12462
- setModalContent(null);
12463
- }
12464
- },
12465
- children: [
12466
- /* @__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: [
12467
- /* @__PURE__ */ jsxs("div", { children: [
12468
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
12469
- /* @__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." }) })
12470
- ] }),
12471
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12472
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
12473
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
12474
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12475
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
12476
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
12477
- ] }),
12478
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
12479
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
12480
- Input,
12481
- {
12482
- type: "search",
12483
- placeholder: "Search items",
12484
- value: searchValue,
12485
- onChange: (e) => onSearchValueChange(e.target.value)
12486
- }
12487
- ) }),
12488
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
12489
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
12490
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
12491
- /* @__PURE__ */ jsx(
12492
- StackedModalTrigger,
12493
- {
12494
- type: "add-items",
12495
- setModalContent
12496
- }
12497
- ),
12498
- /* @__PURE__ */ jsx(
12499
- StackedModalTrigger,
12485
+ /* @__PURE__ */ jsxs(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: [
12486
+ /* @__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: [
12487
+ /* @__PURE__ */ jsxs("div", { children: [
12488
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
12489
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose which shipping method(s) to use for the items in the order." }) })
12490
+ ] }),
12491
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12492
+ /* @__PURE__ */ jsx(Accordion.Root, { type: "multiple", children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle rounded-xl shadow-elevation-card-rest", children: [
12493
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 flex items-center justify-between", children: [
12494
+ /* @__PURE__ */ jsx(
12495
+ Text,
12496
+ {
12497
+ size: "xsmall",
12498
+ weight: "plus",
12499
+ className: "text-ui-fg-muted",
12500
+ children: "Shipping profile"
12501
+ }
12502
+ ),
12503
+ /* @__PURE__ */ jsx(
12504
+ Text,
12505
+ {
12506
+ size: "xsmall",
12507
+ weight: "plus",
12508
+ className: "text-ui-fg-muted",
12509
+ children: "Action"
12510
+ }
12511
+ )
12512
+ ] }),
12513
+ /* @__PURE__ */ jsx("div", { className: "px-[5px] pb-[5px]", children: uniqueShippingProfiles.map((profile) => {
12514
+ var _a2, _b, _c, _d, _e, _f, _g;
12515
+ const items = getItemsWithShippingProfile(
12516
+ profile.id,
12517
+ order.items
12518
+ );
12519
+ const hasItems = items.length > 0;
12520
+ const shippingOption = shipping_options == null ? void 0 : shipping_options.find(
12521
+ (option) => option.shipping_profile_id === profile.id
12522
+ );
12523
+ const shippingMethod = preview.shipping_methods.find(
12524
+ (method) => method.shipping_option_id === (shippingOption == null ? void 0 : shippingOption.id)
12525
+ );
12526
+ const addShippingMethodAction = (_a2 = shippingMethod == null ? void 0 : shippingMethod.actions) == null ? void 0 : _a2.find(
12527
+ (action) => action.action === "SHIPPING_ADD"
12528
+ );
12529
+ return /* @__PURE__ */ jsxs(
12530
+ Accordion.Item,
12531
+ {
12532
+ value: profile.id,
12533
+ className: "bg-ui-bg-base shadow-elevation-card-rest rounded-lg",
12534
+ children: [
12535
+ /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 flex items-center justify-between gap-3", children: [
12536
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 w-full overflow-hidden", children: [
12537
+ /* @__PURE__ */ jsx(Accordion.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
12538
+ IconButton,
12500
12539
  {
12501
- type: "add-custom-item",
12502
- setModalContent
12540
+ size: "2xsmall",
12541
+ variant: "transparent",
12542
+ className: "group/trigger",
12543
+ disabled: !hasItems,
12544
+ children: /* @__PURE__ */ jsx(TriangleRightMini, { className: "group-data-[state=open]/trigger:rotate-90 transition-transform" })
12503
12545
  }
12504
- )
12505
- ] })
12506
- ] })
12507
- ] })
12508
- ] }),
12509
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
12510
- /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
12511
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
12512
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
12513
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
12514
- /* @__PURE__ */ jsx("div", {})
12515
- ] }) }),
12516
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
12517
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
12518
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
12519
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
12520
- Item,
12521
- {
12522
- item,
12523
- preview,
12524
- currencyCode
12525
- },
12526
- item.id
12527
- )) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
12528
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
12529
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
12530
- 'No items found for "',
12531
- query2,
12532
- '".'
12546
+ ) }),
12547
+ !shippingOption ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
12548
+ /* @__PURE__ */ jsx("div", { className: "size-7 rounded-md shadow-borders-base flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "size-6 rounded bg-ui-bg-component-hover flex items-center justify-center", children: /* @__PURE__ */ jsx(Shopping, { className: "text-ui-fg-subtle" }) }) }),
12549
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1", children: [
12550
+ /* @__PURE__ */ jsx(
12551
+ Text,
12552
+ {
12553
+ size: "small",
12554
+ weight: "plus",
12555
+ leading: "compact",
12556
+ children: profile.name
12557
+ }
12558
+ ),
12559
+ /* @__PURE__ */ jsxs(
12560
+ Text,
12561
+ {
12562
+ size: "small",
12563
+ leading: "compact",
12564
+ className: "text-ui-fg-subtle",
12565
+ children: [
12566
+ items.length,
12567
+ " ",
12568
+ pluralize(items.length, "items", "item")
12569
+ ]
12570
+ }
12571
+ )
12572
+ ] })
12573
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[5px] max-sm:flex-col max-sm:items-start flex-1 w-full overflow-hidden", children: [
12574
+ /* @__PURE__ */ jsx(
12575
+ Tooltip,
12576
+ {
12577
+ content: /* @__PURE__ */ jsx("ul", { children: items.map((item) => {
12578
+ var _a3, _b2, _c2;
12579
+ return /* @__PURE__ */ jsx(
12580
+ "li",
12581
+ {
12582
+ children: `${item.quantity}x ${(_b2 = (_a3 = item.variant) == null ? void 0 : _a3.product) == null ? void 0 : _b2.title} (${(_c2 = item.variant) == null ? void 0 : _c2.title})`
12583
+ },
12584
+ item.id
12585
+ );
12586
+ }) }),
12587
+ children: /* @__PURE__ */ jsxs(
12588
+ Badge,
12589
+ {
12590
+ className: "flex items-center gap-x-[3px] overflow-hidden cursor-default",
12591
+ size: "xsmall",
12592
+ children: [
12593
+ /* @__PURE__ */ jsx(Shopping, { className: "shrink-0" }),
12594
+ /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
12595
+ items.reduce(
12596
+ (acc, item) => acc + item.quantity,
12597
+ 0
12598
+ ),
12599
+ "x",
12600
+ " ",
12601
+ pluralize(items.length, "items", "item")
12602
+ ] })
12603
+ ]
12604
+ }
12605
+ )
12606
+ }
12607
+ ),
12608
+ /* @__PURE__ */ jsx(
12609
+ Tooltip,
12610
+ {
12611
+ content: (_d = (_c = (_b = shippingOption.service_zone) == null ? void 0 : _b.fulfillment_set) == null ? void 0 : _c.location) == null ? void 0 : _d.name,
12612
+ children: /* @__PURE__ */ jsxs(
12613
+ Badge,
12614
+ {
12615
+ className: "flex items-center gap-x-[3px] overflow-hidden cursor-default",
12616
+ size: "xsmall",
12617
+ children: [
12618
+ /* @__PURE__ */ jsx(Buildings, { className: "shrink-0" }),
12619
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: (_g = (_f = (_e = shippingOption.service_zone) == null ? void 0 : _e.fulfillment_set) == null ? void 0 : _f.location) == null ? void 0 : _g.name })
12620
+ ]
12621
+ }
12622
+ )
12623
+ }
12624
+ ),
12625
+ /* @__PURE__ */ jsx(Tooltip, { content: shippingOption.name, children: /* @__PURE__ */ jsxs(
12626
+ Badge,
12627
+ {
12628
+ className: "flex items-center gap-x-[3px] overflow-hidden cursor-default",
12629
+ size: "xsmall",
12630
+ children: [
12631
+ /* @__PURE__ */ jsx(TruckFast, { className: "shrink-0" }),
12632
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: shippingOption.name })
12633
+ ]
12634
+ }
12635
+ ) })
12636
+ ] })
12637
+ ] }),
12638
+ shippingOption ? /* @__PURE__ */ jsx(
12639
+ ActionMenu,
12640
+ {
12641
+ groups: [
12642
+ {
12643
+ actions: [
12644
+ hasItems ? {
12645
+ label: "Edit shipping option",
12646
+ icon: /* @__PURE__ */ jsx(Channels, {}),
12647
+ onClick: () => {
12648
+ setIsOpen(
12649
+ STACKED_FOCUS_MODAL_ID,
12650
+ true
12651
+ );
12652
+ setData({
12653
+ shippingProfileId: profile.id,
12654
+ shippingOption,
12655
+ shippingMethod
12656
+ });
12657
+ }
12658
+ } : void 0,
12659
+ {
12660
+ label: "Remove shipping option",
12661
+ icon: /* @__PURE__ */ jsx(Trash, {}),
12662
+ onClick: () => {
12663
+ if (shippingMethod) {
12664
+ if (addShippingMethodAction) {
12665
+ removeActionShippingMethod(
12666
+ addShippingMethodAction.id
12667
+ );
12668
+ } else {
12669
+ removeShippingMethod(
12670
+ shippingMethod.id
12671
+ );
12672
+ }
12673
+ }
12674
+ }
12675
+ }
12676
+ ].filter(Boolean)
12677
+ }
12678
+ ]
12679
+ }
12680
+ ) : /* @__PURE__ */ jsx(
12681
+ StackedModalTrigger,
12682
+ {
12683
+ shippingProfileId: profile.id,
12684
+ shippingOption,
12685
+ shippingMethod,
12686
+ setData,
12687
+ children: "Add shipping option"
12688
+ }
12689
+ )
12690
+ ] }),
12691
+ /* @__PURE__ */ jsxs(Accordion.Content, { children: [
12692
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12693
+ items.map((item, idx) => {
12694
+ var _a3, _b2, _c2, _d2, _e2;
12695
+ return /* @__PURE__ */ jsxs("div", { children: [
12696
+ /* @__PURE__ */ jsxs(
12697
+ "div",
12698
+ {
12699
+ className: "px-3 flex items-center gap-x-3",
12700
+ children: [
12701
+ /* @__PURE__ */ jsx("div", { className: "w-5 h-[56px] flex flex-col justify-center items-center", children: /* @__PURE__ */ jsx(
12702
+ Divider,
12703
+ {
12704
+ variant: "dashed",
12705
+ orientation: "vertical"
12706
+ }
12707
+ ) }),
12708
+ /* @__PURE__ */ jsxs("div", { className: "py-2 flex items-center gap-x-3", children: [
12709
+ /* @__PURE__ */ jsx("div", { className: "size-7 flex items-center justify-center tabular-nums", children: /* @__PURE__ */ jsxs(
12710
+ Text,
12711
+ {
12712
+ size: "small",
12713
+ leading: "compact",
12714
+ className: "text-ui-fg-subtle",
12715
+ children: [
12716
+ item.quantity,
12717
+ "x"
12718
+ ]
12719
+ }
12720
+ ) }),
12721
+ /* @__PURE__ */ jsx(Thumbnail, { thumbnail: item.thumbnail }),
12722
+ /* @__PURE__ */ jsxs("div", { children: [
12723
+ /* @__PURE__ */ jsxs(
12724
+ Text,
12725
+ {
12726
+ size: "small",
12727
+ leading: "compact",
12728
+ weight: "plus",
12729
+ children: [
12730
+ (_b2 = (_a3 = item.variant) == null ? void 0 : _a3.product) == null ? void 0 : _b2.title,
12731
+ " (",
12732
+ (_c2 = item.variant) == null ? void 0 : _c2.title,
12733
+ ")"
12734
+ ]
12735
+ }
12736
+ ),
12737
+ /* @__PURE__ */ jsx(
12738
+ Text,
12739
+ {
12740
+ size: "small",
12741
+ leading: "compact",
12742
+ className: "text-ui-fg-subtle",
12743
+ children: (_e2 = (_d2 = item.variant) == null ? void 0 : _d2.options) == null ? void 0 : _e2.map((option) => option.value).join(" · ")
12744
+ }
12745
+ )
12746
+ ] })
12747
+ ] })
12748
+ ]
12749
+ },
12750
+ item.id
12751
+ ),
12752
+ idx !== items.length - 1 && /* @__PURE__ */ jsx(Divider, { variant: "dashed" })
12753
+ ] }, item.id);
12754
+ })
12533
12755
  ] })
12534
- ] }) })
12535
- ] })
12536
- ] }),
12537
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12538
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
12539
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
12540
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
12541
- Text,
12542
- {
12543
- size: "small",
12544
- leading: "compact",
12545
- className: "text-ui-fg-subtle",
12546
- children: [
12547
- itemCount,
12548
- " ",
12549
- itemCount === 1 ? "item" : "items"
12550
- ]
12551
- }
12552
- ) }),
12553
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
12554
- ] })
12555
- ] }) }),
12556
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
12557
- CustomItemForm,
12558
- {
12559
- orderId: preview.id,
12560
- currencyCode
12756
+ ]
12757
+ },
12758
+ profile.id
12759
+ );
12760
+ }) })
12761
+ ] }) })
12762
+ ] }) }),
12763
+ /* @__PURE__ */ jsx(
12764
+ StackedFocusModal,
12765
+ {
12766
+ id: STACKED_FOCUS_MODAL_ID,
12767
+ onOpenChangeCallback: (open) => {
12768
+ if (!open) {
12769
+ setData(null);
12561
12770
  }
12562
- ) : null)
12563
- ]
12564
- }
12565
- ) }),
12566
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
12771
+ return open;
12772
+ },
12773
+ children: data && /* @__PURE__ */ jsx(ShippingProfileForm, { data, order, preview })
12774
+ }
12775
+ )
12776
+ ] }),
12777
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-x-2", children: [
12567
12778
  /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12568
12779
  /* @__PURE__ */ jsx(
12569
12780
  Button,
12570
12781
  {
12571
12782
  size: "small",
12572
12783
  type: "button",
12573
- onClick: onSubmit,
12574
12784
  isLoading: isSubmitting,
12785
+ onClick: onSubmit,
12575
12786
  children: "Save"
12576
12787
  }
12577
12788
  )
12578
12789
  ] }) })
12579
12790
  ] });
12580
12791
  };
12581
- const Item = ({ item, preview, currencyCode }) => {
12582
- if (item.variant_id) {
12583
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
12584
- }
12585
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
12586
- };
12587
- const VariantItem = ({ item, preview, currencyCode }) => {
12588
- const [editing, setEditing] = useState(false);
12589
- const form = useForm({
12590
- defaultValues: {
12591
- quantity: item.quantity,
12592
- unit_price: item.unit_price
12593
- },
12594
- resolver: zodResolver(variantItemSchema)
12595
- });
12596
- const actionId = useMemo(() => {
12597
- var _a, _b;
12598
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12599
- }, [item]);
12600
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12601
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12602
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12603
- const onSubmit = form.handleSubmit(async (data) => {
12604
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
12605
- setEditing(false);
12606
- return;
12792
+ const StackedModalTrigger = ({
12793
+ shippingProfileId,
12794
+ shippingOption,
12795
+ shippingMethod,
12796
+ setData,
12797
+ children
12798
+ }) => {
12799
+ const { setIsOpen, getIsOpen } = useStackedModal();
12800
+ const isOpen = getIsOpen(STACKED_FOCUS_MODAL_ID);
12801
+ const onToggle = () => {
12802
+ if (isOpen) {
12803
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12804
+ setData(null);
12805
+ } else {
12806
+ setIsOpen(STACKED_FOCUS_MODAL_ID, true);
12807
+ setData({
12808
+ shippingProfileId,
12809
+ shippingOption,
12810
+ shippingMethod
12811
+ });
12607
12812
  }
12608
- if (!actionId) {
12609
- await updateOriginalItem(
12610
- {
12611
- item_id: item.id,
12612
- quantity: data.quantity,
12613
- unit_price: convertNumber(data.unit_price)
12614
- },
12615
- {
12616
- onSuccess: () => {
12617
- setEditing(false);
12618
- },
12619
- onError: (e) => {
12620
- toast.error(e.message);
12621
- }
12622
- }
12623
- );
12624
- return;
12813
+ };
12814
+ return /* @__PURE__ */ jsx(
12815
+ Button,
12816
+ {
12817
+ size: "small",
12818
+ variant: "secondary",
12819
+ onClick: onToggle,
12820
+ className: "text-ui-fg-primary shrink-0",
12821
+ children
12625
12822
  }
12626
- await updateActionItem(
12627
- {
12628
- action_id: actionId,
12629
- quantity: data.quantity,
12630
- unit_price: convertNumber(data.unit_price)
12631
- },
12632
- {
12633
- onSuccess: () => {
12634
- setEditing(false);
12635
- },
12636
- onError: (e) => {
12637
- toast.error(e.message);
12638
- }
12639
- }
12640
- );
12641
- });
12642
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
12643
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
12644
- /* @__PURE__ */ jsx(
12645
- Thumbnail,
12646
- {
12647
- thumbnail: item.thumbnail,
12648
- alt: item.product_title ?? void 0
12649
- }
12650
- ),
12651
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12652
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
12653
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
12654
- /* @__PURE__ */ jsxs(
12655
- Text,
12656
- {
12657
- size: "small",
12658
- leading: "compact",
12659
- className: "text-ui-fg-subtle",
12660
- children: [
12661
- "(",
12662
- item.variant_title,
12663
- ")"
12664
- ]
12665
- }
12666
- )
12667
- ] }),
12668
- /* @__PURE__ */ jsx(
12669
- Text,
12670
- {
12671
- size: "small",
12672
- leading: "compact",
12673
- className: "text-ui-fg-subtle",
12674
- children: item.variant_sku
12675
- }
12676
- )
12677
- ] })
12678
- ] }),
12679
- editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
12680
- Form$2.Field,
12681
- {
12682
- control: form.control,
12683
- name: "quantity",
12684
- render: ({ field }) => {
12685
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
12686
- }
12687
- }
12688
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
12689
- editing ? /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(
12690
- Form$2.Field,
12691
- {
12692
- control: form.control,
12693
- name: "unit_price",
12694
- render: ({ field: { onChange, ...field } }) => {
12695
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12696
- CurrencyInput,
12697
- {
12698
- ...field,
12699
- symbol: getNativeSymbol(currencyCode),
12700
- code: currencyCode,
12701
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12702
- }
12703
- ) }) });
12704
- }
12705
- }
12706
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
12707
- /* @__PURE__ */ jsx(
12708
- IconButton,
12709
- {
12710
- type: "button",
12711
- size: "small",
12712
- onClick: editing ? onSubmit : () => {
12713
- setEditing(true);
12714
- },
12715
- disabled: isPending,
12716
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
12717
- }
12718
- )
12719
- ] }) }) });
12823
+ );
12720
12824
  };
12721
- const variantItemSchema = z.object({
12722
- quantity: z.number(),
12723
- unit_price: z.union([z.number(), z.string()])
12724
- });
12725
- const CustomItem = ({ item, preview, currencyCode }) => {
12726
- const [editing, setEditing] = useState(false);
12727
- const { quantity, unit_price, title } = item;
12825
+ const ShippingProfileForm = ({
12826
+ data,
12827
+ order,
12828
+ preview
12829
+ }) => {
12830
+ var _a, _b, _c, _d, _e, _f;
12831
+ const { setIsOpen } = useStackedModal();
12728
12832
  const form = useForm({
12833
+ resolver: zodResolver(shippingMethodSchema),
12729
12834
  defaultValues: {
12730
- title,
12731
- quantity,
12732
- unit_price
12733
- },
12734
- resolver: zodResolver(customItemSchema)
12835
+ location_id: (_d = (_c = (_b = (_a = data.shippingOption) == null ? void 0 : _a.service_zone) == null ? void 0 : _b.fulfillment_set) == null ? void 0 : _c.location) == null ? void 0 : _d.id,
12836
+ shipping_option_id: (_e = data.shippingOption) == null ? void 0 : _e.id,
12837
+ custom_amount: (_f = data.shippingMethod) == null ? void 0 : _f.amount
12838
+ }
12735
12839
  });
12736
- useEffect(() => {
12737
- form.reset({
12738
- title,
12739
- quantity,
12740
- unit_price
12741
- });
12742
- }, [form, title, quantity, unit_price]);
12743
- const actionId = useMemo(() => {
12744
- var _a, _b;
12745
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12746
- }, [item]);
12747
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12748
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
12749
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12750
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12751
- const onSubmit = form.handleSubmit(async (data) => {
12752
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
12753
- setEditing(false);
12840
+ const { mutateAsync: addShippingMethod, isPending } = useDraftOrderAddShippingMethod(order.id);
12841
+ const {
12842
+ mutateAsync: updateShippingMethod,
12843
+ isPending: isUpdatingShippingMethod
12844
+ } = useDraftOrderUpdateShippingMethod(order.id);
12845
+ const onSubmit = form.handleSubmit(async (values) => {
12846
+ if (isEqual(values, form.formState.defaultValues)) {
12847
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12754
12848
  return;
12755
12849
  }
12756
- if (!actionId) {
12757
- await updateOriginalItem(
12850
+ if (data.shippingMethod) {
12851
+ await updateShippingMethod(
12758
12852
  {
12759
- item_id: item.id,
12760
- quantity: data.quantity,
12761
- unit_price: convertNumber(data.unit_price)
12853
+ method_id: data.shippingMethod.id,
12854
+ shipping_option_id: values.shipping_option_id,
12855
+ custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
12762
12856
  },
12763
12857
  {
12764
- onSuccess: () => {
12765
- setEditing(false);
12766
- },
12767
12858
  onError: (e) => {
12768
12859
  toast.error(e.message);
12860
+ },
12861
+ onSuccess: () => {
12862
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12769
12863
  }
12770
12864
  }
12771
12865
  );
12772
12866
  return;
12773
12867
  }
12774
- if (data.quantity === 0) {
12775
- await removeActionItem(actionId, {
12776
- onSuccess: () => {
12777
- setEditing(false);
12778
- },
12779
- onError: (e) => {
12780
- toast.error(e.message);
12781
- }
12782
- });
12783
- return;
12784
- }
12785
- await updateActionItem(
12786
- {
12787
- action_id: actionId,
12788
- quantity: data.quantity,
12789
- unit_price: convertNumber(data.unit_price)
12790
- },
12791
- {
12792
- onSuccess: () => {
12793
- setEditing(false);
12794
- },
12795
- onError: (e) => {
12796
- toast.error(e.message);
12797
- }
12798
- }
12799
- );
12800
- });
12801
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
12802
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
12803
- /* @__PURE__ */ jsx(
12804
- Thumbnail,
12805
- {
12806
- thumbnail: item.thumbnail,
12807
- alt: item.title ?? void 0
12808
- }
12809
- ),
12810
- editing ? /* @__PURE__ */ jsx(
12811
- Form$2.Field,
12812
- {
12813
- control: form.control,
12814
- name: "title",
12815
- render: ({ field }) => {
12816
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
12817
- }
12818
- }
12819
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
12820
- ] }),
12821
- editing ? /* @__PURE__ */ jsx(
12822
- Form$2.Field,
12823
- {
12824
- control: form.control,
12825
- name: "quantity",
12826
- render: ({ field }) => {
12827
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
12828
- }
12829
- }
12830
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
12831
- editing ? /* @__PURE__ */ jsx(
12832
- Form$2.Field,
12833
- {
12834
- control: form.control,
12835
- name: "unit_price",
12836
- render: ({ field: { onChange, ...field } }) => {
12837
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12838
- CurrencyInput,
12839
- {
12840
- ...field,
12841
- symbol: getNativeSymbol(currencyCode),
12842
- code: currencyCode,
12843
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12844
- }
12845
- ) }) });
12846
- }
12847
- }
12848
- ) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
12849
- /* @__PURE__ */ jsx(
12850
- IconButton,
12851
- {
12852
- type: "button",
12853
- size: "small",
12854
- onClick: editing ? onSubmit : () => {
12855
- setEditing(true);
12856
- },
12857
- disabled: isPending,
12858
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
12859
- }
12860
- )
12861
- ] }) }) });
12862
- };
12863
- const StackedModalTrigger = ({
12864
- type,
12865
- setModalContent
12866
- }) => {
12867
- const { setIsOpen } = useStackedModal();
12868
- const onClick = useCallback(() => {
12869
- setModalContent(type);
12870
- setIsOpen(STACKED_MODAL_ID, true);
12871
- }, [setModalContent, setIsOpen, type]);
12872
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
12873
- };
12874
- const VARIANT_PREFIX = "items";
12875
- const LIMIT = 50;
12876
- const ExistingItemsForm = ({ orderId, items }) => {
12877
- const { setIsOpen } = useStackedModal();
12878
- const [rowSelection, setRowSelection] = useState(
12879
- items.reduce((acc, item) => {
12880
- acc[item.variant_id] = true;
12881
- return acc;
12882
- }, {})
12883
- );
12884
- useEffect(() => {
12885
- setRowSelection(
12886
- items.reduce((acc, item) => {
12887
- if (item.variant_id) {
12888
- acc[item.variant_id] = true;
12889
- }
12890
- return acc;
12891
- }, {})
12892
- );
12893
- }, [items]);
12894
- const { q, order, offset } = useQueryParams(
12895
- ["q", "order", "offset"],
12896
- VARIANT_PREFIX
12897
- );
12898
- const { variants, count, isPending, isError, error } = useProductVariants(
12899
- {
12900
- q,
12901
- order,
12902
- offset: offset ? parseInt(offset) : void 0,
12903
- limit: LIMIT
12904
- },
12905
- {
12906
- placeholderData: keepPreviousData
12907
- }
12908
- );
12909
- const columns = useColumns();
12910
- const { mutateAsync } = useDraftOrderAddItems(orderId);
12911
- const onSubmit = async () => {
12912
- const ids = Object.keys(rowSelection).filter(
12913
- (id) => !items.find((i) => i.variant_id === id)
12914
- );
12915
- await mutateAsync(
12916
- {
12917
- items: ids.map((id) => ({
12918
- variant_id: id,
12919
- quantity: 1
12920
- }))
12921
- },
12868
+ await addShippingMethod(
12922
12869
  {
12923
- onSuccess: () => {
12924
- setRowSelection({});
12925
- setIsOpen(STACKED_MODAL_ID, false);
12926
- },
12927
- onError: (e) => {
12928
- toast.error(e.message);
12929
- }
12930
- }
12931
- );
12932
- };
12933
- if (isError) {
12934
- throw error;
12935
- }
12936
- return /* @__PURE__ */ jsxs(
12937
- StackedFocusModal.Content,
12938
- {
12939
- onOpenAutoFocus: (e) => {
12940
- e.preventDefault();
12941
- const searchInput = document.querySelector(
12942
- "[data-modal-id='modal-search-input']"
12943
- );
12944
- if (searchInput) {
12945
- searchInput.focus();
12946
- }
12947
- },
12948
- children: [
12949
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
12950
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
12951
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
12952
- ] }),
12953
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
12954
- DataTable,
12955
- {
12956
- data: variants,
12957
- columns,
12958
- isLoading: isPending,
12959
- getRowId: (row) => row.id,
12960
- rowCount: count,
12961
- prefix: VARIANT_PREFIX,
12962
- layout: "fill",
12963
- rowSelection: {
12964
- state: rowSelection,
12965
- onRowSelectionChange: setRowSelection,
12966
- enableRowSelection: (row) => {
12967
- return !items.find((i) => i.variant_id === row.original.id);
12968
- }
12969
- },
12970
- autoFocusSearch: true
12971
- }
12972
- ) }),
12973
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
12870
+ shipping_option_id: values.shipping_option_id,
12871
+ custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
12872
+ },
12873
+ {
12874
+ onError: (e) => {
12875
+ toast.error(e.message);
12876
+ },
12877
+ onSuccess: () => {
12878
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12879
+ }
12880
+ }
12881
+ );
12882
+ });
12883
+ return /* @__PURE__ */ jsx(StackedFocusModal.Content, { children: /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxs(
12884
+ KeyboundForm,
12885
+ {
12886
+ className: "flex h-full flex-col overflow-hidden",
12887
+ onSubmit,
12888
+ children: [
12889
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
12890
+ /* @__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 py-16 px-6", children: [
12891
+ /* @__PURE__ */ jsxs("div", { children: [
12892
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
12893
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a shipping method for the selected shipping profile. You can see the items that will be shipped using this method in the preview below." }) })
12894
+ ] }),
12895
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12896
+ /* @__PURE__ */ jsx(
12897
+ LocationField,
12898
+ {
12899
+ control: form.control,
12900
+ setValue: form.setValue
12901
+ }
12902
+ ),
12903
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12904
+ /* @__PURE__ */ jsx(
12905
+ ShippingOptionField,
12906
+ {
12907
+ shippingProfileId: data.shippingProfileId,
12908
+ preview,
12909
+ control: form.control
12910
+ }
12911
+ ),
12912
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12913
+ /* @__PURE__ */ jsx(
12914
+ CustomAmountField,
12915
+ {
12916
+ control: form.control,
12917
+ currencyCode: order.currency_code
12918
+ }
12919
+ ),
12920
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
12921
+ /* @__PURE__ */ jsx(
12922
+ ItemsPreview,
12923
+ {
12924
+ order,
12925
+ shippingProfileId: data.shippingProfileId
12926
+ }
12927
+ )
12928
+ ] }) }) }),
12929
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-x-2", children: [
12974
12930
  /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12975
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
12931
+ /* @__PURE__ */ jsx(
12932
+ Button,
12933
+ {
12934
+ size: "small",
12935
+ type: "submit",
12936
+ isLoading: isPending || isUpdatingShippingMethod,
12937
+ children: data.shippingMethod ? "Update" : "Add"
12938
+ }
12939
+ )
12976
12940
  ] }) })
12977
12941
  ]
12978
12942
  }
12979
- );
12943
+ ) }) });
12980
12944
  };
12981
- const columnHelper = createDataTableColumnHelper();
12982
- const useColumns = () => {
12983
- return useMemo(() => {
12984
- return [
12985
- columnHelper.select(),
12986
- columnHelper.accessor("product.title", {
12987
- header: "Product",
12988
- cell: ({ row }) => {
12989
- var _a, _b, _c;
12990
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
12991
- /* @__PURE__ */ jsx(
12992
- Thumbnail,
12945
+ const shippingMethodSchema = z.object({
12946
+ location_id: z.string(),
12947
+ shipping_option_id: z.string(),
12948
+ custom_amount: z.union([z.number(), z.string()]).optional()
12949
+ });
12950
+ const ItemsPreview = ({ order, shippingProfileId }) => {
12951
+ const matches = order.items.filter(
12952
+ (item) => {
12953
+ var _a, _b, _c;
12954
+ return ((_c = (_b = (_a = item.variant) == null ? void 0 : _a.product) == null ? void 0 : _b.shipping_profile) == null ? void 0 : _c.id) === shippingProfileId;
12955
+ }
12956
+ );
12957
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
12958
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 items-center gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12959
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items to ship" }),
12960
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Items with the selected shipping profile." })
12961
+ ] }) }),
12962
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
12963
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 px-4 py-2 text-ui-fg-muted", children: [
12964
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
12965
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) })
12966
+ ] }),
12967
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxs(
12968
+ "div",
12969
+ {
12970
+ className: "grid grid-cols-2 gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center",
12971
+ children: [
12972
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
12973
+ /* @__PURE__ */ jsx(
12974
+ Thumbnail,
12975
+ {
12976
+ thumbnail: item.thumbnail,
12977
+ alt: item.product_title ?? void 0
12978
+ }
12979
+ ),
12980
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
12981
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
12982
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
12983
+ /* @__PURE__ */ jsxs(
12984
+ Text,
12985
+ {
12986
+ size: "small",
12987
+ leading: "compact",
12988
+ className: "text-ui-fg-subtle",
12989
+ children: [
12990
+ "(",
12991
+ item.variant_title,
12992
+ ")"
12993
+ ]
12994
+ }
12995
+ )
12996
+ ] }),
12997
+ /* @__PURE__ */ jsx(
12998
+ Text,
12999
+ {
13000
+ size: "small",
13001
+ leading: "compact",
13002
+ className: "text-ui-fg-subtle",
13003
+ children: item.variant_sku
13004
+ }
13005
+ )
13006
+ ] })
13007
+ ] }),
13008
+ /* @__PURE__ */ jsxs(
13009
+ Text,
12993
13010
  {
12994
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
12995
- alt: (_b = row.original.product) == null ? void 0 : _b.title
13011
+ size: "small",
13012
+ leading: "compact",
13013
+ className: "text-ui-fg-subtle",
13014
+ children: [
13015
+ item.quantity,
13016
+ "x"
13017
+ ]
12996
13018
  }
12997
- ),
12998
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
12999
- ] });
13000
- },
13001
- enableSorting: true
13002
- }),
13003
- columnHelper.accessor("title", {
13004
- header: "Variant",
13005
- enableSorting: true
13006
- }),
13007
- columnHelper.accessor("sku", {
13008
- header: "SKU",
13009
- cell: ({ getValue }) => {
13010
- return getValue() ?? "-";
13011
- },
13012
- enableSorting: true
13013
- }),
13014
- columnHelper.accessor("updated_at", {
13015
- header: "Updated",
13016
- cell: ({ getValue }) => {
13017
- return /* @__PURE__ */ jsx(
13018
- Tooltip,
13019
- {
13020
- content: getFullDate({ date: getValue(), includeTime: true }),
13021
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
13022
- }
13023
- );
13019
+ )
13020
+ ]
13024
13021
  },
13025
- enableSorting: true,
13026
- sortAscLabel: "Oldest first",
13027
- sortDescLabel: "Newest first"
13028
- }),
13029
- columnHelper.accessor("created_at", {
13030
- header: "Created",
13031
- cell: ({ getValue }) => {
13032
- return /* @__PURE__ */ jsx(
13033
- Tooltip,
13022
+ item.id
13023
+ )) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
13024
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
13025
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
13026
+ 'No items found for "',
13027
+ query,
13028
+ '".'
13029
+ ] })
13030
+ ] }) })
13031
+ ] })
13032
+ ] });
13033
+ };
13034
+ const LocationField = ({ control, setValue }) => {
13035
+ const locations = useComboboxData({
13036
+ queryKey: ["locations"],
13037
+ queryFn: async (params) => {
13038
+ return await sdk.admin.stockLocation.list(params);
13039
+ },
13040
+ getOptions: (data) => {
13041
+ return data.stock_locations.map((location) => ({
13042
+ label: location.name,
13043
+ value: location.id
13044
+ }));
13045
+ }
13046
+ });
13047
+ return /* @__PURE__ */ jsx(
13048
+ Form$2.Field,
13049
+ {
13050
+ control,
13051
+ name: "location_id",
13052
+ render: ({ field: { onChange, ...field } }) => {
13053
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
13054
+ /* @__PURE__ */ jsxs("div", { children: [
13055
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Location" }),
13056
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Choose where you want to ship the items from." })
13057
+ ] }),
13058
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
13059
+ Combobox,
13034
13060
  {
13035
- content: getFullDate({ date: getValue(), includeTime: true }),
13036
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
13037
- }
13038
- );
13039
- },
13040
- enableSorting: true,
13041
- sortAscLabel: "Oldest first",
13042
- sortDescLabel: "Newest first"
13043
- })
13044
- ];
13045
- }, []);
13061
+ options: locations.options,
13062
+ fetchNextPage: locations.fetchNextPage,
13063
+ isFetchingNextPage: locations.isFetchingNextPage,
13064
+ searchValue: locations.searchValue,
13065
+ onSearchValueChange: locations.onSearchValueChange,
13066
+ placeholder: "Select location",
13067
+ onChange: (value) => {
13068
+ setValue("shipping_option_id", "", {
13069
+ shouldDirty: true,
13070
+ shouldTouch: true
13071
+ });
13072
+ onChange(value);
13073
+ },
13074
+ ...field
13075
+ }
13076
+ ) })
13077
+ ] }) });
13078
+ }
13079
+ }
13080
+ );
13046
13081
  };
13047
- const CustomItemForm = ({ orderId, currencyCode }) => {
13048
- const { setIsOpen } = useStackedModal();
13049
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
13050
- const form = useForm({
13051
- defaultValues: {
13052
- title: "",
13053
- quantity: 1,
13054
- unit_price: ""
13082
+ const ShippingOptionField = ({
13083
+ shippingProfileId,
13084
+ preview,
13085
+ control
13086
+ }) => {
13087
+ var _a;
13088
+ const locationId = useWatch({ control, name: "location_id" });
13089
+ const shippingOptions = useComboboxData({
13090
+ queryKey: ["shipping_options", locationId, shippingProfileId],
13091
+ queryFn: async (params) => {
13092
+ return await sdk.admin.shippingOption.list({
13093
+ ...params,
13094
+ stock_location_id: locationId,
13095
+ shipping_profile_id: shippingProfileId
13096
+ });
13055
13097
  },
13056
- resolver: zodResolver(customItemSchema)
13057
- });
13058
- const onSubmit = form.handleSubmit(async (data) => {
13059
- await addItems(
13060
- {
13061
- items: [
13062
- {
13063
- title: data.title,
13064
- quantity: data.quantity,
13065
- unit_price: convertNumber(data.unit_price)
13066
- }
13067
- ]
13068
- },
13069
- {
13070
- onSuccess: () => {
13071
- setIsOpen(STACKED_MODAL_ID, false);
13072
- },
13073
- onError: (e) => {
13074
- toast.error(e.message);
13098
+ getOptions: (data) => {
13099
+ return data.shipping_options.map((option) => {
13100
+ var _a2;
13101
+ if ((_a2 = option.rules) == null ? void 0 : _a2.find(
13102
+ (r) => r.attribute === "is_return" && r.value === "true"
13103
+ )) {
13104
+ return void 0;
13075
13105
  }
13076
- }
13077
- );
13106
+ return {
13107
+ label: option.name,
13108
+ value: option.id
13109
+ };
13110
+ }).filter(Boolean);
13111
+ },
13112
+ enabled: !!locationId && !!shippingProfileId,
13113
+ defaultValue: ((_a = preview.shipping_methods[0]) == null ? void 0 : _a.shipping_option_id) || void 0
13078
13114
  });
13079
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
13080
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
13081
- /* @__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: [
13082
- /* @__PURE__ */ jsxs("div", { children: [
13083
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
13084
- /* @__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." }) })
13085
- ] }),
13086
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
13087
- /* @__PURE__ */ jsx(
13088
- Form$2.Field,
13089
- {
13090
- control: form.control,
13091
- name: "title",
13092
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
13093
- /* @__PURE__ */ jsxs("div", { children: [
13094
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
13095
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
13096
- ] }),
13097
- /* @__PURE__ */ jsxs("div", { children: [
13098
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13099
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13100
- ] })
13101
- ] }) })
13102
- }
13103
- ),
13104
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
13105
- /* @__PURE__ */ jsx(
13106
- Form$2.Field,
13107
- {
13108
- control: form.control,
13109
- name: "unit_price",
13110
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
13111
- /* @__PURE__ */ jsxs("div", { children: [
13112
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
13113
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
13114
- ] }),
13115
- /* @__PURE__ */ jsxs("div", { children: [
13116
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
13117
- CurrencyInput,
13115
+ const tooltipContent = !locationId && !shippingProfileId ? "Choose a location and shipping profile first." : !locationId ? "Choose a location first." : "Choose a shipping profile first.";
13116
+ return /* @__PURE__ */ jsx(
13117
+ Form$2.Field,
13118
+ {
13119
+ control,
13120
+ name: "shipping_option_id",
13121
+ render: ({ field }) => {
13122
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
13123
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
13124
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Shipping option" }),
13125
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Choose the shipping option to use." })
13126
+ ] }),
13127
+ /* @__PURE__ */ jsx(
13128
+ ConditionalTooltip,
13129
+ {
13130
+ content: tooltipContent,
13131
+ showTooltip: !locationId || !shippingProfileId,
13132
+ children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
13133
+ Combobox,
13118
13134
  {
13119
- symbol: getNativeSymbol(currencyCode),
13120
- code: currencyCode,
13121
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
13122
- ...field
13135
+ options: shippingOptions.options,
13136
+ fetchNextPage: shippingOptions.fetchNextPage,
13137
+ isFetchingNextPage: shippingOptions.isFetchingNextPage,
13138
+ searchValue: shippingOptions.searchValue,
13139
+ onSearchValueChange: shippingOptions.onSearchValueChange,
13140
+ placeholder: "Select shipping option",
13141
+ ...field,
13142
+ disabled: !locationId || !shippingProfileId
13123
13143
  }
13124
- ) }),
13125
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13126
- ] })
13127
- ] }) })
13128
- }
13129
- ),
13130
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
13131
- /* @__PURE__ */ jsx(
13132
- Form$2.Field,
13133
- {
13134
- control: form.control,
13135
- name: "quantity",
13136
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
13137
- /* @__PURE__ */ jsxs("div", { children: [
13138
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
13139
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
13140
- ] }),
13141
- /* @__PURE__ */ jsxs("div", { className: "flex-1 w-full", children: [
13142
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
13143
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13144
- ] })
13145
- ] }) })
13146
- }
13147
- )
13148
- ] }) }) }),
13149
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
13150
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
13151
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
13152
- ] }) })
13153
- ] }) }) });
13154
- };
13155
- const customItemSchema = z.object({
13156
- title: z.string().min(1),
13157
- quantity: z.number(),
13158
- unit_price: z.union([z.number(), z.string()])
13159
- });
13160
- const CustomItems = () => {
13161
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
13162
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
13163
- /* @__PURE__ */ jsx(CustomItemsForm, {})
13164
- ] });
13144
+ ) }) })
13145
+ }
13146
+ )
13147
+ ] }) });
13148
+ }
13149
+ }
13150
+ );
13165
13151
  };
13166
- const CustomItemsForm = () => {
13167
- const form = useForm({
13168
- resolver: zodResolver(schema)
13169
- });
13170
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
13171
- /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
13172
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13173
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
13174
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
13175
- ] }) })
13176
- ] }) });
13152
+ const CustomAmountField = ({
13153
+ control,
13154
+ currencyCode
13155
+ }) => {
13156
+ return /* @__PURE__ */ jsx(
13157
+ Form$2.Field,
13158
+ {
13159
+ control,
13160
+ name: "custom_amount",
13161
+ render: ({ field: { onChange, ...field } }) => {
13162
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
13163
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
13164
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Custom amount" }),
13165
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
13166
+ ] }),
13167
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
13168
+ CurrencyInput,
13169
+ {
13170
+ ...field,
13171
+ onValueChange: (value) => onChange(value),
13172
+ symbol: getNativeSymbol(currencyCode),
13173
+ code: currencyCode
13174
+ }
13175
+ ) })
13176
+ ] });
13177
+ }
13178
+ }
13179
+ );
13177
13180
  };
13178
- const schema = z.object({
13179
- email: z.string().email()
13180
- });
13181
13181
  const widgetModule = { widgets: [] };
13182
13182
  const routeModule = {
13183
13183
  routes: [
@@ -13203,25 +13203,29 @@ const routeModule = {
13203
13203
  path: "/draft-orders/:id/billing-address"
13204
13204
  },
13205
13205
  {
13206
- Component: Email,
13207
- path: "/draft-orders/:id/email"
13206
+ Component: CustomItems,
13207
+ path: "/draft-orders/:id/custom-items"
13208
13208
  },
13209
13209
  {
13210
- Component: Promotions,
13211
- path: "/draft-orders/:id/promotions"
13210
+ Component: Items,
13211
+ path: "/draft-orders/:id/items"
13212
13212
  },
13213
13213
  {
13214
- Component: SalesChannel,
13215
- path: "/draft-orders/:id/sales-channel"
13214
+ Component: Email,
13215
+ path: "/draft-orders/:id/email"
13216
13216
  },
13217
13217
  {
13218
- Component: Shipping,
13219
- path: "/draft-orders/:id/shipping"
13218
+ Component: SalesChannel,
13219
+ path: "/draft-orders/:id/sales-channel"
13220
13220
  },
13221
13221
  {
13222
13222
  Component: Metadata,
13223
13223
  path: "/draft-orders/:id/metadata"
13224
13224
  },
13225
+ {
13226
+ Component: Promotions,
13227
+ path: "/draft-orders/:id/promotions"
13228
+ },
13225
13229
  {
13226
13230
  Component: ShippingAddress,
13227
13231
  path: "/draft-orders/:id/shipping-address"
@@ -13231,12 +13235,8 @@ const routeModule = {
13231
13235
  path: "/draft-orders/:id/transfer-ownership"
13232
13236
  },
13233
13237
  {
13234
- Component: Items,
13235
- path: "/draft-orders/:id/items"
13236
- },
13237
- {
13238
- Component: CustomItems,
13239
- path: "/draft-orders/:id/custom-items"
13238
+ Component: Shipping,
13239
+ path: "/draft-orders/:id/shipping"
13240
13240
  }
13241
13241
  ]
13242
13242
  }