@medusajs/draft-order 2.11.4-preview-20251106090134 → 2.11.4-preview-20251106120154

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