@medusajs/draft-order 0.0.8 → 0.0.10

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.
@@ -9712,95 +9712,6 @@ const ID = () => {
9712
9712
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Outlet, {})
9713
9713
  ] });
9714
9714
  };
9715
- const CustomItems = () => {
9716
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9717
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Custom Items" }) }) }),
9718
- /* @__PURE__ */ jsxRuntime.jsx(CustomItemsForm, {})
9719
- ] });
9720
- };
9721
- const CustomItemsForm = () => {
9722
- const form = reactHookForm.useForm({
9723
- resolver: zod.zodResolver(schema$5)
9724
- });
9725
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9726
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, {}),
9727
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9728
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9729
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", children: "Save" })
9730
- ] }) })
9731
- ] }) });
9732
- };
9733
- const schema$5 = z.object({
9734
- email: z.string().email()
9735
- });
9736
- const Email = () => {
9737
- const { id } = reactRouterDom.useParams();
9738
- const { order, isPending, isError, error } = useOrder(id, {
9739
- fields: "+email"
9740
- });
9741
- if (isError) {
9742
- throw error;
9743
- }
9744
- const isReady = !isPending && !!order;
9745
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9746
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
9747
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Email" }) }),
9748
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
9749
- ] }),
9750
- isReady && /* @__PURE__ */ jsxRuntime.jsx(EmailForm, { order })
9751
- ] });
9752
- };
9753
- const EmailForm = ({ order }) => {
9754
- const form = reactHookForm.useForm({
9755
- defaultValues: {
9756
- email: order.email ?? ""
9757
- },
9758
- resolver: zod.zodResolver(schema$4)
9759
- });
9760
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9761
- const { handleSuccess } = useRouteModal();
9762
- const onSubmit = form.handleSubmit(async (data) => {
9763
- await mutateAsync(
9764
- { email: data.email },
9765
- {
9766
- onSuccess: () => {
9767
- handleSuccess();
9768
- },
9769
- onError: (error) => {
9770
- ui.toast.error(error.message);
9771
- }
9772
- }
9773
- );
9774
- });
9775
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
9776
- KeyboundForm,
9777
- {
9778
- className: "flex flex-1 flex-col overflow-hidden",
9779
- onSubmit,
9780
- children: [
9781
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
9782
- Form$2.Field,
9783
- {
9784
- control: form.control,
9785
- name: "email",
9786
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
9787
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Email" }),
9788
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
9789
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
9790
- ] })
9791
- }
9792
- ) }),
9793
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9794
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9795
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9796
- ] }) })
9797
- ]
9798
- }
9799
- ) });
9800
- };
9801
- const schema$4 = z.object({
9802
- email: z.string().email()
9803
- });
9804
9715
  const BillingAddress = () => {
9805
9716
  const { id } = reactRouterDom.useParams();
9806
9717
  const { order, isPending, isError, error } = useOrder(id, {
@@ -9833,7 +9744,7 @@ const BillingAddressForm = ({ order }) => {
9833
9744
  postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
9834
9745
  phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
9835
9746
  },
9836
- resolver: zod.zodResolver(schema$3)
9747
+ resolver: zod.zodResolver(schema$5)
9837
9748
  });
9838
9749
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9839
9750
  const { handleSuccess } = useRouteModal();
@@ -9990,514 +9901,523 @@ const BillingAddressForm = ({ order }) => {
9990
9901
  }
9991
9902
  ) });
9992
9903
  };
9993
- const schema$3 = addressSchema;
9994
- const PROMOTION_QUERY_KEY = "promotions";
9995
- const promotionsQueryKeys = {
9996
- list: (query2) => [
9997
- PROMOTION_QUERY_KEY,
9998
- query2 ? query2 : void 0
9999
- ],
10000
- detail: (id, query2) => [
10001
- PROMOTION_QUERY_KEY,
10002
- id,
10003
- query2 ? query2 : void 0
10004
- ]
9904
+ const schema$5 = addressSchema;
9905
+ const CustomItems = () => {
9906
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9907
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Custom Items" }) }) }),
9908
+ /* @__PURE__ */ jsxRuntime.jsx(CustomItemsForm, {})
9909
+ ] });
10005
9910
  };
10006
- const usePromotions = (query2, options) => {
10007
- const { data, ...rest } = reactQuery.useQuery({
10008
- queryKey: promotionsQueryKeys.list(query2),
10009
- queryFn: async () => sdk.admin.promotion.list(query2),
10010
- ...options
9911
+ const CustomItemsForm = () => {
9912
+ const form = reactHookForm.useForm({
9913
+ resolver: zod.zodResolver(schema$4)
10011
9914
  });
10012
- return { ...data, ...rest };
10013
- };
10014
- const useCancelOrderEdit = ({ preview }) => {
10015
- const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
10016
- const onCancel = React.useCallback(async () => {
10017
- if (!preview) {
10018
- return true;
10019
- }
10020
- let res = false;
10021
- await cancelOrderEdit(void 0, {
10022
- onError: (e) => {
10023
- ui.toast.error(e.message);
10024
- },
10025
- onSuccess: () => {
10026
- res = true;
10027
- }
10028
- });
10029
- return res;
10030
- }, [preview, cancelOrderEdit]);
10031
- return { onCancel };
9915
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9916
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, {}),
9917
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
9918
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9919
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", children: "Save" })
9920
+ ] }) })
9921
+ ] }) });
10032
9922
  };
10033
- let IS_REQUEST_RUNNING = false;
10034
- const useInitiateOrderEdit = ({
10035
- preview
10036
- }) => {
10037
- const navigate = reactRouterDom.useNavigate();
10038
- const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
10039
- React.useEffect(() => {
10040
- async function run() {
10041
- if (IS_REQUEST_RUNNING || !preview) {
10042
- return;
10043
- }
10044
- if (preview.order_change) {
10045
- return;
9923
+ const schema$4 = z.object({
9924
+ email: z.string().email()
9925
+ });
9926
+ const InlineTip = React.forwardRef(
9927
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
9928
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
9929
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9930
+ "div",
9931
+ {
9932
+ ref,
9933
+ className: ui.clx(
9934
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
9935
+ className
9936
+ ),
9937
+ ...props,
9938
+ children: [
9939
+ /* @__PURE__ */ jsxRuntime.jsx(
9940
+ "div",
9941
+ {
9942
+ role: "presentation",
9943
+ className: ui.clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
9944
+ "bg-ui-tag-orange-icon": variant === "warning"
9945
+ })
9946
+ }
9947
+ ),
9948
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-pretty", children: [
9949
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
9950
+ labelValue,
9951
+ ":"
9952
+ ] }),
9953
+ " ",
9954
+ children
9955
+ ] })
9956
+ ]
10046
9957
  }
10047
- IS_REQUEST_RUNNING = true;
10048
- await mutateAsync(void 0, {
10049
- onError: (e) => {
10050
- ui.toast.error(e.message);
10051
- navigate(`/draft-orders/${preview.id}`, { replace: true });
10052
- return;
10053
- }
10054
- });
10055
- IS_REQUEST_RUNNING = false;
10056
- }
10057
- run();
10058
- }, [preview, navigate, mutateAsync]);
10059
- };
10060
- const Promotions = () => {
9958
+ );
9959
+ }
9960
+ );
9961
+ InlineTip.displayName = "InlineTip";
9962
+ const MetadataFieldSchema = z.object({
9963
+ key: z.string(),
9964
+ disabled: z.boolean().optional(),
9965
+ value: z.any()
9966
+ });
9967
+ const MetadataSchema = z.object({
9968
+ metadata: z.array(MetadataFieldSchema)
9969
+ });
9970
+ const Metadata = () => {
10061
9971
  const { id } = reactRouterDom.useParams();
10062
- const {
10063
- order: preview,
10064
- isError: isPreviewError,
10065
- error: previewError
10066
- } = useOrderPreview(id, void 0);
10067
- useInitiateOrderEdit({ preview });
10068
- const { onCancel } = useCancelOrderEdit({ preview });
10069
- if (isPreviewError) {
10070
- throw previewError;
9972
+ const { order, isPending, isError, error } = useOrder(id, {
9973
+ fields: "metadata"
9974
+ });
9975
+ if (isError) {
9976
+ throw error;
10071
9977
  }
10072
- const isReady = !!preview;
10073
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { onClose: onCancel, children: [
10074
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Promotions" }) }) }),
10075
- isReady && /* @__PURE__ */ jsxRuntime.jsx(PromotionForm, { preview })
9978
+ const isReady = !isPending && !!order;
9979
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
9980
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
9981
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Metadata" }) }),
9982
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
9983
+ ] }),
9984
+ !isReady ? /* @__PURE__ */ jsxRuntime.jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10076
9985
  ] });
10077
9986
  };
10078
- const PromotionForm = ({ preview }) => {
10079
- const { items, shipping_methods } = preview;
10080
- const [isSubmitting, setIsSubmitting] = React.useState(false);
10081
- const [comboboxValue, setComboboxValue] = React.useState("");
9987
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
9988
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
9989
+ const MetadataForm = ({ orderId, metadata }) => {
10082
9990
  const { handleSuccess } = useRouteModal();
10083
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10084
- const promoCodes = getPromotionCodes(items, shipping_methods);
10085
- const { promotions, isPending, isError, error } = usePromotions(
10086
- {
10087
- code: promoCodes
10088
- },
10089
- {
10090
- enabled: !!promoCodes.length
10091
- }
10092
- );
10093
- const comboboxData = useComboboxData({
10094
- queryKey: ["promotions", "combobox", promoCodes],
10095
- queryFn: async (params) => {
10096
- return await sdk.admin.promotion.list({
10097
- ...params,
10098
- code: {
10099
- $nin: promoCodes
10100
- }
10101
- });
9991
+ const hasUneditableRows = getHasUneditableRows(metadata);
9992
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
9993
+ const form = reactHookForm.useForm({
9994
+ defaultValues: {
9995
+ metadata: getDefaultValues(metadata)
10102
9996
  },
10103
- getOptions: (data) => {
10104
- return data.promotions.map((promotion) => ({
10105
- label: promotion.code,
10106
- value: promotion.code
10107
- }));
10108
- }
9997
+ resolver: zod.zodResolver(MetadataSchema)
10109
9998
  });
10110
- const add = async (value) => {
10111
- if (!value) {
10112
- return;
10113
- }
10114
- addPromotions(
9999
+ const handleSubmit = form.handleSubmit(async (data) => {
10000
+ const parsedData = parseValues(data);
10001
+ await mutateAsync(
10115
10002
  {
10116
- promo_codes: [value]
10003
+ metadata: parsedData
10117
10004
  },
10118
10005
  {
10119
- onError: (e) => {
10120
- ui.toast.error(e.message);
10121
- comboboxData.onSearchValueChange("");
10122
- setComboboxValue("");
10123
- },
10124
10006
  onSuccess: () => {
10125
- comboboxData.onSearchValueChange("");
10126
- setComboboxValue("");
10007
+ ui.toast.success("Metadata updated");
10008
+ handleSuccess();
10009
+ },
10010
+ onError: (error) => {
10011
+ ui.toast.error(error.message);
10127
10012
  }
10128
10013
  }
10129
10014
  );
10130
- };
10131
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10132
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10133
- const onSubmit = async () => {
10134
- setIsSubmitting(true);
10135
- let requestSucceeded = false;
10136
- await requestOrderEdit(void 0, {
10137
- onError: (e) => {
10138
- ui.toast.error(e.message);
10139
- },
10140
- onSuccess: () => {
10141
- requestSucceeded = true;
10142
- }
10143
- });
10144
- if (!requestSucceeded) {
10145
- setIsSubmitting(false);
10146
- return;
10015
+ });
10016
+ const { fields, insert, remove } = reactHookForm.useFieldArray({
10017
+ control: form.control,
10018
+ name: "metadata"
10019
+ });
10020
+ function deleteRow(index) {
10021
+ remove(index);
10022
+ if (fields.length === 1) {
10023
+ insert(0, {
10024
+ key: "",
10025
+ value: "",
10026
+ disabled: false
10027
+ });
10147
10028
  }
10148
- await confirmOrderEdit(void 0, {
10149
- onError: (e) => {
10150
- ui.toast.error(e.message);
10151
- },
10152
- onSuccess: () => {
10153
- handleSuccess();
10154
- },
10155
- onSettled: () => {
10156
- setIsSubmitting(false);
10157
- }
10029
+ }
10030
+ function insertRow(index, position) {
10031
+ insert(index + (position === "above" ? 0 : 1), {
10032
+ key: "",
10033
+ value: "",
10034
+ disabled: false
10158
10035
  });
10159
- };
10160
- if (isError) {
10161
- throw error;
10162
10036
  }
10163
- return /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10164
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
10165
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
10166
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10167
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10168
- /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10169
- ] }),
10170
- /* @__PURE__ */ jsxRuntime.jsx(
10171
- Combobox,
10172
- {
10173
- id: "promotion-combobox",
10174
- "aria-describedby": "promotion-combobox-hint",
10175
- isFetchingNextPage: comboboxData.isFetchingNextPage,
10176
- fetchNextPage: comboboxData.fetchNextPage,
10177
- options: comboboxData.options,
10178
- onSearchValueChange: comboboxData.onSearchValueChange,
10179
- searchValue: comboboxData.searchValue,
10180
- disabled: comboboxData.disabled || isAddingPromotions,
10181
- onChange: add,
10182
- value: comboboxValue
10183
- }
10184
- )
10185
- ] }),
10186
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10187
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsxRuntime.jsx(
10188
- PromotionItem,
10189
- {
10190
- promotion,
10191
- orderId: preview.id,
10192
- isLoading: isPending
10193
- },
10194
- promotion.id
10195
- )) })
10196
- ] }) }),
10197
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
10198
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10199
- /* @__PURE__ */ jsxRuntime.jsx(
10200
- ui.Button,
10201
- {
10202
- size: "small",
10203
- type: "submit",
10204
- isLoading: isSubmitting || isAddingPromotions,
10205
- children: "Save"
10206
- }
10207
- )
10208
- ] }) })
10209
- ] });
10210
- };
10211
- const PromotionItem = ({
10212
- promotion,
10213
- orderId,
10214
- isLoading
10215
- }) => {
10216
- var _a;
10217
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10218
- const onRemove = async () => {
10219
- removePromotions(
10220
- {
10221
- promo_codes: [promotion.code]
10222
- },
10223
- {
10224
- onError: (e) => {
10225
- ui.toast.error(e.message);
10226
- }
10227
- }
10228
- );
10229
- };
10230
- const displayValue = getDisplayValue(promotion);
10231
- return /* @__PURE__ */ jsxRuntime.jsxs(
10232
- "div",
10037
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
10038
+ KeyboundForm,
10233
10039
  {
10234
- className: ui.clx(
10235
- "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
10236
- {
10237
- "animate-pulse": isLoading
10238
- }
10239
- ),
10040
+ onSubmit: handleSubmit,
10041
+ className: "flex flex-1 flex-col overflow-hidden",
10240
10042
  children: [
10241
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10242
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10243
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
10244
- displayValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
10245
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: displayValue }),
10246
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: "·" })
10043
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10044
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10045
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10046
+ /* @__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" }) }),
10047
+ /* @__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" }) })
10247
10048
  ] }),
10248
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10249
- ] })
10250
- ] }),
10251
- /* @__PURE__ */ jsxRuntime.jsx(
10252
- ui.IconButton,
10253
- {
10254
- size: "small",
10255
- type: "button",
10256
- variant: "transparent",
10257
- onClick: onRemove,
10258
- isLoading: isPending || isLoading,
10259
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.XMark, {})
10260
- }
10261
- )
10262
- ]
10263
- },
10264
- promotion.id
10265
- );
10266
- };
10267
- function getDisplayValue(promotion) {
10268
- var _a, _b, _c, _d;
10269
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10270
- if (!value) {
10271
- return null;
10272
- }
10273
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10274
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10275
- if (!currency) {
10276
- return null;
10277
- }
10278
- return getLocaleAmount(value, currency);
10279
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10280
- return formatPercentage(value);
10281
- }
10282
- return null;
10283
- }
10284
- const formatter = new Intl.NumberFormat([], {
10285
- style: "percent",
10286
- minimumFractionDigits: 2
10287
- });
10288
- const formatPercentage = (value, isPercentageValue = false) => {
10289
- let val = value || 0;
10290
- if (!isPercentageValue) {
10291
- val = val / 100;
10292
- }
10293
- return formatter.format(val);
10294
- };
10295
- function getPromotionCodes(items, shippingMethods) {
10296
- const codes = /* @__PURE__ */ new Set();
10297
- for (const item of items) {
10298
- if (item.adjustments) {
10299
- for (const adjustment of item.adjustments) {
10300
- if (adjustment.code) {
10301
- codes.add(adjustment.code);
10302
- }
10303
- }
10304
- }
10305
- }
10306
- for (const shippingMethod of shippingMethods) {
10307
- if (shippingMethod.adjustments) {
10308
- for (const adjustment of shippingMethod.adjustments) {
10309
- if (adjustment.code) {
10310
- codes.add(adjustment.code);
10311
- }
10312
- }
10313
- }
10314
- }
10315
- return Array.from(codes);
10316
- }
10317
- const NumberInput = React.forwardRef(
10318
- ({
10319
- value,
10320
- onChange,
10321
- size = "base",
10322
- min = 0,
10323
- max = 100,
10324
- step = 1,
10325
- className,
10326
- disabled,
10327
- ...props
10328
- }, ref) => {
10329
- const handleChange = (event) => {
10330
- const newValue = event.target.value === "" ? min : Number(event.target.value);
10331
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
10332
- onChange(newValue);
10333
- }
10334
- };
10335
- const handleIncrement = () => {
10336
- const newValue = value + step;
10337
- if (max === void 0 || newValue <= max) {
10338
- onChange(newValue);
10049
+ fields.map((field, index) => {
10050
+ const isDisabled = field.disabled || false;
10051
+ let placeholder = "-";
10052
+ if (typeof field.value === "object") {
10053
+ placeholder = "{ ... }";
10054
+ }
10055
+ if (Array.isArray(field.value)) {
10056
+ placeholder = "[ ... ]";
10057
+ }
10058
+ return /* @__PURE__ */ jsxRuntime.jsx(
10059
+ ConditionalTooltip,
10060
+ {
10061
+ showTooltip: isDisabled,
10062
+ content: "This row is disabled because it contains non-primitive data.",
10063
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/table relative", children: [
10064
+ /* @__PURE__ */ jsxRuntime.jsxs(
10065
+ "div",
10066
+ {
10067
+ className: ui.clx("grid grid-cols-2 divide-x", {
10068
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
10069
+ }),
10070
+ children: [
10071
+ /* @__PURE__ */ jsxRuntime.jsx(
10072
+ Form$2.Field,
10073
+ {
10074
+ control: form.control,
10075
+ name: `metadata.${index}.key`,
10076
+ render: ({ field: field2 }) => {
10077
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10078
+ GridInput,
10079
+ {
10080
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
10081
+ ...field2,
10082
+ disabled: isDisabled,
10083
+ placeholder: "Key"
10084
+ }
10085
+ ) }) });
10086
+ }
10087
+ }
10088
+ ),
10089
+ /* @__PURE__ */ jsxRuntime.jsx(
10090
+ Form$2.Field,
10091
+ {
10092
+ control: form.control,
10093
+ name: `metadata.${index}.value`,
10094
+ render: ({ field: { value, ...field2 } }) => {
10095
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10096
+ GridInput,
10097
+ {
10098
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
10099
+ ...field2,
10100
+ value: isDisabled ? placeholder : value,
10101
+ disabled: isDisabled,
10102
+ placeholder: "Value"
10103
+ }
10104
+ ) }) });
10105
+ }
10106
+ }
10107
+ )
10108
+ ]
10109
+ }
10110
+ ),
10111
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
10112
+ /* @__PURE__ */ jsxRuntime.jsx(
10113
+ ui.DropdownMenu.Trigger,
10114
+ {
10115
+ className: ui.clx(
10116
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10117
+ {
10118
+ hidden: isDisabled
10119
+ }
10120
+ ),
10121
+ disabled: isDisabled,
10122
+ asChild: true,
10123
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisVertical, {}) })
10124
+ }
10125
+ ),
10126
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
10127
+ /* @__PURE__ */ jsxRuntime.jsxs(
10128
+ ui.DropdownMenu.Item,
10129
+ {
10130
+ className: "gap-x-2",
10131
+ onClick: () => insertRow(index, "above"),
10132
+ children: [
10133
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpMini, { className: "text-ui-fg-subtle" }),
10134
+ "Insert row above"
10135
+ ]
10136
+ }
10137
+ ),
10138
+ /* @__PURE__ */ jsxRuntime.jsxs(
10139
+ ui.DropdownMenu.Item,
10140
+ {
10141
+ className: "gap-x-2",
10142
+ onClick: () => insertRow(index, "below"),
10143
+ children: [
10144
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownMini, { className: "text-ui-fg-subtle" }),
10145
+ "Insert row below"
10146
+ ]
10147
+ }
10148
+ ),
10149
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
10150
+ /* @__PURE__ */ jsxRuntime.jsxs(
10151
+ ui.DropdownMenu.Item,
10152
+ {
10153
+ className: "gap-x-2",
10154
+ onClick: () => deleteRow(index),
10155
+ children: [
10156
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
10157
+ "Delete row"
10158
+ ]
10159
+ }
10160
+ )
10161
+ ] })
10162
+ ] })
10163
+ ] })
10164
+ },
10165
+ field.id
10166
+ );
10167
+ })
10168
+ ] }),
10169
+ 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." })
10170
+ ] }),
10171
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10172
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10173
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10174
+ ] }) })
10175
+ ]
10176
+ }
10177
+ ) });
10178
+ };
10179
+ const GridInput = React.forwardRef(({ className, ...props }, ref) => {
10180
+ return /* @__PURE__ */ jsxRuntime.jsx(
10181
+ "input",
10182
+ {
10183
+ ref,
10184
+ ...props,
10185
+ autoComplete: "off",
10186
+ className: ui.clx(
10187
+ "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",
10188
+ className
10189
+ )
10190
+ }
10191
+ );
10192
+ });
10193
+ GridInput.displayName = "MetadataForm.GridInput";
10194
+ const PlaceholderInner = () => {
10195
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10196
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10197
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10198
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" }),
10199
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" })
10200
+ ] }) })
10201
+ ] });
10202
+ };
10203
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
10204
+ function getDefaultValues(metadata) {
10205
+ if (!metadata || !Object.keys(metadata).length) {
10206
+ return [
10207
+ {
10208
+ key: "",
10209
+ value: "",
10210
+ disabled: false
10339
10211
  }
10212
+ ];
10213
+ }
10214
+ return Object.entries(metadata).map(([key, value]) => {
10215
+ if (!EDITABLE_TYPES.includes(typeof value)) {
10216
+ return {
10217
+ key,
10218
+ value,
10219
+ disabled: true
10220
+ };
10221
+ }
10222
+ let stringValue = value;
10223
+ if (typeof value !== "string") {
10224
+ stringValue = JSON.stringify(value);
10225
+ }
10226
+ return {
10227
+ key,
10228
+ value: stringValue,
10229
+ original_key: key
10340
10230
  };
10341
- const handleDecrement = () => {
10342
- const newValue = value - step;
10343
- if (min === void 0 || newValue >= min) {
10344
- onChange(newValue);
10231
+ });
10232
+ }
10233
+ function parseValues(values) {
10234
+ const metadata = values.metadata;
10235
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10236
+ if (isEmpty) {
10237
+ return null;
10238
+ }
10239
+ const update = {};
10240
+ metadata.forEach((field) => {
10241
+ let key = field.key;
10242
+ let value = field.value;
10243
+ const disabled = field.disabled;
10244
+ if (!key || !value) {
10245
+ return;
10246
+ }
10247
+ if (disabled) {
10248
+ update[key] = value;
10249
+ return;
10250
+ }
10251
+ key = key.trim();
10252
+ value = value.trim();
10253
+ if (value === "true") {
10254
+ update[key] = true;
10255
+ } else if (value === "false") {
10256
+ update[key] = false;
10257
+ } else {
10258
+ const parsedNumber = parseFloat(value);
10259
+ if (!isNaN(parsedNumber)) {
10260
+ update[key] = parsedNumber;
10261
+ } else {
10262
+ update[key] = value;
10345
10263
  }
10346
- };
10347
- return /* @__PURE__ */ jsxRuntime.jsxs(
10348
- "div",
10349
- {
10350
- className: ui.clx(
10351
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
10352
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
10353
- {
10354
- "h-7": size === "small",
10355
- "h-8": size === "base"
10356
- },
10357
- className
10358
- ),
10359
- children: [
10360
- /* @__PURE__ */ jsxRuntime.jsx(
10361
- "input",
10362
- {
10363
- ref,
10364
- type: "number",
10365
- value,
10366
- onChange: handleChange,
10367
- min,
10368
- max,
10369
- step,
10370
- className: ui.clx(
10371
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
10372
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
10373
- "placeholder:text-ui-fg-muted"
10374
- ),
10375
- ...props
10376
- }
10377
- ),
10378
- /* @__PURE__ */ jsxRuntime.jsxs(
10379
- "button",
10380
- {
10381
- className: ui.clx(
10382
- "flex items-center justify-center outline-none transition-fg",
10383
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10384
- "focus:bg-ui-bg-field-component-hover",
10385
- "hover:bg-ui-bg-field-component-hover",
10386
- {
10387
- "size-7": size === "small",
10388
- "size-8": size === "base"
10389
- }
10390
- ),
10391
- type: "button",
10392
- onClick: handleDecrement,
10393
- disabled: min !== void 0 && value <= min || disabled,
10394
- children: [
10395
- /* @__PURE__ */ jsxRuntime.jsx(icons.Minus, {}),
10396
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
10397
- ]
10398
- }
10399
- ),
10400
- /* @__PURE__ */ jsxRuntime.jsxs(
10401
- "button",
10402
- {
10403
- className: ui.clx(
10404
- "flex items-center justify-center outline-none transition-fg",
10405
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10406
- "focus:bg-ui-bg-field-hover",
10407
- "hover:bg-ui-bg-field-hover",
10408
- {
10409
- "size-7": size === "small",
10410
- "size-8": size === "base"
10411
- }
10412
- ),
10413
- type: "button",
10414
- onClick: handleIncrement,
10415
- disabled: max !== void 0 && value >= max || disabled,
10416
- children: [
10417
- /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
10418
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Increase by ${step}` })
10419
- ]
10420
- }
10421
- )
10422
- ]
10423
- }
10424
- );
10264
+ }
10265
+ });
10266
+ return update;
10267
+ }
10268
+ function getHasUneditableRows(metadata) {
10269
+ if (!metadata) {
10270
+ return false;
10425
10271
  }
10426
- );
10427
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
10428
- const productVariantsQueryKeys = {
10272
+ return Object.values(metadata).some(
10273
+ (value) => !EDITABLE_TYPES.includes(typeof value)
10274
+ );
10275
+ }
10276
+ const PROMOTION_QUERY_KEY = "promotions";
10277
+ const promotionsQueryKeys = {
10429
10278
  list: (query2) => [
10430
- PRODUCT_VARIANTS_QUERY_KEY,
10279
+ PROMOTION_QUERY_KEY,
10280
+ query2 ? query2 : void 0
10281
+ ],
10282
+ detail: (id, query2) => [
10283
+ PROMOTION_QUERY_KEY,
10284
+ id,
10431
10285
  query2 ? query2 : void 0
10432
10286
  ]
10433
10287
  };
10434
- const useProductVariants = (query2, options) => {
10288
+ const usePromotions = (query2, options) => {
10435
10289
  const { data, ...rest } = reactQuery.useQuery({
10436
- queryKey: productVariantsQueryKeys.list(query2),
10437
- queryFn: async () => await sdk.admin.productVariant.list(query2),
10290
+ queryKey: promotionsQueryKeys.list(query2),
10291
+ queryFn: async () => sdk.admin.promotion.list(query2),
10438
10292
  ...options
10439
10293
  });
10440
10294
  return { ...data, ...rest };
10441
10295
  };
10442
- function convertNumber(value) {
10443
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10444
- }
10445
- const STACKED_MODAL_ID = "items_stacked_modal";
10446
- const Items = () => {
10296
+ const useCancelOrderEdit = ({ preview }) => {
10297
+ const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
10298
+ const onCancel = React.useCallback(async () => {
10299
+ if (!preview) {
10300
+ return true;
10301
+ }
10302
+ let res = false;
10303
+ await cancelOrderEdit(void 0, {
10304
+ onError: (e) => {
10305
+ ui.toast.error(e.message);
10306
+ },
10307
+ onSuccess: () => {
10308
+ res = true;
10309
+ }
10310
+ });
10311
+ return res;
10312
+ }, [preview, cancelOrderEdit]);
10313
+ return { onCancel };
10314
+ };
10315
+ let IS_REQUEST_RUNNING = false;
10316
+ const useInitiateOrderEdit = ({
10317
+ preview
10318
+ }) => {
10319
+ const navigate = reactRouterDom.useNavigate();
10320
+ const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
10321
+ React.useEffect(() => {
10322
+ async function run() {
10323
+ if (IS_REQUEST_RUNNING || !preview) {
10324
+ return;
10325
+ }
10326
+ if (preview.order_change) {
10327
+ return;
10328
+ }
10329
+ IS_REQUEST_RUNNING = true;
10330
+ await mutateAsync(void 0, {
10331
+ onError: (e) => {
10332
+ ui.toast.error(e.message);
10333
+ navigate(`/draft-orders/${preview.id}`, { replace: true });
10334
+ return;
10335
+ }
10336
+ });
10337
+ IS_REQUEST_RUNNING = false;
10338
+ }
10339
+ run();
10340
+ }, [preview, navigate, mutateAsync]);
10341
+ };
10342
+ const Promotions = () => {
10447
10343
  const { id } = reactRouterDom.useParams();
10448
10344
  const {
10449
10345
  order: preview,
10450
- isPending: isPreviewPending,
10451
10346
  isError: isPreviewError,
10452
10347
  error: previewError
10453
- } = useOrderPreview(id, void 0, {
10454
- placeholderData: reactQuery.keepPreviousData
10455
- });
10348
+ } = useOrderPreview(id, void 0);
10456
10349
  useInitiateOrderEdit({ preview });
10457
- const { draft_order, isPending, isError, error } = useDraftOrder(
10458
- id,
10459
- {
10460
- fields: "currency_code"
10461
- },
10462
- {
10463
- enabled: !!id
10464
- }
10465
- );
10466
10350
  const { onCancel } = useCancelOrderEdit({ preview });
10467
- if (isError) {
10468
- throw error;
10469
- }
10470
10351
  if (isPreviewError) {
10471
10352
  throw previewError;
10472
10353
  }
10473
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10474
- return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsxRuntime.jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10475
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10476
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10477
- ] }) });
10354
+ const isReady = !!preview;
10355
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { onClose: onCancel, children: [
10356
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Promotions" }) }) }),
10357
+ isReady && /* @__PURE__ */ jsxRuntime.jsx(PromotionForm, { preview })
10358
+ ] });
10478
10359
  };
10479
- const ItemsForm = ({ preview, currencyCode }) => {
10480
- var _a;
10360
+ const PromotionForm = ({ preview }) => {
10361
+ const { items, shipping_methods } = preview;
10481
10362
  const [isSubmitting, setIsSubmitting] = React.useState(false);
10482
- const [modalContent, setModalContent] = React.useState(
10483
- null
10484
- );
10363
+ const [comboboxValue, setComboboxValue] = React.useState("");
10485
10364
  const { handleSuccess } = useRouteModal();
10486
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10365
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10366
+ const promoCodes = getPromotionCodes(items, shipping_methods);
10367
+ const { promotions, isPending, isError, error } = usePromotions(
10368
+ {
10369
+ code: promoCodes
10370
+ },
10371
+ {
10372
+ enabled: !!promoCodes.length
10373
+ }
10374
+ );
10375
+ const comboboxData = useComboboxData({
10376
+ queryKey: ["promotions", "combobox", promoCodes],
10377
+ queryFn: async (params) => {
10378
+ return await sdk.admin.promotion.list({
10379
+ ...params,
10380
+ code: {
10381
+ $nin: promoCodes
10382
+ }
10383
+ });
10384
+ },
10385
+ getOptions: (data) => {
10386
+ return data.promotions.map((promotion) => ({
10387
+ label: promotion.code,
10388
+ value: promotion.code
10389
+ }));
10390
+ }
10391
+ });
10392
+ const add = async (value) => {
10393
+ if (!value) {
10394
+ return;
10395
+ }
10396
+ addPromotions(
10397
+ {
10398
+ promo_codes: [value]
10399
+ },
10400
+ {
10401
+ onError: (e) => {
10402
+ ui.toast.error(e.message);
10403
+ comboboxData.onSearchValueChange("");
10404
+ setComboboxValue("");
10405
+ },
10406
+ onSuccess: () => {
10407
+ comboboxData.onSearchValueChange("");
10408
+ setComboboxValue("");
10409
+ }
10410
+ }
10411
+ );
10412
+ };
10487
10413
  const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10488
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10489
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10490
- const matches = React.useMemo(() => {
10491
- return matchSorter.matchSorter(preview.items, query2, {
10492
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10493
- });
10494
- }, [preview.items, query2]);
10414
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10495
10415
  const onSubmit = async () => {
10496
10416
  setIsSubmitting(true);
10497
10417
  let requestSucceeded = false;
10498
10418
  await requestOrderEdit(void 0, {
10499
10419
  onError: (e) => {
10500
- ui.toast.error(`Failed to request order edit: ${e.message}`);
10420
+ ui.toast.error(e.message);
10501
10421
  },
10502
10422
  onSuccess: () => {
10503
10423
  requestSucceeded = true;
@@ -10509,7 +10429,7 @@ const ItemsForm = ({ preview, currencyCode }) => {
10509
10429
  }
10510
10430
  await confirmOrderEdit(void 0, {
10511
10431
  onError: (e) => {
10512
- ui.toast.error(`Failed to confirm order edit: ${e.message}`);
10432
+ ui.toast.error(e.message);
10513
10433
  },
10514
10434
  onSuccess: () => {
10515
10435
  handleSuccess();
@@ -10519,1206 +10439,293 @@ const ItemsForm = ({ preview, currencyCode }) => {
10519
10439
  }
10520
10440
  });
10521
10441
  };
10522
- const onKeyDown = React.useCallback(
10523
- (e) => {
10524
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10525
- if (modalContent || isSubmitting) {
10526
- return;
10527
- }
10528
- onSubmit();
10529
- }
10530
- },
10531
- [modalContent, isSubmitting, onSubmit]
10532
- );
10533
- React.useEffect(() => {
10534
- document.addEventListener("keydown", onKeyDown);
10535
- return () => {
10536
- document.removeEventListener("keydown", onKeyDown);
10537
- };
10538
- }, [onKeyDown]);
10539
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10540
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
10541
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
10542
- StackedFocusModal,
10543
- {
10544
- id: STACKED_MODAL_ID,
10545
- onOpenChangeCallback: (open) => {
10546
- if (!open) {
10547
- setModalContent(null);
10442
+ if (isError) {
10443
+ throw error;
10444
+ }
10445
+ return /* @__PURE__ */ jsxRuntime.jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10446
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
10447
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
10448
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10449
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10450
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
10451
+ ] }),
10452
+ /* @__PURE__ */ jsxRuntime.jsx(
10453
+ Combobox,
10454
+ {
10455
+ id: "promotion-combobox",
10456
+ "aria-describedby": "promotion-combobox-hint",
10457
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
10458
+ fetchNextPage: comboboxData.fetchNextPage,
10459
+ options: comboboxData.options,
10460
+ onSearchValueChange: comboboxData.onSearchValueChange,
10461
+ searchValue: comboboxData.searchValue,
10462
+ disabled: comboboxData.disabled || isAddingPromotions,
10463
+ onChange: add,
10464
+ value: comboboxValue
10548
10465
  }
10466
+ )
10467
+ ] }),
10468
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10469
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsxRuntime.jsx(
10470
+ PromotionItem,
10471
+ {
10472
+ promotion,
10473
+ orderId: preview.id,
10474
+ isLoading: isPending
10549
10475
  },
10550
- children: [
10551
- /* @__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: [
10552
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10553
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Items" }) }),
10554
- /* @__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." }) })
10555
- ] }),
10556
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10557
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
10558
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10559
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10560
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10561
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10562
- ] }),
10563
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
10564
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
10565
- ui.Input,
10566
- {
10567
- type: "search",
10568
- placeholder: "Search items",
10569
- value: searchValue,
10570
- onChange: (e) => onSearchValueChange(e.target.value)
10571
- }
10572
- ) }),
10573
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
10574
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}) }) }),
10575
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
10576
- /* @__PURE__ */ jsxRuntime.jsx(
10577
- StackedModalTrigger$1,
10578
- {
10579
- type: "add-items",
10580
- setModalContent
10581
- }
10582
- ),
10583
- /* @__PURE__ */ jsxRuntime.jsx(
10584
- StackedModalTrigger$1,
10585
- {
10586
- type: "add-custom-item",
10587
- setModalContent
10588
- }
10589
- )
10590
- ] })
10591
- ] })
10592
- ] })
10593
- ] }),
10594
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10595
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
10596
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Item" }) }),
10597
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10598
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Price" }) }),
10599
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10600
- ] }) }),
10601
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10602
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10603
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10604
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
10605
- Item,
10606
- {
10607
- item,
10608
- preview,
10609
- currencyCode
10610
- },
10611
- item.id
10612
- )) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
10613
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10614
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
10615
- 'No items found for "',
10616
- query2,
10617
- '".'
10618
- ] })
10619
- ] }) })
10620
- ] })
10621
- ] }),
10622
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10623
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10624
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10625
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(
10626
- ui.Text,
10627
- {
10628
- size: "small",
10629
- leading: "compact",
10630
- className: "text-ui-fg-subtle",
10631
- children: [
10632
- itemCount,
10633
- " ",
10634
- itemCount === 1 ? "item" : "items"
10635
- ]
10636
- }
10637
- ) }),
10638
- /* @__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) }) })
10639
- ] })
10640
- ] }) }),
10641
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsxRuntime.jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsxRuntime.jsx(
10642
- CustomItemForm,
10643
- {
10644
- orderId: preview.id,
10645
- currencyCode
10646
- }
10647
- ) : null)
10648
- ]
10649
- }
10650
- ) }),
10651
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
10652
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10476
+ promotion.id
10477
+ )) })
10478
+ ] }) }),
10479
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
10480
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10653
10481
  /* @__PURE__ */ jsxRuntime.jsx(
10654
10482
  ui.Button,
10655
10483
  {
10656
10484
  size: "small",
10657
- type: "button",
10658
- onClick: onSubmit,
10659
- isLoading: isSubmitting,
10485
+ type: "submit",
10486
+ isLoading: isSubmitting || isAddingPromotions,
10660
10487
  children: "Save"
10661
10488
  }
10662
10489
  )
10663
10490
  ] }) })
10664
10491
  ] });
10665
10492
  };
10666
- const Item = ({ item, preview, currencyCode }) => {
10667
- if (item.variant_id) {
10668
- return /* @__PURE__ */ jsxRuntime.jsx(VariantItem, { item, preview, currencyCode });
10669
- }
10670
- return /* @__PURE__ */ jsxRuntime.jsx(CustomItem, { item, preview, currencyCode });
10671
- };
10672
- const VariantItem = ({ item, preview, currencyCode }) => {
10673
- const [editing, setEditing] = React.useState(false);
10674
- const form = reactHookForm.useForm({
10675
- defaultValues: {
10676
- quantity: item.quantity,
10677
- unit_price: item.unit_price
10678
- },
10679
- resolver: zod.zodResolver(variantItemSchema)
10680
- });
10681
- const actionId = React.useMemo(() => {
10682
- var _a, _b;
10683
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10684
- }, [item]);
10685
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10686
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10687
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10688
- const onSubmit = form.handleSubmit(async (data) => {
10689
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10690
- setEditing(false);
10691
- return;
10692
- }
10693
- if (!actionId) {
10694
- await updateOriginalItem(
10695
- {
10696
- item_id: item.id,
10697
- quantity: data.quantity,
10698
- unit_price: convertNumber(data.unit_price)
10699
- },
10700
- {
10701
- onSuccess: () => {
10702
- setEditing(false);
10703
- },
10704
- onError: (e) => {
10705
- ui.toast.error(e.message);
10706
- }
10707
- }
10708
- );
10709
- return;
10710
- }
10711
- await updateActionItem(
10493
+ const PromotionItem = ({
10494
+ promotion,
10495
+ orderId,
10496
+ isLoading
10497
+ }) => {
10498
+ var _a;
10499
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10500
+ const onRemove = async () => {
10501
+ removePromotions(
10712
10502
  {
10713
- action_id: actionId,
10714
- quantity: data.quantity,
10715
- unit_price: convertNumber(data.unit_price)
10503
+ promo_codes: [promotion.code]
10716
10504
  },
10717
10505
  {
10718
- onSuccess: () => {
10719
- setEditing(false);
10720
- },
10721
10506
  onError: (e) => {
10722
10507
  ui.toast.error(e.message);
10723
10508
  }
10724
10509
  }
10725
10510
  );
10726
- });
10727
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10728
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
10729
- /* @__PURE__ */ jsxRuntime.jsx(
10730
- Thumbnail,
10511
+ };
10512
+ const displayValue = getDisplayValue(promotion);
10513
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10514
+ "div",
10515
+ {
10516
+ className: ui.clx(
10517
+ "px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
10731
10518
  {
10732
- thumbnail: item.thumbnail,
10733
- alt: item.product_title ?? void 0
10519
+ "animate-pulse": isLoading
10734
10520
  }
10735
10521
  ),
10736
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
10737
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
10738
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10739
- /* @__PURE__ */ jsxRuntime.jsxs(
10740
- ui.Text,
10741
- {
10742
- size: "small",
10743
- leading: "compact",
10744
- className: "text-ui-fg-subtle",
10745
- children: [
10746
- "(",
10747
- item.variant_title,
10748
- ")"
10749
- ]
10750
- }
10751
- )
10522
+ children: [
10523
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10524
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
10525
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-ui-fg-subtle", children: [
10526
+ displayValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
10527
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: displayValue }),
10528
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", children: "·" })
10529
+ ] }),
10530
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
10531
+ ] })
10752
10532
  ] }),
10753
10533
  /* @__PURE__ */ jsxRuntime.jsx(
10754
- ui.Text,
10534
+ ui.IconButton,
10755
10535
  {
10756
10536
  size: "small",
10757
- leading: "compact",
10758
- className: "text-ui-fg-subtle",
10759
- children: item.variant_sku
10537
+ type: "button",
10538
+ variant: "transparent",
10539
+ onClick: onRemove,
10540
+ isLoading: isPending || isLoading,
10541
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.XMark, {})
10760
10542
  }
10761
10543
  )
10762
- ] })
10763
- ] }),
10764
- editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
10765
- Form$2.Field,
10766
- {
10767
- control: form.control,
10768
- name: "quantity",
10769
- render: ({ field }) => {
10770
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
10544
+ ]
10545
+ },
10546
+ promotion.id
10547
+ );
10548
+ };
10549
+ function getDisplayValue(promotion) {
10550
+ var _a, _b, _c, _d;
10551
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
10552
+ if (!value) {
10553
+ return null;
10554
+ }
10555
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
10556
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
10557
+ if (!currency) {
10558
+ return null;
10559
+ }
10560
+ return getLocaleAmount(value, currency);
10561
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
10562
+ return formatPercentage(value);
10563
+ }
10564
+ return null;
10565
+ }
10566
+ const formatter = new Intl.NumberFormat([], {
10567
+ style: "percent",
10568
+ minimumFractionDigits: 2
10569
+ });
10570
+ const formatPercentage = (value, isPercentageValue = false) => {
10571
+ let val = value || 0;
10572
+ if (!isPercentageValue) {
10573
+ val = val / 100;
10574
+ }
10575
+ return formatter.format(val);
10576
+ };
10577
+ function getPromotionCodes(items, shippingMethods) {
10578
+ const codes = /* @__PURE__ */ new Set();
10579
+ for (const item of items) {
10580
+ if (item.adjustments) {
10581
+ for (const adjustment of item.adjustments) {
10582
+ if (adjustment.code) {
10583
+ codes.add(adjustment.code);
10771
10584
  }
10772
10585
  }
10773
- ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }) }),
10774
- editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
10775
- Form$2.Field,
10776
- {
10777
- control: form.control,
10778
- name: "unit_price",
10779
- render: ({ field: { onChange, ...field } }) => {
10780
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10781
- ui.CurrencyInput,
10782
- {
10783
- ...field,
10784
- symbol: getNativeSymbol(currencyCode),
10785
- code: currencyCode,
10786
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10787
- }
10788
- ) }) });
10586
+ }
10587
+ }
10588
+ for (const shippingMethod of shippingMethods) {
10589
+ if (shippingMethod.adjustments) {
10590
+ for (const adjustment of shippingMethod.adjustments) {
10591
+ if (adjustment.code) {
10592
+ codes.add(adjustment.code);
10789
10593
  }
10790
10594
  }
10791
- ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10792
- /* @__PURE__ */ jsxRuntime.jsx(
10793
- ui.IconButton,
10794
- {
10795
- type: "button",
10796
- size: "small",
10797
- onClick: editing ? onSubmit : () => {
10798
- setEditing(true);
10799
- },
10800
- disabled: isPending,
10801
- children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
10802
- }
10803
- )
10804
- ] }) }) });
10595
+ }
10596
+ }
10597
+ return Array.from(codes);
10598
+ }
10599
+ function convertNumber(value) {
10600
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10601
+ }
10602
+ const STACKED_FOCUS_MODAL_ID = "shipping-form";
10603
+ const Shipping = () => {
10604
+ var _a;
10605
+ const { id } = reactRouterDom.useParams();
10606
+ const { order, isPending, isError, error } = useOrder(id, {
10607
+ fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
10608
+ });
10609
+ const {
10610
+ order: preview,
10611
+ isPending: isPreviewPending,
10612
+ isError: isPreviewError,
10613
+ error: previewError
10614
+ } = useOrderPreview(id);
10615
+ useInitiateOrderEdit({ preview });
10616
+ const { onCancel } = useCancelOrderEdit({ preview });
10617
+ if (isError) {
10618
+ throw error;
10619
+ }
10620
+ if (isPreviewError) {
10621
+ throw previewError;
10622
+ }
10623
+ const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
10624
+ const isReady = preview && !isPreviewPending && order && !isPending;
10625
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
10626
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
10627
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.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 py-16 px-6", children: [
10628
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
10629
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
10630
+ ] }) }) }),
10631
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
10632
+ ] }) : isReady ? /* @__PURE__ */ jsxRuntime.jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10633
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
10634
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10635
+ ] }) });
10805
10636
  };
10806
- const variantItemSchema = z.object({
10807
- quantity: z.number(),
10808
- unit_price: z.union([z.number(), z.string()])
10809
- });
10810
- const CustomItem = ({ item, preview, currencyCode }) => {
10811
- const [editing, setEditing] = React.useState(false);
10812
- const { quantity, unit_price, title } = item;
10813
- const form = reactHookForm.useForm({
10814
- defaultValues: {
10815
- title,
10816
- quantity,
10817
- unit_price
10637
+ const ShippingForm = ({ preview, order }) => {
10638
+ var _a;
10639
+ const { setIsOpen } = useStackedModal();
10640
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
10641
+ const [data, setData] = React.useState(null);
10642
+ const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
10643
+ const { shipping_options } = useShippingOptions(
10644
+ {
10645
+ id: appliedShippingOptionIds,
10646
+ fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
10818
10647
  },
10819
- resolver: zod.zodResolver(customItemSchema)
10820
- });
10821
- React.useEffect(() => {
10822
- form.reset({
10823
- title,
10824
- quantity,
10825
- unit_price
10826
- });
10827
- }, [form, title, quantity, unit_price]);
10828
- const actionId = React.useMemo(() => {
10829
- var _a, _b;
10830
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10831
- }, [item]);
10832
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10833
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10834
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10835
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10836
- const onSubmit = form.handleSubmit(async (data) => {
10837
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10838
- setEditing(false);
10839
- return;
10840
- }
10841
- if (!actionId) {
10842
- await updateOriginalItem(
10843
- {
10844
- item_id: item.id,
10845
- quantity: data.quantity,
10846
- unit_price: convertNumber(data.unit_price)
10847
- },
10848
- {
10849
- onSuccess: () => {
10850
- setEditing(false);
10851
- },
10852
- onError: (e) => {
10853
- ui.toast.error(e.message);
10854
- }
10855
- }
10856
- );
10857
- return;
10648
+ {
10649
+ enabled: appliedShippingOptionIds.length > 0
10858
10650
  }
10859
- if (data.quantity === 0) {
10860
- await removeActionItem(actionId, {
10861
- onSuccess: () => {
10862
- setEditing(false);
10863
- },
10864
- onError: (e) => {
10865
- ui.toast.error(e.message);
10866
- }
10867
- });
10651
+ );
10652
+ const uniqueShippingProfiles = React.useMemo(() => {
10653
+ const profiles = /* @__PURE__ */ new Map();
10654
+ getUniqueShippingProfiles(order.items).forEach((profile) => {
10655
+ profiles.set(profile.id, profile);
10656
+ });
10657
+ shipping_options == null ? void 0 : shipping_options.forEach((option) => {
10658
+ profiles.set(option.shipping_profile_id, option.shipping_profile);
10659
+ });
10660
+ return Array.from(profiles.values());
10661
+ }, [order.items, shipping_options]);
10662
+ const { handleSuccess } = useRouteModal();
10663
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10664
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10665
+ const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
10666
+ const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
10667
+ const onSubmit = async () => {
10668
+ setIsSubmitting(true);
10669
+ let requestSucceeded = false;
10670
+ await requestOrderEdit(void 0, {
10671
+ onError: (e) => {
10672
+ ui.toast.error(`Failed to request order edit: ${e.message}`);
10673
+ },
10674
+ onSuccess: () => {
10675
+ requestSucceeded = true;
10676
+ }
10677
+ });
10678
+ if (!requestSucceeded) {
10679
+ setIsSubmitting(false);
10868
10680
  return;
10869
10681
  }
10870
- await updateActionItem(
10871
- {
10872
- action_id: actionId,
10873
- quantity: data.quantity,
10874
- unit_price: convertNumber(data.unit_price)
10682
+ await confirmOrderEdit(void 0, {
10683
+ onError: (e) => {
10684
+ ui.toast.error(`Failed to confirm order edit: ${e.message}`);
10875
10685
  },
10876
- {
10877
- onSuccess: () => {
10878
- setEditing(false);
10879
- },
10880
- onError: (e) => {
10881
- ui.toast.error(e.message);
10882
- }
10686
+ onSuccess: () => {
10687
+ handleSuccess();
10688
+ },
10689
+ onSettled: () => {
10690
+ setIsSubmitting(false);
10883
10691
  }
10884
- );
10885
- });
10886
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
10887
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
10888
- /* @__PURE__ */ jsxRuntime.jsx(
10889
- Thumbnail,
10890
- {
10891
- thumbnail: item.thumbnail,
10892
- alt: item.title ?? void 0
10893
- }
10894
- ),
10895
- editing ? /* @__PURE__ */ jsxRuntime.jsx(
10896
- Form$2.Field,
10897
- {
10898
- control: form.control,
10899
- name: "title",
10900
- render: ({ field }) => {
10901
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }) });
10902
- }
10903
- }
10904
- ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.title })
10905
- ] }),
10906
- editing ? /* @__PURE__ */ jsxRuntime.jsx(
10907
- Form$2.Field,
10908
- {
10909
- control: form.control,
10910
- name: "quantity",
10911
- render: ({ field }) => {
10912
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
10913
- }
10914
- }
10915
- ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }),
10916
- editing ? /* @__PURE__ */ jsxRuntime.jsx(
10917
- Form$2.Field,
10918
- {
10919
- control: form.control,
10920
- name: "unit_price",
10921
- render: ({ field: { onChange, ...field } }) => {
10922
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
10923
- ui.CurrencyInput,
10924
- {
10925
- ...field,
10926
- symbol: getNativeSymbol(currencyCode),
10927
- code: currencyCode,
10928
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10929
- }
10930
- ) }) });
10692
+ });
10693
+ };
10694
+ const onKeydown = React.useCallback(
10695
+ (e) => {
10696
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10697
+ if (data || isSubmitting) {
10698
+ return;
10931
10699
  }
10700
+ onSubmit();
10932
10701
  }
10933
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10934
- /* @__PURE__ */ jsxRuntime.jsx(
10935
- ui.IconButton,
10936
- {
10937
- type: "button",
10938
- size: "small",
10939
- onClick: editing ? onSubmit : () => {
10940
- setEditing(true);
10941
- },
10942
- disabled: isPending,
10943
- children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
10944
- }
10945
- )
10946
- ] }) }) });
10947
- };
10948
- const StackedModalTrigger$1 = ({
10949
- type,
10950
- setModalContent
10951
- }) => {
10952
- const { setIsOpen } = useStackedModal();
10953
- const onClick = React.useCallback(() => {
10954
- setModalContent(type);
10955
- setIsOpen(STACKED_MODAL_ID, true);
10956
- }, [setModalContent, setIsOpen, type]);
10957
- 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" }) });
10958
- };
10959
- const VARIANT_PREFIX = "items";
10960
- const LIMIT = 50;
10961
- const ExistingItemsForm = ({ orderId, items }) => {
10962
- const { setIsOpen } = useStackedModal();
10963
- const [rowSelection, setRowSelection] = React.useState(
10964
- items.reduce((acc, item) => {
10965
- acc[item.variant_id] = true;
10966
- return acc;
10967
- }, {})
10968
- );
10969
- React.useEffect(() => {
10970
- setRowSelection(
10971
- items.reduce((acc, item) => {
10972
- if (item.variant_id) {
10973
- acc[item.variant_id] = true;
10974
- }
10975
- return acc;
10976
- }, {})
10977
- );
10978
- }, [items]);
10979
- const { q, order, offset } = useQueryParams(
10980
- ["q", "order", "offset"],
10981
- VARIANT_PREFIX
10982
- );
10983
- const { variants, count, isPending, isError, error } = useProductVariants(
10984
- {
10985
- q,
10986
- order,
10987
- offset: offset ? parseInt(offset) : void 0,
10988
- limit: LIMIT
10989
10702
  },
10990
- {
10991
- placeholderData: reactQuery.keepPreviousData
10992
- }
10703
+ [data, isSubmitting, onSubmit]
10993
10704
  );
10994
- const columns = useColumns();
10995
- const { mutateAsync } = useDraftOrderAddItems(orderId);
10996
- const onSubmit = async () => {
10997
- const ids = Object.keys(rowSelection).filter(
10998
- (id) => !items.find((i) => i.variant_id === id)
10999
- );
11000
- await mutateAsync(
11001
- {
11002
- items: ids.map((id) => ({
11003
- variant_id: id,
11004
- quantity: 1
11005
- }))
11006
- },
11007
- {
11008
- onSuccess: () => {
11009
- setRowSelection({});
11010
- setIsOpen(STACKED_MODAL_ID, false);
11011
- },
11012
- onError: (e) => {
11013
- ui.toast.error(e.message);
11014
- }
11015
- }
11016
- );
11017
- };
11018
- if (isError) {
11019
- throw error;
11020
- }
11021
- return /* @__PURE__ */ jsxRuntime.jsxs(
11022
- StackedFocusModal.Content,
11023
- {
11024
- onOpenAutoFocus: (e) => {
11025
- e.preventDefault();
11026
- const searchInput = document.querySelector(
11027
- "[data-modal-id='modal-search-input']"
11028
- );
11029
- if (searchInput) {
11030
- searchInput.focus();
11031
- }
11032
- },
11033
- children: [
11034
- /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Header, { children: [
11035
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Product Variants" }) }),
11036
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10705
+ React.useEffect(() => {
10706
+ document.addEventListener("keydown", onKeydown);
10707
+ return () => {
10708
+ document.removeEventListener("keydown", onKeydown);
10709
+ };
10710
+ }, [onKeydown]);
10711
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10712
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
10713
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: [
10714
+ /* @__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 py-16 px-6", children: [
10715
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
10716
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
10717
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose which shipping method(s) to use for the items in the order." }) })
11037
10718
  ] }),
11038
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
11039
- DataTable,
11040
- {
11041
- data: variants,
11042
- columns,
11043
- isLoading: isPending,
11044
- getRowId: (row) => row.id,
11045
- rowCount: count,
11046
- prefix: VARIANT_PREFIX,
11047
- layout: "fill",
11048
- rowSelection: {
11049
- state: rowSelection,
11050
- onRowSelectionChange: setRowSelection,
11051
- enableRowSelection: (row) => {
11052
- return !items.find((i) => i.variant_id === row.original.id);
11053
- }
11054
- },
11055
- autoFocusSearch: true
11056
- }
11057
- ) }),
11058
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11059
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11060
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
11061
- ] }) })
11062
- ]
11063
- }
11064
- );
11065
- };
11066
- const columnHelper = ui.createDataTableColumnHelper();
11067
- const useColumns = () => {
11068
- return React.useMemo(() => {
11069
- return [
11070
- columnHelper.select(),
11071
- columnHelper.accessor("product.title", {
11072
- header: "Product",
11073
- cell: ({ row }) => {
11074
- var _a, _b, _c;
11075
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
10719
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
10720
+ /* @__PURE__ */ jsxRuntime.jsx(radixUi.Accordion.Root, { type: "multiple", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle rounded-xl shadow-elevation-card-rest", children: [
10721
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2 flex items-center justify-between", children: [
11076
10722
  /* @__PURE__ */ jsxRuntime.jsx(
11077
- Thumbnail,
10723
+ ui.Text,
11078
10724
  {
11079
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
11080
- alt: (_b = row.original.product) == null ? void 0 : _b.title
11081
- }
11082
- ),
11083
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
11084
- ] });
11085
- },
11086
- enableSorting: true
11087
- }),
11088
- columnHelper.accessor("title", {
11089
- header: "Variant",
11090
- enableSorting: true
11091
- }),
11092
- columnHelper.accessor("sku", {
11093
- header: "SKU",
11094
- cell: ({ getValue }) => {
11095
- return getValue() ?? "-";
11096
- },
11097
- enableSorting: true
11098
- }),
11099
- columnHelper.accessor("updated_at", {
11100
- header: "Updated",
11101
- cell: ({ getValue }) => {
11102
- return /* @__PURE__ */ jsxRuntime.jsx(
11103
- ui.Tooltip,
11104
- {
11105
- content: getFullDate({ date: getValue(), includeTime: true }),
11106
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
11107
- }
11108
- );
11109
- },
11110
- enableSorting: true,
11111
- sortAscLabel: "Oldest first",
11112
- sortDescLabel: "Newest first"
11113
- }),
11114
- columnHelper.accessor("created_at", {
11115
- header: "Created",
11116
- cell: ({ getValue }) => {
11117
- return /* @__PURE__ */ jsxRuntime.jsx(
11118
- ui.Tooltip,
11119
- {
11120
- content: getFullDate({ date: getValue(), includeTime: true }),
11121
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
11122
- }
11123
- );
11124
- },
11125
- enableSorting: true,
11126
- sortAscLabel: "Oldest first",
11127
- sortDescLabel: "Newest first"
11128
- })
11129
- ];
11130
- }, []);
11131
- };
11132
- const CustomItemForm = ({ orderId, currencyCode }) => {
11133
- const { setIsOpen } = useStackedModal();
11134
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
11135
- const form = reactHookForm.useForm({
11136
- defaultValues: {
11137
- title: "",
11138
- quantity: 1,
11139
- unit_price: ""
11140
- },
11141
- resolver: zod.zodResolver(customItemSchema)
11142
- });
11143
- const onSubmit = form.handleSubmit(async (data) => {
11144
- await addItems(
11145
- {
11146
- items: [
11147
- {
11148
- title: data.title,
11149
- quantity: data.quantity,
11150
- unit_price: convertNumber(data.unit_price)
11151
- }
11152
- ]
11153
- },
11154
- {
11155
- onSuccess: () => {
11156
- setIsOpen(STACKED_MODAL_ID, false);
11157
- },
11158
- onError: (e) => {
11159
- ui.toast.error(e.message);
11160
- }
11161
- }
11162
- );
11163
- });
11164
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Content, { children: [
11165
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Header, {}),
11166
- /* @__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: [
11167
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11168
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Add custom item" }) }),
11169
- /* @__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." }) })
11170
- ] }),
11171
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11172
- /* @__PURE__ */ jsxRuntime.jsx(
11173
- Form$2.Field,
11174
- {
11175
- control: form.control,
11176
- name: "title",
11177
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11178
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11179
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Title" }),
11180
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the title of the item" })
11181
- ] }),
11182
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11183
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
11184
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11185
- ] })
11186
- ] }) })
11187
- }
11188
- ),
11189
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11190
- /* @__PURE__ */ jsxRuntime.jsx(
11191
- Form$2.Field,
11192
- {
11193
- control: form.control,
11194
- name: "unit_price",
11195
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11196
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11197
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Unit price" }),
11198
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
11199
- ] }),
11200
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11201
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11202
- ui.CurrencyInput,
11203
- {
11204
- symbol: getNativeSymbol(currencyCode),
11205
- code: currencyCode,
11206
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
11207
- ...field
11208
- }
11209
- ) }),
11210
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11211
- ] })
11212
- ] }) })
11213
- }
11214
- ),
11215
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11216
- /* @__PURE__ */ jsxRuntime.jsx(
11217
- Form$2.Field,
11218
- {
11219
- control: form.control,
11220
- name: "quantity",
11221
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11222
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11223
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Quantity" }),
11224
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
11225
- ] }),
11226
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 w-full", children: [
11227
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field, className: "w-full" }) }) }),
11228
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11229
- ] })
11230
- ] }) })
11231
- }
11232
- )
11233
- ] }) }) }),
11234
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11235
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11236
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
11237
- ] }) })
11238
- ] }) }) });
11239
- };
11240
- const customItemSchema = z.object({
11241
- title: z.string().min(1),
11242
- quantity: z.number(),
11243
- unit_price: z.union([z.number(), z.string()])
11244
- });
11245
- const InlineTip = React.forwardRef(
11246
- ({ variant = "tip", label, className, children, ...props }, ref) => {
11247
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
11248
- return /* @__PURE__ */ jsxRuntime.jsxs(
11249
- "div",
11250
- {
11251
- ref,
11252
- className: ui.clx(
11253
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
11254
- className
11255
- ),
11256
- ...props,
11257
- children: [
11258
- /* @__PURE__ */ jsxRuntime.jsx(
11259
- "div",
11260
- {
11261
- role: "presentation",
11262
- className: ui.clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
11263
- "bg-ui-tag-orange-icon": variant === "warning"
11264
- })
11265
- }
11266
- ),
11267
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-pretty", children: [
11268
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
11269
- labelValue,
11270
- ":"
11271
- ] }),
11272
- " ",
11273
- children
11274
- ] })
11275
- ]
11276
- }
11277
- );
11278
- }
11279
- );
11280
- InlineTip.displayName = "InlineTip";
11281
- const MetadataFieldSchema = z.object({
11282
- key: z.string(),
11283
- disabled: z.boolean().optional(),
11284
- value: z.any()
11285
- });
11286
- const MetadataSchema = z.object({
11287
- metadata: z.array(MetadataFieldSchema)
11288
- });
11289
- const Metadata = () => {
11290
- const { id } = reactRouterDom.useParams();
11291
- const { order, isPending, isError, error } = useOrder(id, {
11292
- fields: "metadata"
11293
- });
11294
- if (isError) {
11295
- throw error;
11296
- }
11297
- const isReady = !isPending && !!order;
11298
- return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
11299
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
11300
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Metadata" }) }),
11301
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
11302
- ] }),
11303
- !isReady ? /* @__PURE__ */ jsxRuntime.jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
11304
- ] });
11305
- };
11306
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
11307
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
11308
- const MetadataForm = ({ orderId, metadata }) => {
11309
- const { handleSuccess } = useRouteModal();
11310
- const hasUneditableRows = getHasUneditableRows(metadata);
11311
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
11312
- const form = reactHookForm.useForm({
11313
- defaultValues: {
11314
- metadata: getDefaultValues(metadata)
11315
- },
11316
- resolver: zod.zodResolver(MetadataSchema)
11317
- });
11318
- const handleSubmit = form.handleSubmit(async (data) => {
11319
- const parsedData = parseValues(data);
11320
- await mutateAsync(
11321
- {
11322
- metadata: parsedData
11323
- },
11324
- {
11325
- onSuccess: () => {
11326
- ui.toast.success("Metadata updated");
11327
- handleSuccess();
11328
- },
11329
- onError: (error) => {
11330
- ui.toast.error(error.message);
11331
- }
11332
- }
11333
- );
11334
- });
11335
- const { fields, insert, remove } = reactHookForm.useFieldArray({
11336
- control: form.control,
11337
- name: "metadata"
11338
- });
11339
- function deleteRow(index) {
11340
- remove(index);
11341
- if (fields.length === 1) {
11342
- insert(0, {
11343
- key: "",
11344
- value: "",
11345
- disabled: false
11346
- });
11347
- }
11348
- }
11349
- function insertRow(index, position) {
11350
- insert(index + (position === "above" ? 0 : 1), {
11351
- key: "",
11352
- value: "",
11353
- disabled: false
11354
- });
11355
- }
11356
- return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
11357
- KeyboundForm,
11358
- {
11359
- onSubmit: handleSubmit,
11360
- className: "flex flex-1 flex-col overflow-hidden",
11361
- children: [
11362
- /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
11363
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
11364
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
11365
- /* @__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" }) }),
11366
- /* @__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" }) })
11367
- ] }),
11368
- fields.map((field, index) => {
11369
- const isDisabled = field.disabled || false;
11370
- let placeholder = "-";
11371
- if (typeof field.value === "object") {
11372
- placeholder = "{ ... }";
11373
- }
11374
- if (Array.isArray(field.value)) {
11375
- placeholder = "[ ... ]";
11376
- }
11377
- return /* @__PURE__ */ jsxRuntime.jsx(
11378
- ConditionalTooltip,
11379
- {
11380
- showTooltip: isDisabled,
11381
- content: "This row is disabled because it contains non-primitive data.",
11382
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/table relative", children: [
11383
- /* @__PURE__ */ jsxRuntime.jsxs(
11384
- "div",
11385
- {
11386
- className: ui.clx("grid grid-cols-2 divide-x", {
11387
- "overflow-hidden rounded-b-lg": index === fields.length - 1
11388
- }),
11389
- children: [
11390
- /* @__PURE__ */ jsxRuntime.jsx(
11391
- Form$2.Field,
11392
- {
11393
- control: form.control,
11394
- name: `metadata.${index}.key`,
11395
- render: ({ field: field2 }) => {
11396
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11397
- GridInput,
11398
- {
11399
- "aria-labelledby": METADATA_KEY_LABEL_ID,
11400
- ...field2,
11401
- disabled: isDisabled,
11402
- placeholder: "Key"
11403
- }
11404
- ) }) });
11405
- }
11406
- }
11407
- ),
11408
- /* @__PURE__ */ jsxRuntime.jsx(
11409
- Form$2.Field,
11410
- {
11411
- control: form.control,
11412
- name: `metadata.${index}.value`,
11413
- render: ({ field: { value, ...field2 } }) => {
11414
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11415
- GridInput,
11416
- {
11417
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
11418
- ...field2,
11419
- value: isDisabled ? placeholder : value,
11420
- disabled: isDisabled,
11421
- placeholder: "Value"
11422
- }
11423
- ) }) });
11424
- }
11425
- }
11426
- )
11427
- ]
11428
- }
11429
- ),
11430
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
11431
- /* @__PURE__ */ jsxRuntime.jsx(
11432
- ui.DropdownMenu.Trigger,
11433
- {
11434
- className: ui.clx(
11435
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
11436
- {
11437
- hidden: isDisabled
11438
- }
11439
- ),
11440
- disabled: isDisabled,
11441
- asChild: true,
11442
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisVertical, {}) })
11443
- }
11444
- ),
11445
- /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
11446
- /* @__PURE__ */ jsxRuntime.jsxs(
11447
- ui.DropdownMenu.Item,
11448
- {
11449
- className: "gap-x-2",
11450
- onClick: () => insertRow(index, "above"),
11451
- children: [
11452
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowUpMini, { className: "text-ui-fg-subtle" }),
11453
- "Insert row above"
11454
- ]
11455
- }
11456
- ),
11457
- /* @__PURE__ */ jsxRuntime.jsxs(
11458
- ui.DropdownMenu.Item,
11459
- {
11460
- className: "gap-x-2",
11461
- onClick: () => insertRow(index, "below"),
11462
- children: [
11463
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowDownMini, { className: "text-ui-fg-subtle" }),
11464
- "Insert row below"
11465
- ]
11466
- }
11467
- ),
11468
- /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Separator, {}),
11469
- /* @__PURE__ */ jsxRuntime.jsxs(
11470
- ui.DropdownMenu.Item,
11471
- {
11472
- className: "gap-x-2",
11473
- onClick: () => deleteRow(index),
11474
- children: [
11475
- /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { className: "text-ui-fg-subtle" }),
11476
- "Delete row"
11477
- ]
11478
- }
11479
- )
11480
- ] })
11481
- ] })
11482
- ] })
11483
- },
11484
- field.id
11485
- );
11486
- })
11487
- ] }),
11488
- 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." })
11489
- ] }),
11490
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11491
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11492
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11493
- ] }) })
11494
- ]
11495
- }
11496
- ) });
11497
- };
11498
- const GridInput = React.forwardRef(({ className, ...props }, ref) => {
11499
- return /* @__PURE__ */ jsxRuntime.jsx(
11500
- "input",
11501
- {
11502
- ref,
11503
- ...props,
11504
- autoComplete: "off",
11505
- className: ui.clx(
11506
- "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",
11507
- className
11508
- )
11509
- }
11510
- );
11511
- });
11512
- GridInput.displayName = "MetadataForm.GridInput";
11513
- const PlaceholderInner = () => {
11514
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11515
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11516
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11517
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" }),
11518
- /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-12 rounded-md" })
11519
- ] }) })
11520
- ] });
11521
- };
11522
- const EDITABLE_TYPES = ["string", "number", "boolean"];
11523
- function getDefaultValues(metadata) {
11524
- if (!metadata || !Object.keys(metadata).length) {
11525
- return [
11526
- {
11527
- key: "",
11528
- value: "",
11529
- disabled: false
11530
- }
11531
- ];
11532
- }
11533
- return Object.entries(metadata).map(([key, value]) => {
11534
- if (!EDITABLE_TYPES.includes(typeof value)) {
11535
- return {
11536
- key,
11537
- value,
11538
- disabled: true
11539
- };
11540
- }
11541
- let stringValue = value;
11542
- if (typeof value !== "string") {
11543
- stringValue = JSON.stringify(value);
11544
- }
11545
- return {
11546
- key,
11547
- value: stringValue,
11548
- original_key: key
11549
- };
11550
- });
11551
- }
11552
- function parseValues(values) {
11553
- const metadata = values.metadata;
11554
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11555
- if (isEmpty) {
11556
- return null;
11557
- }
11558
- const update = {};
11559
- metadata.forEach((field) => {
11560
- let key = field.key;
11561
- let value = field.value;
11562
- const disabled = field.disabled;
11563
- if (!key || !value) {
11564
- return;
11565
- }
11566
- if (disabled) {
11567
- update[key] = value;
11568
- return;
11569
- }
11570
- key = key.trim();
11571
- value = value.trim();
11572
- if (value === "true") {
11573
- update[key] = true;
11574
- } else if (value === "false") {
11575
- update[key] = false;
11576
- } else {
11577
- const parsedNumber = parseFloat(value);
11578
- if (!isNaN(parsedNumber)) {
11579
- update[key] = parsedNumber;
11580
- } else {
11581
- update[key] = value;
11582
- }
11583
- }
11584
- });
11585
- return update;
11586
- }
11587
- function getHasUneditableRows(metadata) {
11588
- if (!metadata) {
11589
- return false;
11590
- }
11591
- return Object.values(metadata).some(
11592
- (value) => !EDITABLE_TYPES.includes(typeof value)
11593
- );
11594
- }
11595
- const STACKED_FOCUS_MODAL_ID = "shipping-form";
11596
- const Shipping = () => {
11597
- var _a;
11598
- const { id } = reactRouterDom.useParams();
11599
- const { order, isPending, isError, error } = useOrder(id, {
11600
- fields: "+items.*,+items.variant.*,+items.variant.product.*,+items.variant.product.shipping_profile.*,+currency_code"
11601
- });
11602
- const {
11603
- order: preview,
11604
- isPending: isPreviewPending,
11605
- isError: isPreviewError,
11606
- error: previewError
11607
- } = useOrderPreview(id);
11608
- useInitiateOrderEdit({ preview });
11609
- const { onCancel } = useCancelOrderEdit({ preview });
11610
- if (isError) {
11611
- throw error;
11612
- }
11613
- if (isPreviewError) {
11614
- throw previewError;
11615
- }
11616
- const orderHasItems = (((_a = order == null ? void 0 : order.items) == null ? void 0 : _a.length) || 0) > 0;
11617
- const isReady = preview && !isPreviewPending && order && !isPending;
11618
- return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: !orderHasItems ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden ", children: [
11619
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
11620
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.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 py-16 px-6", children: [
11621
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
11622
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "This draft order currently has no items. Add items to the order before adding shipping." }) })
11623
- ] }) }) }),
11624
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }) })
11625
- ] }) : isReady ? /* @__PURE__ */ jsxRuntime.jsx(ShippingForm, { preview, order }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11626
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Shipping" }) }),
11627
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
11628
- ] }) });
11629
- };
11630
- const ShippingForm = ({ preview, order }) => {
11631
- var _a;
11632
- const { setIsOpen } = useStackedModal();
11633
- const [isSubmitting, setIsSubmitting] = React.useState(false);
11634
- const [data, setData] = React.useState(null);
11635
- const appliedShippingOptionIds = (_a = preview.shipping_methods) == null ? void 0 : _a.map((method) => method.shipping_option_id).filter(Boolean);
11636
- const { shipping_options } = useShippingOptions(
11637
- {
11638
- id: appliedShippingOptionIds,
11639
- fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
11640
- },
11641
- {
11642
- enabled: appliedShippingOptionIds.length > 0
11643
- }
11644
- );
11645
- const uniqueShippingProfiles = React.useMemo(() => {
11646
- const profiles = /* @__PURE__ */ new Map();
11647
- getUniqueShippingProfiles(order.items).forEach((profile) => {
11648
- profiles.set(profile.id, profile);
11649
- });
11650
- shipping_options == null ? void 0 : shipping_options.forEach((option) => {
11651
- profiles.set(option.shipping_profile_id, option.shipping_profile);
11652
- });
11653
- return Array.from(profiles.values());
11654
- }, [order.items, shipping_options]);
11655
- const { handleSuccess } = useRouteModal();
11656
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11657
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
11658
- const { mutateAsync: removeShippingMethod } = useDraftOrderRemoveShippingMethod(preview.id);
11659
- const { mutateAsync: removeActionShippingMethod } = useDraftOrderRemoveActionShippingMethod(preview.id);
11660
- const onSubmit = async () => {
11661
- setIsSubmitting(true);
11662
- let requestSucceeded = false;
11663
- await requestOrderEdit(void 0, {
11664
- onError: (e) => {
11665
- ui.toast.error(`Failed to request order edit: ${e.message}`);
11666
- },
11667
- onSuccess: () => {
11668
- requestSucceeded = true;
11669
- }
11670
- });
11671
- if (!requestSucceeded) {
11672
- setIsSubmitting(false);
11673
- return;
11674
- }
11675
- await confirmOrderEdit(void 0, {
11676
- onError: (e) => {
11677
- ui.toast.error(`Failed to confirm order edit: ${e.message}`);
11678
- },
11679
- onSuccess: () => {
11680
- handleSuccess();
11681
- },
11682
- onSettled: () => {
11683
- setIsSubmitting(false);
11684
- }
11685
- });
11686
- };
11687
- const onKeydown = React.useCallback(
11688
- (e) => {
11689
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11690
- if (data || isSubmitting) {
11691
- return;
11692
- }
11693
- onSubmit();
11694
- }
11695
- },
11696
- [data, isSubmitting, onSubmit]
11697
- );
11698
- React.useEffect(() => {
11699
- document.addEventListener("keydown", onKeydown);
11700
- return () => {
11701
- document.removeEventListener("keydown", onKeydown);
11702
- };
11703
- }, [onKeydown]);
11704
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
11705
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
11706
- /* @__PURE__ */ jsxRuntime.jsxs(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: [
11707
- /* @__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 py-16 px-6", children: [
11708
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11709
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
11710
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose which shipping method(s) to use for the items in the order." }) })
11711
- ] }),
11712
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11713
- /* @__PURE__ */ jsxRuntime.jsx(radixUi.Accordion.Root, { type: "multiple", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle rounded-xl shadow-elevation-card-rest", children: [
11714
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2 flex items-center justify-between", children: [
11715
- /* @__PURE__ */ jsxRuntime.jsx(
11716
- ui.Text,
11717
- {
11718
- size: "xsmall",
11719
- weight: "plus",
11720
- className: "text-ui-fg-muted",
11721
- children: "Shipping profile"
10725
+ size: "xsmall",
10726
+ weight: "plus",
10727
+ className: "text-ui-fg-muted",
10728
+ children: "Shipping profile"
11722
10729
  }
11723
10730
  ),
11724
10731
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -11899,7 +10906,7 @@ const ShippingForm = ({ preview, order }) => {
11899
10906
  ]
11900
10907
  }
11901
10908
  ) : /* @__PURE__ */ jsxRuntime.jsx(
11902
- StackedModalTrigger,
10909
+ StackedModalTrigger$1,
11903
10910
  {
11904
10911
  shippingProfileId: profile.id,
11905
10912
  shippingOption,
@@ -11974,431 +10981,1462 @@ const ShippingForm = ({ preview, order }) => {
11974
10981
  ] }, item.id);
11975
10982
  })
11976
10983
  ] })
11977
- ]
11978
- },
11979
- profile.id
11980
- );
11981
- }) })
11982
- ] }) })
11983
- ] }) }),
11984
- /* @__PURE__ */ jsxRuntime.jsx(
11985
- StackedFocusModal,
11986
- {
11987
- id: STACKED_FOCUS_MODAL_ID,
11988
- onOpenChangeCallback: (open) => {
11989
- if (!open) {
11990
- setData(null);
10984
+ ]
10985
+ },
10986
+ profile.id
10987
+ );
10988
+ }) })
10989
+ ] }) })
10990
+ ] }) }),
10991
+ /* @__PURE__ */ jsxRuntime.jsx(
10992
+ StackedFocusModal,
10993
+ {
10994
+ id: STACKED_FOCUS_MODAL_ID,
10995
+ onOpenChangeCallback: (open) => {
10996
+ if (!open) {
10997
+ setData(null);
10998
+ }
10999
+ return open;
11000
+ },
11001
+ children: data && /* @__PURE__ */ jsxRuntime.jsx(ShippingProfileForm, { data, order, preview })
11002
+ }
11003
+ )
11004
+ ] }),
11005
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-x-2", children: [
11006
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11007
+ /* @__PURE__ */ jsxRuntime.jsx(
11008
+ ui.Button,
11009
+ {
11010
+ size: "small",
11011
+ type: "button",
11012
+ isLoading: isSubmitting,
11013
+ onClick: onSubmit,
11014
+ children: "Save"
11015
+ }
11016
+ )
11017
+ ] }) })
11018
+ ] });
11019
+ };
11020
+ const StackedModalTrigger$1 = ({
11021
+ shippingProfileId,
11022
+ shippingOption,
11023
+ shippingMethod,
11024
+ setData,
11025
+ children
11026
+ }) => {
11027
+ const { setIsOpen, getIsOpen } = useStackedModal();
11028
+ const isOpen = getIsOpen(STACKED_FOCUS_MODAL_ID);
11029
+ const onToggle = () => {
11030
+ if (isOpen) {
11031
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
11032
+ setData(null);
11033
+ } else {
11034
+ setIsOpen(STACKED_FOCUS_MODAL_ID, true);
11035
+ setData({
11036
+ shippingProfileId,
11037
+ shippingOption,
11038
+ shippingMethod
11039
+ });
11040
+ }
11041
+ };
11042
+ return /* @__PURE__ */ jsxRuntime.jsx(
11043
+ ui.Button,
11044
+ {
11045
+ size: "small",
11046
+ variant: "secondary",
11047
+ onClick: onToggle,
11048
+ className: "text-ui-fg-primary shrink-0",
11049
+ children
11050
+ }
11051
+ );
11052
+ };
11053
+ const ShippingProfileForm = ({
11054
+ data,
11055
+ order,
11056
+ preview
11057
+ }) => {
11058
+ var _a, _b, _c, _d, _e, _f;
11059
+ const { setIsOpen } = useStackedModal();
11060
+ const form = reactHookForm.useForm({
11061
+ resolver: zod.zodResolver(shippingMethodSchema),
11062
+ defaultValues: {
11063
+ location_id: (_d = (_c = (_b = (_a = data.shippingOption) == null ? void 0 : _a.service_zone) == null ? void 0 : _b.fulfillment_set) == null ? void 0 : _c.location) == null ? void 0 : _d.id,
11064
+ shipping_option_id: (_e = data.shippingOption) == null ? void 0 : _e.id,
11065
+ custom_amount: (_f = data.shippingMethod) == null ? void 0 : _f.amount
11066
+ }
11067
+ });
11068
+ const { mutateAsync: addShippingMethod, isPending } = useDraftOrderAddShippingMethod(order.id);
11069
+ const {
11070
+ mutateAsync: updateShippingMethod,
11071
+ isPending: isUpdatingShippingMethod
11072
+ } = useDraftOrderUpdateShippingMethod(order.id);
11073
+ const onSubmit = form.handleSubmit(async (values) => {
11074
+ if (lodash.isEqual(values, form.formState.defaultValues)) {
11075
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
11076
+ return;
11077
+ }
11078
+ if (data.shippingMethod) {
11079
+ await updateShippingMethod(
11080
+ {
11081
+ method_id: data.shippingMethod.id,
11082
+ shipping_option_id: values.shipping_option_id,
11083
+ custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
11084
+ },
11085
+ {
11086
+ onError: (e) => {
11087
+ ui.toast.error(e.message);
11088
+ },
11089
+ onSuccess: () => {
11090
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
11091
+ }
11092
+ }
11093
+ );
11094
+ return;
11095
+ }
11096
+ await addShippingMethod(
11097
+ {
11098
+ shipping_option_id: values.shipping_option_id,
11099
+ custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
11100
+ },
11101
+ {
11102
+ onError: (e) => {
11103
+ ui.toast.error(e.message);
11104
+ },
11105
+ onSuccess: () => {
11106
+ setIsOpen(STACKED_FOCUS_MODAL_ID, false);
11107
+ }
11108
+ }
11109
+ );
11110
+ });
11111
+ return /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs(
11112
+ KeyboundForm,
11113
+ {
11114
+ className: "flex h-full flex-col overflow-hidden",
11115
+ onSubmit,
11116
+ children: [
11117
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Header, {}),
11118
+ /* @__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 py-16 px-6", children: [
11119
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11120
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
11121
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a shipping method for the selected shipping profile. You can see the items that will be shipped using this method in the preview below." }) })
11122
+ ] }),
11123
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11124
+ /* @__PURE__ */ jsxRuntime.jsx(
11125
+ LocationField,
11126
+ {
11127
+ control: form.control,
11128
+ setValue: form.setValue
11129
+ }
11130
+ ),
11131
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11132
+ /* @__PURE__ */ jsxRuntime.jsx(
11133
+ ShippingOptionField,
11134
+ {
11135
+ shippingProfileId: data.shippingProfileId,
11136
+ preview,
11137
+ control: form.control
11138
+ }
11139
+ ),
11140
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11141
+ /* @__PURE__ */ jsxRuntime.jsx(
11142
+ CustomAmountField,
11143
+ {
11144
+ control: form.control,
11145
+ currencyCode: order.currency_code
11146
+ }
11147
+ ),
11148
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11149
+ /* @__PURE__ */ jsxRuntime.jsx(
11150
+ ItemsPreview,
11151
+ {
11152
+ order,
11153
+ shippingProfileId: data.shippingProfileId
11154
+ }
11155
+ )
11156
+ ] }) }) }),
11157
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-x-2", children: [
11158
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11159
+ /* @__PURE__ */ jsxRuntime.jsx(
11160
+ ui.Button,
11161
+ {
11162
+ size: "small",
11163
+ type: "submit",
11164
+ isLoading: isPending || isUpdatingShippingMethod,
11165
+ children: data.shippingMethod ? "Update" : "Add"
11166
+ }
11167
+ )
11168
+ ] }) })
11169
+ ]
11170
+ }
11171
+ ) }) });
11172
+ };
11173
+ const shippingMethodSchema = z.object({
11174
+ location_id: z.string(),
11175
+ shipping_option_id: z.string(),
11176
+ custom_amount: z.union([z.number(), z.string()]).optional()
11177
+ });
11178
+ const ItemsPreview = ({ order, shippingProfileId }) => {
11179
+ const matches = order.items.filter(
11180
+ (item) => {
11181
+ var _a, _b, _c;
11182
+ return ((_c = (_b = (_a = item.variant) == null ? void 0 : _a.product) == null ? void 0 : _b.shipping_profile) == null ? void 0 : _c.id) === shippingProfileId;
11183
+ }
11184
+ );
11185
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
11186
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 items-center gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11187
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Items to ship" }),
11188
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Items with the selected shipping profile." })
11189
+ ] }) }),
11190
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
11191
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 px-4 py-2 text-ui-fg-muted", children: [
11192
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Item" }) }),
11193
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Quantity" }) })
11194
+ ] }),
11195
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
11196
+ "div",
11197
+ {
11198
+ className: "grid grid-cols-2 gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center",
11199
+ children: [
11200
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
11201
+ /* @__PURE__ */ jsxRuntime.jsx(
11202
+ Thumbnail,
11203
+ {
11204
+ thumbnail: item.thumbnail,
11205
+ alt: item.product_title ?? void 0
11206
+ }
11207
+ ),
11208
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11209
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
11210
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
11211
+ /* @__PURE__ */ jsxRuntime.jsxs(
11212
+ ui.Text,
11213
+ {
11214
+ size: "small",
11215
+ leading: "compact",
11216
+ className: "text-ui-fg-subtle",
11217
+ children: [
11218
+ "(",
11219
+ item.variant_title,
11220
+ ")"
11221
+ ]
11222
+ }
11223
+ )
11224
+ ] }),
11225
+ /* @__PURE__ */ jsxRuntime.jsx(
11226
+ ui.Text,
11227
+ {
11228
+ size: "small",
11229
+ leading: "compact",
11230
+ className: "text-ui-fg-subtle",
11231
+ children: item.variant_sku
11232
+ }
11233
+ )
11234
+ ] })
11235
+ ] }),
11236
+ /* @__PURE__ */ jsxRuntime.jsxs(
11237
+ ui.Text,
11238
+ {
11239
+ size: "small",
11240
+ leading: "compact",
11241
+ className: "text-ui-fg-subtle",
11242
+ children: [
11243
+ item.quantity,
11244
+ "x"
11245
+ ]
11246
+ }
11247
+ )
11248
+ ]
11249
+ },
11250
+ item.id
11251
+ )) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
11252
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
11253
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
11254
+ 'No items found for "',
11255
+ query,
11256
+ '".'
11257
+ ] })
11258
+ ] }) })
11259
+ ] })
11260
+ ] });
11261
+ };
11262
+ const LocationField = ({ control, setValue }) => {
11263
+ const locations = useComboboxData({
11264
+ queryKey: ["locations"],
11265
+ queryFn: async (params) => {
11266
+ return await sdk.admin.stockLocation.list(params);
11267
+ },
11268
+ getOptions: (data) => {
11269
+ return data.stock_locations.map((location) => ({
11270
+ label: location.name,
11271
+ value: location.id
11272
+ }));
11273
+ }
11274
+ });
11275
+ return /* @__PURE__ */ jsxRuntime.jsx(
11276
+ Form$2.Field,
11277
+ {
11278
+ control,
11279
+ name: "location_id",
11280
+ render: ({ field: { onChange, ...field } }) => {
11281
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11282
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11283
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Location" }),
11284
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Choose where you want to ship the items from." })
11285
+ ] }),
11286
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11287
+ Combobox,
11288
+ {
11289
+ options: locations.options,
11290
+ fetchNextPage: locations.fetchNextPage,
11291
+ isFetchingNextPage: locations.isFetchingNextPage,
11292
+ searchValue: locations.searchValue,
11293
+ onSearchValueChange: locations.onSearchValueChange,
11294
+ placeholder: "Select location",
11295
+ onChange: (value) => {
11296
+ setValue("shipping_option_id", "", {
11297
+ shouldDirty: true,
11298
+ shouldTouch: true
11299
+ });
11300
+ onChange(value);
11301
+ },
11302
+ ...field
11303
+ }
11304
+ ) })
11305
+ ] }) });
11306
+ }
11307
+ }
11308
+ );
11309
+ };
11310
+ const ShippingOptionField = ({
11311
+ shippingProfileId,
11312
+ preview,
11313
+ control
11314
+ }) => {
11315
+ var _a;
11316
+ const locationId = reactHookForm.useWatch({ control, name: "location_id" });
11317
+ const shippingOptions = useComboboxData({
11318
+ queryKey: ["shipping_options", locationId, shippingProfileId],
11319
+ queryFn: async (params) => {
11320
+ return await sdk.admin.shippingOption.list({
11321
+ ...params,
11322
+ stock_location_id: locationId,
11323
+ shipping_profile_id: shippingProfileId
11324
+ });
11325
+ },
11326
+ getOptions: (data) => {
11327
+ return data.shipping_options.map((option) => {
11328
+ var _a2;
11329
+ if ((_a2 = option.rules) == null ? void 0 : _a2.find(
11330
+ (r) => r.attribute === "is_return" && r.value === "true"
11331
+ )) {
11332
+ return void 0;
11333
+ }
11334
+ return {
11335
+ label: option.name,
11336
+ value: option.id
11337
+ };
11338
+ }).filter(Boolean);
11339
+ },
11340
+ enabled: !!locationId && !!shippingProfileId,
11341
+ defaultValue: ((_a = preview.shipping_methods[0]) == null ? void 0 : _a.shipping_option_id) || void 0
11342
+ });
11343
+ const tooltipContent = !locationId && !shippingProfileId ? "Choose a location and shipping profile first." : !locationId ? "Choose a location first." : "Choose a shipping profile first.";
11344
+ return /* @__PURE__ */ jsxRuntime.jsx(
11345
+ Form$2.Field,
11346
+ {
11347
+ control,
11348
+ name: "shipping_option_id",
11349
+ render: ({ field }) => {
11350
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11351
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11352
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Shipping option" }),
11353
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Choose the shipping option to use." })
11354
+ ] }),
11355
+ /* @__PURE__ */ jsxRuntime.jsx(
11356
+ ConditionalTooltip,
11357
+ {
11358
+ content: tooltipContent,
11359
+ showTooltip: !locationId || !shippingProfileId,
11360
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11361
+ Combobox,
11362
+ {
11363
+ options: shippingOptions.options,
11364
+ fetchNextPage: shippingOptions.fetchNextPage,
11365
+ isFetchingNextPage: shippingOptions.isFetchingNextPage,
11366
+ searchValue: shippingOptions.searchValue,
11367
+ onSearchValueChange: shippingOptions.onSearchValueChange,
11368
+ placeholder: "Select shipping option",
11369
+ ...field,
11370
+ disabled: !locationId || !shippingProfileId
11371
+ }
11372
+ ) }) })
11373
+ }
11374
+ )
11375
+ ] }) });
11376
+ }
11377
+ }
11378
+ );
11379
+ };
11380
+ const CustomAmountField = ({
11381
+ control,
11382
+ currencyCode
11383
+ }) => {
11384
+ return /* @__PURE__ */ jsxRuntime.jsx(
11385
+ Form$2.Field,
11386
+ {
11387
+ control,
11388
+ name: "custom_amount",
11389
+ render: ({ field: { onChange, ...field } }) => {
11390
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11391
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11392
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { optional: true, children: "Custom amount" }),
11393
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
11394
+ ] }),
11395
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11396
+ ui.CurrencyInput,
11397
+ {
11398
+ ...field,
11399
+ onValueChange: (value) => onChange(value),
11400
+ symbol: getNativeSymbol(currencyCode),
11401
+ code: currencyCode
11402
+ }
11403
+ ) })
11404
+ ] });
11405
+ }
11406
+ }
11407
+ );
11408
+ };
11409
+ const SalesChannel = () => {
11410
+ const { id } = reactRouterDom.useParams();
11411
+ const { draft_order, isPending, isError, error } = useDraftOrder(
11412
+ id,
11413
+ {
11414
+ fields: "+sales_channel_id"
11415
+ },
11416
+ {
11417
+ enabled: !!id
11418
+ }
11419
+ );
11420
+ if (isError) {
11421
+ throw error;
11422
+ }
11423
+ const ISrEADY = !!draft_order && !isPending;
11424
+ return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
11425
+ /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
11426
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Sales Channel" }) }),
11427
+ /* @__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" }) })
11428
+ ] }),
11429
+ ISrEADY && /* @__PURE__ */ jsxRuntime.jsx(SalesChannelForm, { order: draft_order })
11430
+ ] });
11431
+ };
11432
+ const SalesChannelForm = ({ order }) => {
11433
+ const form = reactHookForm.useForm({
11434
+ defaultValues: {
11435
+ sales_channel_id: order.sales_channel_id || ""
11436
+ },
11437
+ resolver: zod.zodResolver(schema$3)
11438
+ });
11439
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11440
+ const { handleSuccess } = useRouteModal();
11441
+ const onSubmit = form.handleSubmit(async (data) => {
11442
+ await mutateAsync(
11443
+ {
11444
+ sales_channel_id: data.sales_channel_id
11445
+ },
11446
+ {
11447
+ onSuccess: () => {
11448
+ ui.toast.success("Sales channel updated");
11449
+ handleSuccess();
11450
+ },
11451
+ onError: (error) => {
11452
+ ui.toast.error(error.message);
11453
+ }
11454
+ }
11455
+ );
11456
+ });
11457
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxRuntime.jsxs(
11458
+ KeyboundForm,
11459
+ {
11460
+ className: "flex flex-1 flex-col overflow-hidden",
11461
+ onSubmit,
11462
+ children: [
11463
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(SalesChannelField, { control: form.control, order }) }),
11464
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
11465
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11466
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11467
+ ] }) })
11468
+ ]
11469
+ }
11470
+ ) });
11471
+ };
11472
+ const SalesChannelField = ({ control, order }) => {
11473
+ const salesChannels = useComboboxData({
11474
+ queryFn: async (params) => {
11475
+ return await sdk.admin.salesChannel.list(params);
11476
+ },
11477
+ queryKey: ["sales-channels"],
11478
+ getOptions: (data) => {
11479
+ return data.sales_channels.map((salesChannel) => ({
11480
+ label: salesChannel.name,
11481
+ value: salesChannel.id
11482
+ }));
11483
+ },
11484
+ defaultValue: order.sales_channel_id || void 0
11485
+ });
11486
+ return /* @__PURE__ */ jsxRuntime.jsx(
11487
+ Form$2.Field,
11488
+ {
11489
+ control,
11490
+ name: "sales_channel_id",
11491
+ render: ({ field }) => {
11492
+ return /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
11493
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Sales Channel" }),
11494
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11495
+ Combobox,
11496
+ {
11497
+ options: salesChannels.options,
11498
+ fetchNextPage: salesChannels.fetchNextPage,
11499
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
11500
+ searchValue: salesChannels.searchValue,
11501
+ onSearchValueChange: salesChannels.onSearchValueChange,
11502
+ placeholder: "Select sales channel",
11503
+ ...field
11504
+ }
11505
+ ) }),
11506
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
11507
+ ] });
11508
+ }
11509
+ }
11510
+ );
11511
+ };
11512
+ const schema$3 = z.object({
11513
+ sales_channel_id: z.string().min(1)
11514
+ });
11515
+ const NumberInput = React.forwardRef(
11516
+ ({
11517
+ value,
11518
+ onChange,
11519
+ size = "base",
11520
+ min = 0,
11521
+ max = 100,
11522
+ step = 1,
11523
+ className,
11524
+ disabled,
11525
+ ...props
11526
+ }, ref) => {
11527
+ const handleChange = (event) => {
11528
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
11529
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
11530
+ onChange(newValue);
11531
+ }
11532
+ };
11533
+ const handleIncrement = () => {
11534
+ const newValue = value + step;
11535
+ if (max === void 0 || newValue <= max) {
11536
+ onChange(newValue);
11537
+ }
11538
+ };
11539
+ const handleDecrement = () => {
11540
+ const newValue = value - step;
11541
+ if (min === void 0 || newValue >= min) {
11542
+ onChange(newValue);
11543
+ }
11544
+ };
11545
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11546
+ "div",
11547
+ {
11548
+ className: ui.clx(
11549
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
11550
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
11551
+ {
11552
+ "h-7": size === "small",
11553
+ "h-8": size === "base"
11554
+ },
11555
+ className
11556
+ ),
11557
+ children: [
11558
+ /* @__PURE__ */ jsxRuntime.jsx(
11559
+ "input",
11560
+ {
11561
+ ref,
11562
+ type: "number",
11563
+ value,
11564
+ onChange: handleChange,
11565
+ min,
11566
+ max,
11567
+ step,
11568
+ className: ui.clx(
11569
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
11570
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
11571
+ "placeholder:text-ui-fg-muted"
11572
+ ),
11573
+ ...props
11574
+ }
11575
+ ),
11576
+ /* @__PURE__ */ jsxRuntime.jsxs(
11577
+ "button",
11578
+ {
11579
+ className: ui.clx(
11580
+ "flex items-center justify-center outline-none transition-fg",
11581
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
11582
+ "focus:bg-ui-bg-field-component-hover",
11583
+ "hover:bg-ui-bg-field-component-hover",
11584
+ {
11585
+ "size-7": size === "small",
11586
+ "size-8": size === "base"
11587
+ }
11588
+ ),
11589
+ type: "button",
11590
+ onClick: handleDecrement,
11591
+ disabled: min !== void 0 && value <= min || disabled,
11592
+ children: [
11593
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Minus, {}),
11594
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
11595
+ ]
11596
+ }
11597
+ ),
11598
+ /* @__PURE__ */ jsxRuntime.jsxs(
11599
+ "button",
11600
+ {
11601
+ className: ui.clx(
11602
+ "flex items-center justify-center outline-none transition-fg",
11603
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
11604
+ "focus:bg-ui-bg-field-hover",
11605
+ "hover:bg-ui-bg-field-hover",
11606
+ {
11607
+ "size-7": size === "small",
11608
+ "size-8": size === "base"
11609
+ }
11610
+ ),
11611
+ type: "button",
11612
+ onClick: handleIncrement,
11613
+ disabled: max !== void 0 && value >= max || disabled,
11614
+ children: [
11615
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
11616
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `Increase by ${step}` })
11617
+ ]
11618
+ }
11619
+ )
11620
+ ]
11621
+ }
11622
+ );
11623
+ }
11624
+ );
11625
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
11626
+ const productVariantsQueryKeys = {
11627
+ list: (query2) => [
11628
+ PRODUCT_VARIANTS_QUERY_KEY,
11629
+ query2 ? query2 : void 0
11630
+ ]
11631
+ };
11632
+ const useProductVariants = (query2, options) => {
11633
+ const { data, ...rest } = reactQuery.useQuery({
11634
+ queryKey: productVariantsQueryKeys.list(query2),
11635
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
11636
+ ...options
11637
+ });
11638
+ return { ...data, ...rest };
11639
+ };
11640
+ const STACKED_MODAL_ID = "items_stacked_modal";
11641
+ const Items = () => {
11642
+ const { id } = reactRouterDom.useParams();
11643
+ const {
11644
+ order: preview,
11645
+ isPending: isPreviewPending,
11646
+ isError: isPreviewError,
11647
+ error: previewError
11648
+ } = useOrderPreview(id, void 0, {
11649
+ placeholderData: reactQuery.keepPreviousData
11650
+ });
11651
+ useInitiateOrderEdit({ preview });
11652
+ const { draft_order, isPending, isError, error } = useDraftOrder(
11653
+ id,
11654
+ {
11655
+ fields: "currency_code"
11656
+ },
11657
+ {
11658
+ enabled: !!id
11659
+ }
11660
+ );
11661
+ const { onCancel } = useCancelOrderEdit({ preview });
11662
+ if (isError) {
11663
+ throw error;
11664
+ }
11665
+ if (isPreviewError) {
11666
+ throw previewError;
11667
+ }
11668
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
11669
+ return /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsxRuntime.jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11670
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit Items" }) }),
11671
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
11672
+ ] }) });
11673
+ };
11674
+ const ItemsForm = ({ preview, currencyCode }) => {
11675
+ var _a;
11676
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
11677
+ const [modalContent, setModalContent] = React.useState(
11678
+ null
11679
+ );
11680
+ const { handleSuccess } = useRouteModal();
11681
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
11682
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11683
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
11684
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
11685
+ const matches = React.useMemo(() => {
11686
+ return matchSorter.matchSorter(preview.items, query2, {
11687
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
11688
+ });
11689
+ }, [preview.items, query2]);
11690
+ const onSubmit = async () => {
11691
+ setIsSubmitting(true);
11692
+ let requestSucceeded = false;
11693
+ await requestOrderEdit(void 0, {
11694
+ onError: (e) => {
11695
+ ui.toast.error(`Failed to request order edit: ${e.message}`);
11696
+ },
11697
+ onSuccess: () => {
11698
+ requestSucceeded = true;
11699
+ }
11700
+ });
11701
+ if (!requestSucceeded) {
11702
+ setIsSubmitting(false);
11703
+ return;
11704
+ }
11705
+ await confirmOrderEdit(void 0, {
11706
+ onError: (e) => {
11707
+ ui.toast.error(`Failed to confirm order edit: ${e.message}`);
11708
+ },
11709
+ onSuccess: () => {
11710
+ handleSuccess();
11711
+ },
11712
+ onSettled: () => {
11713
+ setIsSubmitting(false);
11714
+ }
11715
+ });
11716
+ };
11717
+ const onKeyDown = React.useCallback(
11718
+ (e) => {
11719
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
11720
+ if (modalContent || isSubmitting) {
11721
+ return;
11722
+ }
11723
+ onSubmit();
11724
+ }
11725
+ },
11726
+ [modalContent, isSubmitting, onSubmit]
11727
+ );
11728
+ React.useEffect(() => {
11729
+ document.addEventListener("keydown", onKeyDown);
11730
+ return () => {
11731
+ document.removeEventListener("keydown", onKeyDown);
11732
+ };
11733
+ }, [onKeyDown]);
11734
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
11735
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Header, {}),
11736
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
11737
+ StackedFocusModal,
11738
+ {
11739
+ id: STACKED_MODAL_ID,
11740
+ onOpenChangeCallback: (open) => {
11741
+ if (!open) {
11742
+ setModalContent(null);
11743
+ }
11744
+ },
11745
+ children: [
11746
+ /* @__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: [
11747
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
11748
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Items" }) }),
11749
+ /* @__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." }) })
11750
+ ] }),
11751
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11752
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
11753
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
11754
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11755
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
11756
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
11757
+ ] }),
11758
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
11759
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
11760
+ ui.Input,
11761
+ {
11762
+ type: "search",
11763
+ placeholder: "Search items",
11764
+ value: searchValue,
11765
+ onChange: (e) => onSearchValueChange(e.target.value)
11766
+ }
11767
+ ) }),
11768
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
11769
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}) }) }),
11770
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu.Content, { children: [
11771
+ /* @__PURE__ */ jsxRuntime.jsx(
11772
+ StackedModalTrigger,
11773
+ {
11774
+ type: "add-items",
11775
+ setModalContent
11776
+ }
11777
+ ),
11778
+ /* @__PURE__ */ jsxRuntime.jsx(
11779
+ StackedModalTrigger,
11780
+ {
11781
+ type: "add-custom-item",
11782
+ setModalContent
11783
+ }
11784
+ )
11785
+ ] })
11786
+ ] })
11787
+ ] })
11788
+ ] }),
11789
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
11790
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted", children: [
11791
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Item" }) }),
11792
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Quantity" }) }),
11793
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Price" }) }),
11794
+ /* @__PURE__ */ jsxRuntime.jsx("div", {})
11795
+ ] }) }),
11796
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
11797
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
11798
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
11799
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
11800
+ Item,
11801
+ {
11802
+ item,
11803
+ preview,
11804
+ currencyCode
11805
+ },
11806
+ item.id
11807
+ )) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
11808
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
11809
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
11810
+ 'No items found for "',
11811
+ query2,
11812
+ '".'
11813
+ ] })
11814
+ ] }) })
11815
+ ] })
11816
+ ] }),
11817
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
11818
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
11819
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
11820
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(
11821
+ ui.Text,
11822
+ {
11823
+ size: "small",
11824
+ leading: "compact",
11825
+ className: "text-ui-fg-subtle",
11826
+ children: [
11827
+ itemCount,
11828
+ " ",
11829
+ itemCount === 1 ? "item" : "items"
11830
+ ]
11831
+ }
11832
+ ) }),
11833
+ /* @__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) }) })
11834
+ ] })
11835
+ ] }) }),
11836
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsxRuntime.jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsxRuntime.jsx(
11837
+ CustomItemForm,
11838
+ {
11839
+ orderId: preview.id,
11840
+ currencyCode
11991
11841
  }
11992
- return open;
11993
- },
11994
- children: data && /* @__PURE__ */ jsxRuntime.jsx(ShippingProfileForm, { data, order, preview })
11995
- }
11996
- )
11997
- ] }),
11998
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-x-2", children: [
11842
+ ) : null)
11843
+ ]
11844
+ }
11845
+ ) }),
11846
+ /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
11999
11847
  /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12000
11848
  /* @__PURE__ */ jsxRuntime.jsx(
12001
11849
  ui.Button,
12002
11850
  {
12003
11851
  size: "small",
12004
11852
  type: "button",
12005
- isLoading: isSubmitting,
12006
11853
  onClick: onSubmit,
11854
+ isLoading: isSubmitting,
12007
11855
  children: "Save"
12008
11856
  }
12009
11857
  )
12010
11858
  ] }) })
12011
11859
  ] });
12012
11860
  };
12013
- const StackedModalTrigger = ({
12014
- shippingProfileId,
12015
- shippingOption,
12016
- shippingMethod,
12017
- setData,
12018
- children
12019
- }) => {
12020
- const { setIsOpen, getIsOpen } = useStackedModal();
12021
- const isOpen = getIsOpen(STACKED_FOCUS_MODAL_ID);
12022
- const onToggle = () => {
12023
- if (isOpen) {
12024
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12025
- setData(null);
12026
- } else {
12027
- setIsOpen(STACKED_FOCUS_MODAL_ID, true);
12028
- setData({
12029
- shippingProfileId,
12030
- shippingOption,
12031
- shippingMethod
12032
- });
11861
+ const Item = ({ item, preview, currencyCode }) => {
11862
+ if (item.variant_id) {
11863
+ return /* @__PURE__ */ jsxRuntime.jsx(VariantItem, { item, preview, currencyCode });
11864
+ }
11865
+ return /* @__PURE__ */ jsxRuntime.jsx(CustomItem, { item, preview, currencyCode });
11866
+ };
11867
+ const VariantItem = ({ item, preview, currencyCode }) => {
11868
+ const [editing, setEditing] = React.useState(false);
11869
+ const form = reactHookForm.useForm({
11870
+ defaultValues: {
11871
+ quantity: item.quantity,
11872
+ unit_price: item.unit_price
11873
+ },
11874
+ resolver: zod.zodResolver(variantItemSchema)
11875
+ });
11876
+ const actionId = React.useMemo(() => {
11877
+ var _a, _b;
11878
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
11879
+ }, [item]);
11880
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
11881
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
11882
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
11883
+ const onSubmit = form.handleSubmit(async (data) => {
11884
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
11885
+ setEditing(false);
11886
+ return;
12033
11887
  }
12034
- };
12035
- return /* @__PURE__ */ jsxRuntime.jsx(
12036
- ui.Button,
12037
- {
12038
- size: "small",
12039
- variant: "secondary",
12040
- onClick: onToggle,
12041
- className: "text-ui-fg-primary shrink-0",
12042
- children
11888
+ if (!actionId) {
11889
+ await updateOriginalItem(
11890
+ {
11891
+ item_id: item.id,
11892
+ quantity: data.quantity,
11893
+ unit_price: convertNumber(data.unit_price)
11894
+ },
11895
+ {
11896
+ onSuccess: () => {
11897
+ setEditing(false);
11898
+ },
11899
+ onError: (e) => {
11900
+ ui.toast.error(e.message);
11901
+ }
11902
+ }
11903
+ );
11904
+ return;
12043
11905
  }
12044
- );
11906
+ await updateActionItem(
11907
+ {
11908
+ action_id: actionId,
11909
+ quantity: data.quantity,
11910
+ unit_price: convertNumber(data.unit_price)
11911
+ },
11912
+ {
11913
+ onSuccess: () => {
11914
+ setEditing(false);
11915
+ },
11916
+ onError: (e) => {
11917
+ ui.toast.error(e.message);
11918
+ }
11919
+ }
11920
+ );
11921
+ });
11922
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
11923
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3 w-full", children: [
11924
+ /* @__PURE__ */ jsxRuntime.jsx(
11925
+ Thumbnail,
11926
+ {
11927
+ thumbnail: item.thumbnail,
11928
+ alt: item.product_title ?? void 0
11929
+ }
11930
+ ),
11931
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
11932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
11933
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
11934
+ /* @__PURE__ */ jsxRuntime.jsxs(
11935
+ ui.Text,
11936
+ {
11937
+ size: "small",
11938
+ leading: "compact",
11939
+ className: "text-ui-fg-subtle",
11940
+ children: [
11941
+ "(",
11942
+ item.variant_title,
11943
+ ")"
11944
+ ]
11945
+ }
11946
+ )
11947
+ ] }),
11948
+ /* @__PURE__ */ jsxRuntime.jsx(
11949
+ ui.Text,
11950
+ {
11951
+ size: "small",
11952
+ leading: "compact",
11953
+ className: "text-ui-fg-subtle",
11954
+ children: item.variant_sku
11955
+ }
11956
+ )
11957
+ ] })
11958
+ ] }),
11959
+ editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
11960
+ Form$2.Field,
11961
+ {
11962
+ control: form.control,
11963
+ name: "quantity",
11964
+ render: ({ field }) => {
11965
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
11966
+ }
11967
+ }
11968
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }) }),
11969
+ editing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
11970
+ Form$2.Field,
11971
+ {
11972
+ control: form.control,
11973
+ name: "unit_price",
11974
+ render: ({ field: { onChange, ...field } }) => {
11975
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
11976
+ ui.CurrencyInput,
11977
+ {
11978
+ ...field,
11979
+ symbol: getNativeSymbol(currencyCode),
11980
+ code: currencyCode,
11981
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
11982
+ }
11983
+ ) }) });
11984
+ }
11985
+ }
11986
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end w-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
11987
+ /* @__PURE__ */ jsxRuntime.jsx(
11988
+ ui.IconButton,
11989
+ {
11990
+ type: "button",
11991
+ size: "small",
11992
+ onClick: editing ? onSubmit : () => {
11993
+ setEditing(true);
11994
+ },
11995
+ disabled: isPending,
11996
+ children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
11997
+ }
11998
+ )
11999
+ ] }) }) });
12045
12000
  };
12046
- const ShippingProfileForm = ({
12047
- data,
12048
- order,
12049
- preview
12050
- }) => {
12051
- var _a, _b, _c, _d, _e, _f;
12052
- const { setIsOpen } = useStackedModal();
12001
+ const variantItemSchema = z.object({
12002
+ quantity: z.number(),
12003
+ unit_price: z.union([z.number(), z.string()])
12004
+ });
12005
+ const CustomItem = ({ item, preview, currencyCode }) => {
12006
+ const [editing, setEditing] = React.useState(false);
12007
+ const { quantity, unit_price, title } = item;
12053
12008
  const form = reactHookForm.useForm({
12054
- resolver: zod.zodResolver(shippingMethodSchema),
12055
12009
  defaultValues: {
12056
- location_id: (_d = (_c = (_b = (_a = data.shippingOption) == null ? void 0 : _a.service_zone) == null ? void 0 : _b.fulfillment_set) == null ? void 0 : _c.location) == null ? void 0 : _d.id,
12057
- shipping_option_id: (_e = data.shippingOption) == null ? void 0 : _e.id,
12058
- custom_amount: (_f = data.shippingMethod) == null ? void 0 : _f.amount
12059
- }
12010
+ title,
12011
+ quantity,
12012
+ unit_price
12013
+ },
12014
+ resolver: zod.zodResolver(customItemSchema)
12060
12015
  });
12061
- const { mutateAsync: addShippingMethod, isPending } = useDraftOrderAddShippingMethod(order.id);
12062
- const {
12063
- mutateAsync: updateShippingMethod,
12064
- isPending: isUpdatingShippingMethod
12065
- } = useDraftOrderUpdateShippingMethod(order.id);
12066
- const onSubmit = form.handleSubmit(async (values) => {
12067
- if (lodash.isEqual(values, form.formState.defaultValues)) {
12068
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12016
+ React.useEffect(() => {
12017
+ form.reset({
12018
+ title,
12019
+ quantity,
12020
+ unit_price
12021
+ });
12022
+ }, [form, title, quantity, unit_price]);
12023
+ const actionId = React.useMemo(() => {
12024
+ var _a, _b;
12025
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
12026
+ }, [item]);
12027
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
12028
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
12029
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
12030
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
12031
+ const onSubmit = form.handleSubmit(async (data) => {
12032
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
12033
+ setEditing(false);
12069
12034
  return;
12070
12035
  }
12071
- if (data.shippingMethod) {
12072
- await updateShippingMethod(
12036
+ if (!actionId) {
12037
+ await updateOriginalItem(
12073
12038
  {
12074
- method_id: data.shippingMethod.id,
12075
- shipping_option_id: values.shipping_option_id,
12076
- custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
12039
+ item_id: item.id,
12040
+ quantity: data.quantity,
12041
+ unit_price: convertNumber(data.unit_price)
12077
12042
  },
12078
12043
  {
12044
+ onSuccess: () => {
12045
+ setEditing(false);
12046
+ },
12079
12047
  onError: (e) => {
12080
12048
  ui.toast.error(e.message);
12081
- },
12082
- onSuccess: () => {
12083
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12084
12049
  }
12085
12050
  }
12086
12051
  );
12087
12052
  return;
12088
12053
  }
12089
- await addShippingMethod(
12054
+ if (data.quantity === 0) {
12055
+ await removeActionItem(actionId, {
12056
+ onSuccess: () => {
12057
+ setEditing(false);
12058
+ },
12059
+ onError: (e) => {
12060
+ ui.toast.error(e.message);
12061
+ }
12062
+ });
12063
+ return;
12064
+ }
12065
+ await updateActionItem(
12090
12066
  {
12091
- shipping_option_id: values.shipping_option_id,
12092
- custom_amount: values.custom_amount ? convertNumber(values.custom_amount) : void 0
12067
+ action_id: actionId,
12068
+ quantity: data.quantity,
12069
+ unit_price: convertNumber(data.unit_price)
12093
12070
  },
12094
12071
  {
12072
+ onSuccess: () => {
12073
+ setEditing(false);
12074
+ },
12095
12075
  onError: (e) => {
12096
12076
  ui.toast.error(e.message);
12097
- },
12098
- onSuccess: () => {
12099
- setIsOpen(STACKED_FOCUS_MODAL_ID, false);
12100
12077
  }
12101
12078
  }
12102
12079
  );
12103
12080
  });
12104
- return /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs(
12105
- KeyboundForm,
12106
- {
12107
- className: "flex h-full flex-col overflow-hidden",
12108
- onSubmit,
12109
- children: [
12110
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Header, {}),
12111
- /* @__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 py-16 px-6", children: [
12112
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12113
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Shipping" }) }),
12114
- /* @__PURE__ */ jsxRuntime.jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a shipping method for the selected shipping profile. You can see the items that will be shipped using this method in the preview below." }) })
12115
- ] }),
12116
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12117
- /* @__PURE__ */ jsxRuntime.jsx(
12118
- LocationField,
12119
- {
12120
- control: form.control,
12121
- setValue: form.setValue
12122
- }
12123
- ),
12124
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12125
- /* @__PURE__ */ jsxRuntime.jsx(
12126
- ShippingOptionField,
12127
- {
12128
- shippingProfileId: data.shippingProfileId,
12129
- preview,
12130
- control: form.control
12131
- }
12132
- ),
12133
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12134
- /* @__PURE__ */ jsxRuntime.jsx(
12135
- CustomAmountField,
12136
- {
12137
- control: form.control,
12138
- currencyCode: order.currency_code
12139
- }
12140
- ),
12141
- /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12142
- /* @__PURE__ */ jsxRuntime.jsx(
12143
- ItemsPreview,
12144
- {
12145
- order,
12146
- shippingProfileId: data.shippingProfileId
12147
- }
12148
- )
12149
- ] }) }) }),
12150
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-x-2", children: [
12151
- /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12152
- /* @__PURE__ */ jsxRuntime.jsx(
12153
- ui.Button,
12154
- {
12155
- size: "small",
12156
- type: "submit",
12157
- isLoading: isPending || isUpdatingShippingMethod,
12158
- children: data.shippingMethod ? "Update" : "Add"
12159
- }
12160
- )
12161
- ] }) })
12162
- ]
12163
- }
12164
- ) }) });
12165
- };
12166
- const shippingMethodSchema = z.object({
12167
- location_id: z.string(),
12168
- shipping_option_id: z.string(),
12169
- custom_amount: z.union([z.number(), z.string()]).optional()
12170
- });
12171
- const ItemsPreview = ({ order, shippingProfileId }) => {
12172
- const matches = order.items.filter(
12173
- (item) => {
12174
- var _a, _b, _c;
12175
- return ((_c = (_b = (_a = item.variant) == null ? void 0 : _a.product) == null ? void 0 : _b.shipping_profile) == null ? void 0 : _c.id) === shippingProfileId;
12176
- }
12177
- );
12178
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
12179
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 items-center gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
12180
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "Items to ship" }),
12181
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Items with the selected shipping profile." })
12182
- ] }) }),
12183
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
12184
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 px-4 py-2 text-ui-fg-muted", children: [
12185
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Item" }) }),
12186
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Quantity" }) })
12187
- ] }),
12188
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
12189
- "div",
12081
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center", children: [
12082
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
12083
+ /* @__PURE__ */ jsxRuntime.jsx(
12084
+ Thumbnail,
12190
12085
  {
12191
- className: "grid grid-cols-2 gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center",
12192
- children: [
12193
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
12194
- /* @__PURE__ */ jsxRuntime.jsx(
12195
- Thumbnail,
12196
- {
12197
- thumbnail: item.thumbnail,
12198
- alt: item.product_title ?? void 0
12199
- }
12200
- ),
12201
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
12202
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
12203
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
12204
- /* @__PURE__ */ jsxRuntime.jsxs(
12205
- ui.Text,
12206
- {
12207
- size: "small",
12208
- leading: "compact",
12209
- className: "text-ui-fg-subtle",
12210
- children: [
12211
- "(",
12212
- item.variant_title,
12213
- ")"
12214
- ]
12215
- }
12216
- )
12217
- ] }),
12218
- /* @__PURE__ */ jsxRuntime.jsx(
12219
- ui.Text,
12220
- {
12221
- size: "small",
12222
- leading: "compact",
12223
- className: "text-ui-fg-subtle",
12224
- children: item.variant_sku
12225
- }
12226
- )
12227
- ] })
12228
- ] }),
12229
- /* @__PURE__ */ jsxRuntime.jsxs(
12230
- ui.Text,
12231
- {
12232
- size: "small",
12233
- leading: "compact",
12234
- className: "text-ui-fg-subtle",
12235
- children: [
12236
- item.quantity,
12237
- "x"
12238
- ]
12239
- }
12240
- )
12241
- ]
12242
- },
12243
- item.id
12244
- )) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1", children: [
12245
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
12246
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: [
12247
- 'No items found for "',
12248
- query,
12249
- '".'
12250
- ] })
12251
- ] }) })
12252
- ] })
12253
- ] });
12254
- };
12255
- const LocationField = ({ control, setValue }) => {
12256
- const locations = useComboboxData({
12257
- queryKey: ["locations"],
12258
- queryFn: async (params) => {
12259
- return await sdk.admin.stockLocation.list(params);
12260
- },
12261
- getOptions: (data) => {
12262
- return data.stock_locations.map((location) => ({
12263
- label: location.name,
12264
- value: location.id
12265
- }));
12266
- }
12267
- });
12268
- return /* @__PURE__ */ jsxRuntime.jsx(
12269
- Form$2.Field,
12270
- {
12271
- control,
12272
- name: "location_id",
12273
- render: ({ field: { onChange, ...field } }) => {
12274
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12275
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12276
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Location" }),
12277
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Choose where you want to ship the items from." })
12278
- ] }),
12279
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
12280
- Combobox,
12281
- {
12282
- options: locations.options,
12283
- fetchNextPage: locations.fetchNextPage,
12284
- isFetchingNextPage: locations.isFetchingNextPage,
12285
- searchValue: locations.searchValue,
12286
- onSearchValueChange: locations.onSearchValueChange,
12287
- placeholder: "Select location",
12288
- onChange: (value) => {
12289
- setValue("shipping_option_id", "", {
12290
- shouldDirty: true,
12291
- shouldTouch: true
12292
- });
12293
- onChange(value);
12294
- },
12295
- ...field
12086
+ thumbnail: item.thumbnail,
12087
+ alt: item.title ?? void 0
12088
+ }
12089
+ ),
12090
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
12091
+ Form$2.Field,
12092
+ {
12093
+ control: form.control,
12094
+ name: "title",
12095
+ render: ({ field }) => {
12096
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }) });
12097
+ }
12098
+ }
12099
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.title })
12100
+ ] }),
12101
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
12102
+ Form$2.Field,
12103
+ {
12104
+ control: form.control,
12105
+ name: "quantity",
12106
+ render: ({ field }) => {
12107
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field }) }) });
12108
+ }
12109
+ }
12110
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: item.quantity }),
12111
+ editing ? /* @__PURE__ */ jsxRuntime.jsx(
12112
+ Form$2.Field,
12113
+ {
12114
+ control: form.control,
12115
+ name: "unit_price",
12116
+ render: ({ field: { onChange, ...field } }) => {
12117
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
12118
+ ui.CurrencyInput,
12119
+ {
12120
+ ...field,
12121
+ symbol: getNativeSymbol(currencyCode),
12122
+ code: currencyCode,
12123
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
12296
12124
  }
12297
- ) })
12298
- ] }) });
12125
+ ) }) });
12126
+ }
12299
12127
  }
12300
- }
12301
- );
12128
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
12129
+ /* @__PURE__ */ jsxRuntime.jsx(
12130
+ ui.IconButton,
12131
+ {
12132
+ type: "button",
12133
+ size: "small",
12134
+ onClick: editing ? onSubmit : () => {
12135
+ setEditing(true);
12136
+ },
12137
+ disabled: isPending,
12138
+ children: editing ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.PencilSquare, {})
12139
+ }
12140
+ )
12141
+ ] }) }) });
12302
12142
  };
12303
- const ShippingOptionField = ({
12304
- shippingProfileId,
12305
- preview,
12306
- control
12143
+ const StackedModalTrigger = ({
12144
+ type,
12145
+ setModalContent
12307
12146
  }) => {
12308
- var _a;
12309
- const locationId = reactHookForm.useWatch({ control, name: "location_id" });
12310
- const shippingOptions = useComboboxData({
12311
- queryKey: ["shipping_options", locationId, shippingProfileId],
12312
- queryFn: async (params) => {
12313
- return await sdk.admin.shippingOption.list({
12314
- ...params,
12315
- stock_location_id: locationId,
12316
- shipping_profile_id: shippingProfileId
12317
- });
12318
- },
12319
- getOptions: (data) => {
12320
- return data.shipping_options.map((option) => {
12321
- var _a2;
12322
- if ((_a2 = option.rules) == null ? void 0 : _a2.find(
12323
- (r) => r.attribute === "is_return" && r.value === "true"
12324
- )) {
12325
- return void 0;
12147
+ const { setIsOpen } = useStackedModal();
12148
+ const onClick = React.useCallback(() => {
12149
+ setModalContent(type);
12150
+ setIsOpen(STACKED_MODAL_ID, true);
12151
+ }, [setModalContent, setIsOpen, type]);
12152
+ 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" }) });
12153
+ };
12154
+ const VARIANT_PREFIX = "items";
12155
+ const LIMIT = 50;
12156
+ const ExistingItemsForm = ({ orderId, items }) => {
12157
+ const { setIsOpen } = useStackedModal();
12158
+ const [rowSelection, setRowSelection] = React.useState(
12159
+ items.reduce((acc, item) => {
12160
+ acc[item.variant_id] = true;
12161
+ return acc;
12162
+ }, {})
12163
+ );
12164
+ React.useEffect(() => {
12165
+ setRowSelection(
12166
+ items.reduce((acc, item) => {
12167
+ if (item.variant_id) {
12168
+ acc[item.variant_id] = true;
12326
12169
  }
12327
- return {
12328
- label: option.name,
12329
- value: option.id
12330
- };
12331
- }).filter(Boolean);
12170
+ return acc;
12171
+ }, {})
12172
+ );
12173
+ }, [items]);
12174
+ const { q, order, offset } = useQueryParams(
12175
+ ["q", "order", "offset"],
12176
+ VARIANT_PREFIX
12177
+ );
12178
+ const { variants, count, isPending, isError, error } = useProductVariants(
12179
+ {
12180
+ q,
12181
+ order,
12182
+ offset: offset ? parseInt(offset) : void 0,
12183
+ limit: LIMIT
12332
12184
  },
12333
- enabled: !!locationId && !!shippingProfileId,
12334
- defaultValue: ((_a = preview.shipping_methods[0]) == null ? void 0 : _a.shipping_option_id) || void 0
12335
- });
12336
- const tooltipContent = !locationId && !shippingProfileId ? "Choose a location and shipping profile first." : !locationId ? "Choose a location first." : "Choose a shipping profile first.";
12337
- return /* @__PURE__ */ jsxRuntime.jsx(
12338
- Form$2.Field,
12339
12185
  {
12340
- control,
12341
- name: "shipping_option_id",
12342
- render: ({ field }) => {
12343
- return /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12344
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
12345
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Shipping option" }),
12346
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Choose the shipping option to use." })
12347
- ] }),
12348
- /* @__PURE__ */ jsxRuntime.jsx(
12349
- ConditionalTooltip,
12350
- {
12351
- content: tooltipContent,
12352
- showTooltip: !locationId || !shippingProfileId,
12353
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
12354
- Combobox,
12355
- {
12356
- options: shippingOptions.options,
12357
- fetchNextPage: shippingOptions.fetchNextPage,
12358
- isFetchingNextPage: shippingOptions.isFetchingNextPage,
12359
- searchValue: shippingOptions.searchValue,
12360
- onSearchValueChange: shippingOptions.onSearchValueChange,
12361
- placeholder: "Select shipping option",
12362
- ...field,
12363
- disabled: !locationId || !shippingProfileId
12364
- }
12365
- ) }) })
12366
- }
12367
- )
12368
- ] }) });
12186
+ placeholderData: reactQuery.keepPreviousData
12187
+ }
12188
+ );
12189
+ const columns = useColumns();
12190
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
12191
+ const onSubmit = async () => {
12192
+ const ids = Object.keys(rowSelection).filter(
12193
+ (id) => !items.find((i) => i.variant_id === id)
12194
+ );
12195
+ await mutateAsync(
12196
+ {
12197
+ items: ids.map((id) => ({
12198
+ variant_id: id,
12199
+ quantity: 1
12200
+ }))
12201
+ },
12202
+ {
12203
+ onSuccess: () => {
12204
+ setRowSelection({});
12205
+ setIsOpen(STACKED_MODAL_ID, false);
12206
+ },
12207
+ onError: (e) => {
12208
+ ui.toast.error(e.message);
12209
+ }
12369
12210
  }
12211
+ );
12212
+ };
12213
+ if (isError) {
12214
+ throw error;
12215
+ }
12216
+ return /* @__PURE__ */ jsxRuntime.jsxs(
12217
+ StackedFocusModal.Content,
12218
+ {
12219
+ onOpenAutoFocus: (e) => {
12220
+ e.preventDefault();
12221
+ const searchInput = document.querySelector(
12222
+ "[data-modal-id='modal-search-input']"
12223
+ );
12224
+ if (searchInput) {
12225
+ searchInput.focus();
12226
+ }
12227
+ },
12228
+ children: [
12229
+ /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Header, { children: [
12230
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Product Variants" }) }),
12231
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
12232
+ ] }),
12233
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
12234
+ DataTable,
12235
+ {
12236
+ data: variants,
12237
+ columns,
12238
+ isLoading: isPending,
12239
+ getRowId: (row) => row.id,
12240
+ rowCount: count,
12241
+ prefix: VARIANT_PREFIX,
12242
+ layout: "fill",
12243
+ rowSelection: {
12244
+ state: rowSelection,
12245
+ onRowSelectionChange: setRowSelection,
12246
+ enableRowSelection: (row) => {
12247
+ return !items.find((i) => i.variant_id === row.original.id);
12248
+ }
12249
+ },
12250
+ autoFocusSearch: true
12251
+ }
12252
+ ) }),
12253
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
12254
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12255
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
12256
+ ] }) })
12257
+ ]
12370
12258
  }
12371
12259
  );
12372
12260
  };
12373
- const CustomAmountField = ({
12374
- control,
12375
- currencyCode
12376
- }) => {
12377
- return /* @__PURE__ */ jsxRuntime.jsx(
12378
- Form$2.Field,
12379
- {
12380
- control,
12381
- name: "custom_amount",
12382
- render: ({ field: { onChange, ...field } }) => {
12383
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12384
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
12385
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { optional: true, children: "Custom amount" }),
12386
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
12387
- ] }),
12388
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
12389
- ui.CurrencyInput,
12261
+ const columnHelper = ui.createDataTableColumnHelper();
12262
+ const useColumns = () => {
12263
+ return React.useMemo(() => {
12264
+ return [
12265
+ columnHelper.select(),
12266
+ columnHelper.accessor("product.title", {
12267
+ header: "Product",
12268
+ cell: ({ row }) => {
12269
+ var _a, _b, _c;
12270
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
12271
+ /* @__PURE__ */ jsxRuntime.jsx(
12272
+ Thumbnail,
12273
+ {
12274
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
12275
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
12276
+ }
12277
+ ),
12278
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
12279
+ ] });
12280
+ },
12281
+ enableSorting: true
12282
+ }),
12283
+ columnHelper.accessor("title", {
12284
+ header: "Variant",
12285
+ enableSorting: true
12286
+ }),
12287
+ columnHelper.accessor("sku", {
12288
+ header: "SKU",
12289
+ cell: ({ getValue }) => {
12290
+ return getValue() ?? "-";
12291
+ },
12292
+ enableSorting: true
12293
+ }),
12294
+ columnHelper.accessor("updated_at", {
12295
+ header: "Updated",
12296
+ cell: ({ getValue }) => {
12297
+ return /* @__PURE__ */ jsxRuntime.jsx(
12298
+ ui.Tooltip,
12299
+ {
12300
+ content: getFullDate({ date: getValue(), includeTime: true }),
12301
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
12302
+ }
12303
+ );
12304
+ },
12305
+ enableSorting: true,
12306
+ sortAscLabel: "Oldest first",
12307
+ sortDescLabel: "Newest first"
12308
+ }),
12309
+ columnHelper.accessor("created_at", {
12310
+ header: "Created",
12311
+ cell: ({ getValue }) => {
12312
+ return /* @__PURE__ */ jsxRuntime.jsx(
12313
+ ui.Tooltip,
12390
12314
  {
12391
- ...field,
12392
- onValueChange: (value) => onChange(value),
12393
- symbol: getNativeSymbol(currencyCode),
12394
- code: currencyCode
12315
+ content: getFullDate({ date: getValue(), includeTime: true }),
12316
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: getFullDate({ date: getValue() }) })
12395
12317
  }
12396
- ) })
12397
- ] });
12318
+ );
12319
+ },
12320
+ enableSorting: true,
12321
+ sortAscLabel: "Oldest first",
12322
+ sortDescLabel: "Newest first"
12323
+ })
12324
+ ];
12325
+ }, []);
12326
+ };
12327
+ const CustomItemForm = ({ orderId, currencyCode }) => {
12328
+ const { setIsOpen } = useStackedModal();
12329
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
12330
+ const form = reactHookForm.useForm({
12331
+ defaultValues: {
12332
+ title: "",
12333
+ quantity: 1,
12334
+ unit_price: ""
12335
+ },
12336
+ resolver: zod.zodResolver(customItemSchema)
12337
+ });
12338
+ const onSubmit = form.handleSubmit(async (data) => {
12339
+ await addItems(
12340
+ {
12341
+ items: [
12342
+ {
12343
+ title: data.title,
12344
+ quantity: data.quantity,
12345
+ unit_price: convertNumber(data.unit_price)
12346
+ }
12347
+ ]
12348
+ },
12349
+ {
12350
+ onSuccess: () => {
12351
+ setIsOpen(STACKED_MODAL_ID, false);
12352
+ },
12353
+ onError: (e) => {
12354
+ ui.toast.error(e.message);
12355
+ }
12398
12356
  }
12399
- }
12400
- );
12357
+ );
12358
+ });
12359
+ return /* @__PURE__ */ jsxRuntime.jsx(Form$2, { ...form, children: /* @__PURE__ */ jsxRuntime.jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(StackedFocusModal.Content, { children: [
12360
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Header, {}),
12361
+ /* @__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: [
12362
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12363
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Add custom item" }) }),
12364
+ /* @__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." }) })
12365
+ ] }),
12366
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12367
+ /* @__PURE__ */ jsxRuntime.jsx(
12368
+ Form$2.Field,
12369
+ {
12370
+ control: form.control,
12371
+ name: "title",
12372
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12373
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12374
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Title" }),
12375
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the title of the item" })
12376
+ ] }),
12377
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12378
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
12379
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
12380
+ ] })
12381
+ ] }) })
12382
+ }
12383
+ ),
12384
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12385
+ /* @__PURE__ */ jsxRuntime.jsx(
12386
+ Form$2.Field,
12387
+ {
12388
+ control: form.control,
12389
+ name: "unit_price",
12390
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12391
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12392
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Unit price" }),
12393
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
12394
+ ] }),
12395
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12396
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
12397
+ ui.CurrencyInput,
12398
+ {
12399
+ symbol: getNativeSymbol(currencyCode),
12400
+ code: currencyCode,
12401
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
12402
+ ...field
12403
+ }
12404
+ ) }),
12405
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
12406
+ ] })
12407
+ ] }) })
12408
+ }
12409
+ ),
12410
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Divider, { variant: "dashed" }),
12411
+ /* @__PURE__ */ jsxRuntime.jsx(
12412
+ Form$2.Field,
12413
+ {
12414
+ control: form.control,
12415
+ name: "quantity",
12416
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Form$2.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
12417
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
12418
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Quantity" }),
12419
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
12420
+ ] }),
12421
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 w-full", children: [
12422
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...field, className: "w-full" }) }) }),
12423
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
12424
+ ] })
12425
+ ] }) })
12426
+ }
12427
+ )
12428
+ ] }) }) }),
12429
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 justify-end", children: [
12430
+ /* @__PURE__ */ jsxRuntime.jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12431
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
12432
+ ] }) })
12433
+ ] }) }) });
12401
12434
  };
12435
+ const customItemSchema = z.object({
12436
+ title: z.string().min(1),
12437
+ quantity: z.number(),
12438
+ unit_price: z.union([z.number(), z.string()])
12439
+ });
12402
12440
  const ShippingAddress = () => {
12403
12441
  const { id } = reactRouterDom.useParams();
12404
12442
  const { order, isPending, isError, error } = useOrder(id, {
@@ -13078,33 +13116,27 @@ const Illustration = () => {
13078
13116
  const schema$1 = z.object({
13079
13117
  customer_id: z.string().min(1)
13080
13118
  });
13081
- const SalesChannel = () => {
13119
+ const Email = () => {
13082
13120
  const { id } = reactRouterDom.useParams();
13083
- const { draft_order, isPending, isError, error } = useDraftOrder(
13084
- id,
13085
- {
13086
- fields: "+sales_channel_id"
13087
- },
13088
- {
13089
- enabled: !!id
13090
- }
13091
- );
13121
+ const { order, isPending, isError, error } = useOrder(id, {
13122
+ fields: "+email"
13123
+ });
13092
13124
  if (isError) {
13093
13125
  throw error;
13094
13126
  }
13095
- const ISrEADY = !!draft_order && !isPending;
13127
+ const isReady = !isPending && !!order;
13096
13128
  return /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer, { children: [
13097
13129
  /* @__PURE__ */ jsxRuntime.jsxs(RouteDrawer.Header, { children: [
13098
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Sales Channel" }) }),
13099
- /* @__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" }) })
13130
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { children: "Edit Email" }) }),
13131
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
13100
13132
  ] }),
13101
- ISrEADY && /* @__PURE__ */ jsxRuntime.jsx(SalesChannelForm, { order: draft_order })
13133
+ isReady && /* @__PURE__ */ jsxRuntime.jsx(EmailForm, { order })
13102
13134
  ] });
13103
13135
  };
13104
- const SalesChannelForm = ({ order }) => {
13136
+ const EmailForm = ({ order }) => {
13105
13137
  const form = reactHookForm.useForm({
13106
13138
  defaultValues: {
13107
- sales_channel_id: order.sales_channel_id || ""
13139
+ email: order.email ?? ""
13108
13140
  },
13109
13141
  resolver: zod.zodResolver(schema)
13110
13142
  });
@@ -13112,12 +13144,9 @@ const SalesChannelForm = ({ order }) => {
13112
13144
  const { handleSuccess } = useRouteModal();
13113
13145
  const onSubmit = form.handleSubmit(async (data) => {
13114
13146
  await mutateAsync(
13115
- {
13116
- sales_channel_id: data.sales_channel_id
13117
- },
13147
+ { email: data.email },
13118
13148
  {
13119
13149
  onSuccess: () => {
13120
- ui.toast.success("Sales channel updated");
13121
13150
  handleSuccess();
13122
13151
  },
13123
13152
  onError: (error) => {
@@ -13132,7 +13161,18 @@ const SalesChannelForm = ({ order }) => {
13132
13161
  className: "flex flex-1 flex-col overflow-hidden",
13133
13162
  onSubmit,
13134
13163
  children: [
13135
- /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(SalesChannelField, { control: form.control, order }) }),
13164
+ /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
13165
+ Form$2.Field,
13166
+ {
13167
+ control: form.control,
13168
+ name: "email",
13169
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
13170
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Email" }),
13171
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field }) }),
13172
+ /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
13173
+ ] })
13174
+ }
13175
+ ) }),
13136
13176
  /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
13137
13177
  /* @__PURE__ */ jsxRuntime.jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
13138
13178
  /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
@@ -13141,48 +13181,8 @@ const SalesChannelForm = ({ order }) => {
13141
13181
  }
13142
13182
  ) });
13143
13183
  };
13144
- const SalesChannelField = ({ control, order }) => {
13145
- const salesChannels = useComboboxData({
13146
- queryFn: async (params) => {
13147
- return await sdk.admin.salesChannel.list(params);
13148
- },
13149
- queryKey: ["sales-channels"],
13150
- getOptions: (data) => {
13151
- return data.sales_channels.map((salesChannel) => ({
13152
- label: salesChannel.name,
13153
- value: salesChannel.id
13154
- }));
13155
- },
13156
- defaultValue: order.sales_channel_id || void 0
13157
- });
13158
- return /* @__PURE__ */ jsxRuntime.jsx(
13159
- Form$2.Field,
13160
- {
13161
- control,
13162
- name: "sales_channel_id",
13163
- render: ({ field }) => {
13164
- return /* @__PURE__ */ jsxRuntime.jsxs(Form$2.Item, { children: [
13165
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Label, { children: "Sales Channel" }),
13166
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.Control, { children: /* @__PURE__ */ jsxRuntime.jsx(
13167
- Combobox,
13168
- {
13169
- options: salesChannels.options,
13170
- fetchNextPage: salesChannels.fetchNextPage,
13171
- isFetchingNextPage: salesChannels.isFetchingNextPage,
13172
- searchValue: salesChannels.searchValue,
13173
- onSearchValueChange: salesChannels.onSearchValueChange,
13174
- placeholder: "Select sales channel",
13175
- ...field
13176
- }
13177
- ) }),
13178
- /* @__PURE__ */ jsxRuntime.jsx(Form$2.ErrorMessage, {})
13179
- ] });
13180
- }
13181
- }
13182
- );
13183
- };
13184
13184
  const schema = z.object({
13185
- sales_channel_id: z.string().min(1)
13185
+ email: z.string().email()
13186
13186
  });
13187
13187
  const widgetModule = { widgets: [] };
13188
13188
  const routeModule = {
@@ -13205,32 +13205,32 @@ const routeModule = {
13205
13205
  loader,
13206
13206
  children: [
13207
13207
  {
13208
- Component: CustomItems,
13209
- path: "/draft-orders/:id/custom-items"
13208
+ Component: BillingAddress,
13209
+ path: "/draft-orders/:id/billing-address"
13210
13210
  },
13211
13211
  {
13212
- Component: Email,
13213
- path: "/draft-orders/:id/email"
13212
+ Component: CustomItems,
13213
+ path: "/draft-orders/:id/custom-items"
13214
13214
  },
13215
13215
  {
13216
- Component: BillingAddress,
13217
- path: "/draft-orders/:id/billing-address"
13216
+ Component: Metadata,
13217
+ path: "/draft-orders/:id/metadata"
13218
13218
  },
13219
13219
  {
13220
13220
  Component: Promotions,
13221
13221
  path: "/draft-orders/:id/promotions"
13222
13222
  },
13223
13223
  {
13224
- Component: Items,
13225
- path: "/draft-orders/:id/items"
13224
+ Component: Shipping,
13225
+ path: "/draft-orders/:id/shipping"
13226
13226
  },
13227
13227
  {
13228
- Component: Metadata,
13229
- path: "/draft-orders/:id/metadata"
13228
+ Component: SalesChannel,
13229
+ path: "/draft-orders/:id/sales-channel"
13230
13230
  },
13231
13231
  {
13232
- Component: Shipping,
13233
- path: "/draft-orders/:id/shipping"
13232
+ Component: Items,
13233
+ path: "/draft-orders/:id/items"
13234
13234
  },
13235
13235
  {
13236
13236
  Component: ShippingAddress,
@@ -13241,8 +13241,8 @@ const routeModule = {
13241
13241
  path: "/draft-orders/:id/transfer-ownership"
13242
13242
  },
13243
13243
  {
13244
- Component: SalesChannel,
13245
- path: "/draft-orders/:id/sales-channel"
13244
+ Component: Email,
13245
+ path: "/draft-orders/:id/email"
13246
13246
  }
13247
13247
  ]
13248
13248
  }