@medusajs/draft-order 2.11.1-snapshot-20251021090705 → 2.11.1-snapshot-20251021112110

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