@medusajs/draft-order 2.10.2-preview-20250909090202 → 2.10.2-preview-20250909081836

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