@medusajs/draft-order 2.11.4-preview-20251122000259 → 2.11.4-preview-20251122060134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { Tooltip, DropdownMenu, clx, IconButton, useDataTable, DataTable as Data
4
4
  import { useQuery, useQueryClient, useMutation, keepPreviousData, useInfiniteQuery } from "@tanstack/react-query";
5
5
  import React, { useState, useCallback, useMemo, Fragment, createContext, forwardRef, useId, useContext, useTransition, useRef, useImperativeHandle, useDeferredValue, useEffect, Suspense } from "react";
6
6
  import { useSearchParams, Link, useNavigate, Outlet, useBlocker, useLocation, useParams } from "react-router-dom";
7
- import { EllipsisHorizontal, XMark, InformationCircleSolid, XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini, ExclamationCircleSolid, ArrowPath, FlyingBox, CurrencyDollar, Envelope, Channels, Trash, ArrowUpRightOnBox, TriangleDownMini, Check, SquareTwoStack, Photo, TriangleRightMini, Shopping, Buildings, TruckFast, Plus, ReceiptPercent, Minus, PencilSquare, EllipsisVertical, ArrowUpMini, ArrowDownMini } from "@medusajs/icons";
7
+ import { EllipsisHorizontal, XMark, InformationCircleSolid, XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini, ExclamationCircleSolid, ArrowPath, FlyingBox, CurrencyDollar, Envelope, Channels, Trash, ArrowUpRightOnBox, TriangleDownMini, Check, SquareTwoStack, Photo, TriangleRightMini, Shopping, Buildings, TruckFast, Plus, ReceiptPercent, EllipsisVertical, ArrowUpMini, ArrowDownMini, Minus, PencilSquare } from "@medusajs/icons";
8
8
  import Medusa from "@medusajs/js-sdk";
9
9
  import { format, formatDistance, sub, subDays, subMonths } from "date-fns";
10
10
  import { enUS } from "date-fns/locale";
@@ -9776,892 +9776,873 @@ const CustomItemsForm = () => {
9776
9776
  const schema$4 = objectType({
9777
9777
  email: stringType().email()
9778
9778
  });
9779
- const NumberInput = forwardRef(
9780
- ({
9781
- value,
9782
- onChange,
9783
- size = "base",
9784
- min = 0,
9785
- max = 100,
9786
- step = 1,
9787
- className,
9788
- disabled,
9789
- ...props
9790
- }, ref) => {
9791
- const handleChange = (event) => {
9792
- const newValue = event.target.value === "" ? min : Number(event.target.value);
9793
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9794
- onChange(newValue);
9795
- }
9796
- };
9797
- const handleIncrement = () => {
9798
- const newValue = value + step;
9799
- if (max === void 0 || newValue <= max) {
9800
- onChange(newValue);
9801
- }
9802
- };
9803
- const handleDecrement = () => {
9804
- const newValue = value - step;
9805
- if (min === void 0 || newValue >= min) {
9806
- onChange(newValue);
9779
+ const Email = () => {
9780
+ const { id } = useParams();
9781
+ const { order, isPending, isError, error } = useOrder(id, {
9782
+ fields: "+email"
9783
+ });
9784
+ if (isError) {
9785
+ throw error;
9786
+ }
9787
+ const isReady = !isPending && !!order;
9788
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9789
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9790
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
9791
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
9792
+ ] }),
9793
+ isReady && /* @__PURE__ */ jsx(EmailForm, { order })
9794
+ ] });
9795
+ };
9796
+ const EmailForm = ({ order }) => {
9797
+ const form = useForm({
9798
+ defaultValues: {
9799
+ email: order.email ?? ""
9800
+ },
9801
+ resolver: zodResolver(schema$3)
9802
+ });
9803
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9804
+ const { handleSuccess } = useRouteModal();
9805
+ const onSubmit = form.handleSubmit(async (data) => {
9806
+ await mutateAsync(
9807
+ { email: data.email },
9808
+ {
9809
+ onSuccess: () => {
9810
+ handleSuccess();
9811
+ },
9812
+ onError: (error) => {
9813
+ toast.error(error.message);
9814
+ }
9807
9815
  }
9808
- };
9816
+ );
9817
+ });
9818
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9819
+ KeyboundForm,
9820
+ {
9821
+ className: "flex flex-1 flex-col overflow-hidden",
9822
+ onSubmit,
9823
+ children: [
9824
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
9825
+ Form$2.Field,
9826
+ {
9827
+ control: form.control,
9828
+ name: "email",
9829
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9830
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
9831
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9832
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9833
+ ] })
9834
+ }
9835
+ ) }),
9836
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9837
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9838
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9839
+ ] }) })
9840
+ ]
9841
+ }
9842
+ ) });
9843
+ };
9844
+ const schema$3 = objectType({
9845
+ email: stringType().email()
9846
+ });
9847
+ const InlineTip = forwardRef(
9848
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
9849
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
9809
9850
  return /* @__PURE__ */ jsxs(
9810
9851
  "div",
9811
9852
  {
9853
+ ref,
9812
9854
  className: clx(
9813
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9814
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9815
- {
9816
- "h-7": size === "small",
9817
- "h-8": size === "base"
9818
- },
9855
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
9819
9856
  className
9820
9857
  ),
9858
+ ...props,
9821
9859
  children: [
9822
9860
  /* @__PURE__ */ jsx(
9823
- "input",
9824
- {
9825
- ref,
9826
- type: "number",
9827
- value,
9828
- onChange: handleChange,
9829
- min,
9830
- max,
9831
- step,
9832
- className: clx(
9833
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9834
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9835
- "placeholder:text-ui-fg-muted"
9836
- ),
9837
- ...props
9838
- }
9839
- ),
9840
- /* @__PURE__ */ jsxs(
9841
- "button",
9861
+ "div",
9842
9862
  {
9843
- className: clx(
9844
- "flex items-center justify-center outline-none transition-fg",
9845
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9846
- "focus:bg-ui-bg-field-component-hover",
9847
- "hover:bg-ui-bg-field-component-hover",
9848
- {
9849
- "size-7": size === "small",
9850
- "size-8": size === "base"
9851
- }
9852
- ),
9853
- type: "button",
9854
- onClick: handleDecrement,
9855
- disabled: min !== void 0 && value <= min || disabled,
9856
- children: [
9857
- /* @__PURE__ */ jsx(Minus, {}),
9858
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9859
- ]
9863
+ role: "presentation",
9864
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
9865
+ "bg-ui-tag-orange-icon": variant === "warning"
9866
+ })
9860
9867
  }
9861
9868
  ),
9862
- /* @__PURE__ */ jsxs(
9863
- "button",
9864
- {
9865
- className: clx(
9866
- "flex items-center justify-center outline-none transition-fg",
9867
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9868
- "focus:bg-ui-bg-field-hover",
9869
- "hover:bg-ui-bg-field-hover",
9870
- {
9871
- "size-7": size === "small",
9872
- "size-8": size === "base"
9873
- }
9874
- ),
9875
- type: "button",
9876
- onClick: handleIncrement,
9877
- disabled: max !== void 0 && value >= max || disabled,
9878
- children: [
9879
- /* @__PURE__ */ jsx(Plus, {}),
9880
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9881
- ]
9882
- }
9883
- )
9869
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
9870
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
9871
+ labelValue,
9872
+ ":"
9873
+ ] }),
9874
+ " ",
9875
+ children
9876
+ ] })
9884
9877
  ]
9885
9878
  }
9886
9879
  );
9887
9880
  }
9888
9881
  );
9889
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9890
- const productVariantsQueryKeys = {
9891
- list: (query2) => [
9892
- PRODUCT_VARIANTS_QUERY_KEY,
9893
- query2 ? query2 : void 0
9894
- ]
9895
- };
9896
- const useProductVariants = (query2, options) => {
9897
- const { data, ...rest } = useQuery({
9898
- queryKey: productVariantsQueryKeys.list(query2),
9899
- queryFn: async () => await sdk.admin.productVariant.list(query2),
9900
- ...options
9882
+ InlineTip.displayName = "InlineTip";
9883
+ const MetadataFieldSchema = objectType({
9884
+ key: stringType(),
9885
+ disabled: booleanType().optional(),
9886
+ value: anyType()
9887
+ });
9888
+ const MetadataSchema = objectType({
9889
+ metadata: arrayType(MetadataFieldSchema)
9890
+ });
9891
+ const Metadata = () => {
9892
+ const { id } = useParams();
9893
+ const { order, isPending, isError, error } = useOrder(id, {
9894
+ fields: "metadata"
9901
9895
  });
9902
- return { ...data, ...rest };
9896
+ if (isError) {
9897
+ throw error;
9898
+ }
9899
+ const isReady = !isPending && !!order;
9900
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9901
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9902
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
9903
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
9904
+ ] }),
9905
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
9906
+ ] });
9903
9907
  };
9904
- const useCancelOrderEdit = ({ preview }) => {
9905
- const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
9906
- const onCancel = useCallback(async () => {
9907
- if (!preview) {
9908
- return true;
9909
- }
9910
- let res = false;
9911
- await cancelOrderEdit(void 0, {
9912
- onError: (e) => {
9913
- toast.error(e.message);
9908
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
9909
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
9910
+ const MetadataForm = ({ orderId, metadata }) => {
9911
+ const { handleSuccess } = useRouteModal();
9912
+ const hasUneditableRows = getHasUneditableRows(metadata);
9913
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
9914
+ const form = useForm({
9915
+ defaultValues: {
9916
+ metadata: getDefaultValues(metadata)
9917
+ },
9918
+ resolver: zodResolver(MetadataSchema)
9919
+ });
9920
+ const handleSubmit = form.handleSubmit(async (data) => {
9921
+ const parsedData = parseValues(data);
9922
+ await mutateAsync(
9923
+ {
9924
+ metadata: parsedData
9914
9925
  },
9915
- onSuccess: () => {
9916
- res = true;
9926
+ {
9927
+ onSuccess: () => {
9928
+ toast.success("Metadata updated");
9929
+ handleSuccess();
9930
+ },
9931
+ onError: (error) => {
9932
+ toast.error(error.message);
9933
+ }
9917
9934
  }
9918
- });
9919
- return res;
9920
- }, [preview, cancelOrderEdit]);
9921
- return { onCancel };
9922
- };
9923
- let IS_REQUEST_RUNNING = false;
9924
- const useInitiateOrderEdit = ({
9925
- preview
9926
- }) => {
9927
- const navigate = useNavigate();
9928
- const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
9929
- useEffect(() => {
9930
- async function run() {
9931
- if (IS_REQUEST_RUNNING || !preview) {
9932
- return;
9933
- }
9934
- if (preview.order_change) {
9935
- return;
9936
- }
9937
- IS_REQUEST_RUNNING = true;
9938
- await mutateAsync(void 0, {
9939
- onError: (e) => {
9940
- toast.error(e.message);
9941
- navigate(`/draft-orders/${preview.id}`, { replace: true });
9942
- return;
9943
- }
9944
- });
9945
- IS_REQUEST_RUNNING = false;
9946
- }
9947
- run();
9948
- }, [preview, navigate, mutateAsync]);
9949
- };
9950
- function convertNumber(value) {
9951
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
9952
- }
9953
- const STACKED_MODAL_ID = "items_stacked_modal";
9954
- const Items = () => {
9955
- const { id } = useParams();
9956
- const {
9957
- order: preview,
9958
- isPending: isPreviewPending,
9959
- isError: isPreviewError,
9960
- error: previewError
9961
- } = useOrderPreview(id, void 0, {
9962
- placeholderData: keepPreviousData
9935
+ );
9963
9936
  });
9964
- useInitiateOrderEdit({ preview });
9965
- const { draft_order, isPending, isError, error } = useDraftOrder(
9966
- id,
9967
- {
9968
- fields: "currency_code"
9969
- },
9970
- {
9971
- enabled: !!id
9937
+ const { fields, insert, remove } = useFieldArray({
9938
+ control: form.control,
9939
+ name: "metadata"
9940
+ });
9941
+ function deleteRow(index) {
9942
+ remove(index);
9943
+ if (fields.length === 1) {
9944
+ insert(0, {
9945
+ key: "",
9946
+ value: "",
9947
+ disabled: false
9948
+ });
9972
9949
  }
9973
- );
9974
- const { onCancel } = useCancelOrderEdit({ preview });
9975
- if (isError) {
9976
- throw error;
9977
- }
9978
- if (isPreviewError) {
9979
- throw previewError;
9980
9950
  }
9981
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
9982
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
9983
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
9984
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
9985
- ] }) });
9986
- };
9987
- const ItemsForm = ({ preview, currencyCode }) => {
9988
- var _a;
9989
- const [isSubmitting, setIsSubmitting] = useState(false);
9990
- const [modalContent, setModalContent] = useState(
9991
- null
9992
- );
9993
- const { handleSuccess } = useRouteModal();
9994
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
9995
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
9996
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
9997
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
9998
- const matches = useMemo(() => {
9999
- return matchSorter(preview.items, query2, {
10000
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10001
- });
10002
- }, [preview.items, query2]);
10003
- const onSubmit = async () => {
10004
- setIsSubmitting(true);
10005
- let requestSucceeded = false;
10006
- await requestOrderEdit(void 0, {
10007
- onError: (e) => {
10008
- toast.error(`Failed to request order edit: ${e.message}`);
10009
- },
10010
- onSuccess: () => {
10011
- requestSucceeded = true;
10012
- }
10013
- });
10014
- if (!requestSucceeded) {
10015
- setIsSubmitting(false);
10016
- return;
10017
- }
10018
- await confirmOrderEdit(void 0, {
10019
- onError: (e) => {
10020
- toast.error(`Failed to confirm order edit: ${e.message}`);
10021
- },
10022
- onSuccess: () => {
10023
- handleSuccess();
10024
- },
10025
- onSettled: () => {
10026
- setIsSubmitting(false);
10027
- }
9951
+ function insertRow(index, position) {
9952
+ insert(index + (position === "above" ? 0 : 1), {
9953
+ key: "",
9954
+ value: "",
9955
+ disabled: false
10028
9956
  });
10029
- };
10030
- const onKeyDown = useCallback(
10031
- (e) => {
10032
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10033
- if (modalContent || isSubmitting) {
10034
- return;
10035
- }
10036
- onSubmit();
10037
- }
10038
- },
10039
- [modalContent, isSubmitting, onSubmit]
10040
- );
10041
- useEffect(() => {
10042
- document.addEventListener("keydown", onKeyDown);
10043
- return () => {
10044
- document.removeEventListener("keydown", onKeyDown);
10045
- };
10046
- }, [onKeyDown]);
10047
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10048
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10049
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10050
- StackedFocusModal,
10051
- {
10052
- id: STACKED_MODAL_ID,
10053
- onOpenChangeCallback: (open) => {
10054
- if (!open) {
10055
- setModalContent(null);
10056
- }
10057
- },
10058
- children: [
10059
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
10060
- /* @__PURE__ */ jsxs("div", { children: [
10061
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10062
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order" }) })
9957
+ }
9958
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9959
+ KeyboundForm,
9960
+ {
9961
+ onSubmit: handleSubmit,
9962
+ className: "flex flex-1 flex-col overflow-hidden",
9963
+ children: [
9964
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
9965
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
9966
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
9967
+ /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_KEY_LABEL_ID, children: "Key" }) }),
9968
+ /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_VALUE_LABEL_ID, children: "Value" }) })
10063
9969
  ] }),
10064
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10065
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10066
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10067
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10068
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10069
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10070
- ] }),
10071
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10072
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10073
- Input,
10074
- {
10075
- type: "search",
10076
- placeholder: "Search items",
10077
- value: searchValue,
10078
- onChange: (e) => onSearchValueChange(e.target.value)
10079
- }
10080
- ) }),
10081
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10082
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10083
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
9970
+ fields.map((field, index) => {
9971
+ const isDisabled = field.disabled || false;
9972
+ let placeholder = "-";
9973
+ if (typeof field.value === "object") {
9974
+ placeholder = "{ ... }";
9975
+ }
9976
+ if (Array.isArray(field.value)) {
9977
+ placeholder = "[ ... ]";
9978
+ }
9979
+ return /* @__PURE__ */ jsx(
9980
+ ConditionalTooltip,
9981
+ {
9982
+ showTooltip: isDisabled,
9983
+ content: "This row is disabled because it contains non-primitive data.",
9984
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
9985
+ /* @__PURE__ */ jsxs(
9986
+ "div",
9987
+ {
9988
+ className: clx("grid grid-cols-2 divide-x", {
9989
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
9990
+ }),
9991
+ children: [
9992
+ /* @__PURE__ */ jsx(
9993
+ Form$2.Field,
9994
+ {
9995
+ control: form.control,
9996
+ name: `metadata.${index}.key`,
9997
+ render: ({ field: field2 }) => {
9998
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
9999
+ GridInput,
10000
+ {
10001
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
10002
+ ...field2,
10003
+ disabled: isDisabled,
10004
+ placeholder: "Key"
10005
+ }
10006
+ ) }) });
10007
+ }
10008
+ }
10009
+ ),
10010
+ /* @__PURE__ */ jsx(
10011
+ Form$2.Field,
10012
+ {
10013
+ control: form.control,
10014
+ name: `metadata.${index}.value`,
10015
+ render: ({ field: { value, ...field2 } }) => {
10016
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10017
+ GridInput,
10018
+ {
10019
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
10020
+ ...field2,
10021
+ value: isDisabled ? placeholder : value,
10022
+ disabled: isDisabled,
10023
+ placeholder: "Value"
10024
+ }
10025
+ ) }) });
10026
+ }
10027
+ }
10028
+ )
10029
+ ]
10030
+ }
10031
+ ),
10032
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10084
10033
  /* @__PURE__ */ jsx(
10085
- StackedModalTrigger$1,
10034
+ DropdownMenu.Trigger,
10086
10035
  {
10087
- type: "add-items",
10088
- setModalContent
10089
- }
10090
- ),
10091
- /* @__PURE__ */ jsx(
10092
- StackedModalTrigger$1,
10093
- {
10094
- type: "add-custom-item",
10095
- setModalContent
10036
+ className: clx(
10037
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10038
+ {
10039
+ hidden: isDisabled
10040
+ }
10041
+ ),
10042
+ disabled: isDisabled,
10043
+ asChild: true,
10044
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10096
10045
  }
10097
- )
10046
+ ),
10047
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10048
+ /* @__PURE__ */ jsxs(
10049
+ DropdownMenu.Item,
10050
+ {
10051
+ className: "gap-x-2",
10052
+ onClick: () => insertRow(index, "above"),
10053
+ children: [
10054
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10055
+ "Insert row above"
10056
+ ]
10057
+ }
10058
+ ),
10059
+ /* @__PURE__ */ jsxs(
10060
+ DropdownMenu.Item,
10061
+ {
10062
+ className: "gap-x-2",
10063
+ onClick: () => insertRow(index, "below"),
10064
+ children: [
10065
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10066
+ "Insert row below"
10067
+ ]
10068
+ }
10069
+ ),
10070
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10071
+ /* @__PURE__ */ jsxs(
10072
+ DropdownMenu.Item,
10073
+ {
10074
+ className: "gap-x-2",
10075
+ onClick: () => deleteRow(index),
10076
+ children: [
10077
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10078
+ "Delete row"
10079
+ ]
10080
+ }
10081
+ )
10082
+ ] })
10098
10083
  ] })
10099
10084
  ] })
10100
- ] })
10101
- ] }),
10102
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10103
- /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
10104
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10105
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10106
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10107
- /* @__PURE__ */ jsx("div", {})
10108
- ] }) }),
10109
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10110
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10111
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10112
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10113
- Item,
10114
- {
10115
- item,
10116
- preview,
10117
- currencyCode
10118
- },
10119
- item.id
10120
- )) : /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10121
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10122
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10123
- 'No items found for "',
10124
- query2,
10125
- '".'
10126
- ] })
10127
- ] }) })
10128
- ] })
10129
- ] }),
10130
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10131
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10132
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10133
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10134
- Text,
10135
- {
10136
- size: "small",
10137
- leading: "compact",
10138
- className: "text-ui-fg-subtle",
10139
- children: [
10140
- itemCount,
10141
- " ",
10142
- itemCount === 1 ? "item" : "items"
10143
- ]
10144
- }
10145
- ) }),
10146
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10147
- ] })
10148
- ] }) }),
10149
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10150
- CustomItemForm,
10151
- {
10152
- orderId: preview.id,
10153
- currencyCode
10154
- }
10155
- ) : null)
10156
- ]
10157
- }
10158
- ) }),
10159
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10160
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10161
- /* @__PURE__ */ jsx(
10162
- Button,
10163
- {
10164
- size: "small",
10165
- type: "button",
10166
- onClick: onSubmit,
10167
- isLoading: isSubmitting,
10168
- children: "Save"
10169
- }
10170
- )
10171
- ] }) })
10172
- ] });
10173
- };
10174
- const Item = ({ item, preview, currencyCode }) => {
10175
- if (item.variant_id) {
10176
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10177
- }
10178
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10179
- };
10180
- const VariantItem = ({ item, preview, currencyCode }) => {
10181
- const [editing, setEditing] = useState(false);
10182
- const form = useForm({
10183
- defaultValues: {
10184
- quantity: item.quantity,
10185
- unit_price: item.unit_price
10186
- },
10187
- resolver: zodResolver(variantItemSchema)
10188
- });
10189
- const actionId = useMemo(() => {
10190
- var _a, _b;
10191
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10192
- }, [item]);
10193
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10194
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10195
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10196
- const onSubmit = form.handleSubmit(async (data) => {
10197
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10198
- setEditing(false);
10199
- return;
10200
- }
10201
- if (!actionId) {
10202
- await updateOriginalItem(
10203
- {
10204
- item_id: item.id,
10205
- quantity: data.quantity,
10206
- unit_price: convertNumber(data.unit_price)
10207
- },
10208
- {
10209
- onSuccess: () => {
10210
- setEditing(false);
10211
- },
10212
- onError: (e) => {
10213
- toast.error(e.message);
10214
- }
10215
- }
10216
- );
10217
- return;
10218
- }
10219
- await updateActionItem(
10220
- {
10221
- action_id: actionId,
10222
- quantity: data.quantity,
10223
- unit_price: convertNumber(data.unit_price)
10224
- },
10225
- {
10226
- onSuccess: () => {
10227
- setEditing(false);
10228
- },
10229
- onError: (e) => {
10230
- toast.error(e.message);
10231
- }
10232
- }
10233
- );
10234
- });
10235
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10236
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10237
- /* @__PURE__ */ jsx(
10238
- Thumbnail,
10239
- {
10240
- thumbnail: item.thumbnail,
10241
- alt: item.product_title ?? void 0
10242
- }
10243
- ),
10244
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10245
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10246
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10247
- /* @__PURE__ */ jsxs(
10248
- Text,
10249
- {
10250
- size: "small",
10251
- leading: "compact",
10252
- className: "text-ui-fg-subtle",
10253
- children: [
10254
- "(",
10255
- item.variant_title,
10256
- ")"
10257
- ]
10258
- }
10259
- )
10260
- ] }),
10261
- /* @__PURE__ */ jsx(
10262
- Text,
10263
- {
10264
- size: "small",
10265
- leading: "compact",
10266
- className: "text-ui-fg-subtle",
10267
- children: item.variant_sku
10268
- }
10269
- )
10270
- ] })
10271
- ] }),
10272
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10273
- Form$2.Field,
10274
- {
10275
- control: form.control,
10276
- name: "quantity",
10277
- render: ({ field }) => {
10278
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10279
- }
10280
- }
10281
- ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10282
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10283
- Form$2.Field,
10284
- {
10285
- control: form.control,
10286
- name: "unit_price",
10287
- render: ({ field: { onChange, ...field } }) => {
10288
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10289
- CurrencyInput,
10290
- {
10291
- ...field,
10292
- symbol: getNativeSymbol(currencyCode),
10293
- code: currencyCode,
10294
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10295
- }
10296
- ) }) });
10297
- }
10298
- }
10299
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10300
- /* @__PURE__ */ jsx(
10301
- IconButton,
10302
- {
10303
- type: "button",
10304
- size: "small",
10305
- onClick: editing ? onSubmit : () => {
10306
- setEditing(true);
10307
- },
10308
- disabled: isPending,
10309
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10310
- }
10311
- )
10312
- ] }) }) });
10085
+ },
10086
+ field.id
10087
+ );
10088
+ })
10089
+ ] }),
10090
+ hasUneditableRows && /* @__PURE__ */ jsx(InlineTip, { variant: "warning", label: "Some rows are disabled", children: "This object contains non-primitive metadata, such as arrays or objects, that can't be edited here. To edit the disabled rows, use the API directly." })
10091
+ ] }),
10092
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10093
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10094
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10095
+ ] }) })
10096
+ ]
10097
+ }
10098
+ ) });
10313
10099
  };
10314
- const variantItemSchema = objectType({
10315
- quantity: numberType(),
10316
- unit_price: unionType([numberType(), stringType()])
10100
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
10101
+ return /* @__PURE__ */ jsx(
10102
+ "input",
10103
+ {
10104
+ ref,
10105
+ ...props,
10106
+ autoComplete: "off",
10107
+ className: clx(
10108
+ "txt-compact-small text-ui-fg-base placeholder:text-ui-fg-muted disabled:text-ui-fg-disabled disabled:bg-ui-bg-base bg-transparent px-2 py-1.5 outline-none",
10109
+ className
10110
+ )
10111
+ }
10112
+ );
10317
10113
  });
10318
- const CustomItem = ({ item, preview, currencyCode }) => {
10319
- const [editing, setEditing] = useState(false);
10320
- const { quantity, unit_price, title } = item;
10321
- const form = useForm({
10322
- defaultValues: {
10323
- title,
10324
- quantity,
10325
- unit_price
10326
- },
10327
- resolver: zodResolver(customItemSchema)
10328
- });
10329
- useEffect(() => {
10330
- form.reset({
10331
- title,
10332
- quantity,
10333
- unit_price
10334
- });
10335
- }, [form, title, quantity, unit_price]);
10336
- const actionId = useMemo(() => {
10337
- var _a, _b;
10338
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10339
- }, [item]);
10340
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10341
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10342
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10343
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10344
- const onSubmit = form.handleSubmit(async (data) => {
10345
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10346
- setEditing(false);
10347
- return;
10114
+ GridInput.displayName = "MetadataForm.GridInput";
10115
+ const PlaceholderInner = () => {
10116
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10117
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10118
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10119
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10120
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10121
+ ] }) })
10122
+ ] });
10123
+ };
10124
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
10125
+ function getDefaultValues(metadata) {
10126
+ if (!metadata || !Object.keys(metadata).length) {
10127
+ return [
10128
+ {
10129
+ key: "",
10130
+ value: "",
10131
+ disabled: false
10132
+ }
10133
+ ];
10134
+ }
10135
+ return Object.entries(metadata).map(([key, value]) => {
10136
+ if (!EDITABLE_TYPES.includes(typeof value)) {
10137
+ return {
10138
+ key,
10139
+ value,
10140
+ disabled: true
10141
+ };
10348
10142
  }
10349
- if (!actionId) {
10350
- await updateOriginalItem(
10351
- {
10352
- item_id: item.id,
10353
- quantity: data.quantity,
10354
- unit_price: convertNumber(data.unit_price)
10355
- },
10356
- {
10357
- onSuccess: () => {
10358
- setEditing(false);
10359
- },
10360
- onError: (e) => {
10361
- toast.error(e.message);
10362
- }
10363
- }
10364
- );
10143
+ let stringValue = value;
10144
+ if (typeof value !== "string") {
10145
+ stringValue = JSON.stringify(value);
10146
+ }
10147
+ return {
10148
+ key,
10149
+ value: stringValue,
10150
+ original_key: key
10151
+ };
10152
+ });
10153
+ }
10154
+ function parseValues(values) {
10155
+ const metadata = values.metadata;
10156
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10157
+ if (isEmpty) {
10158
+ return null;
10159
+ }
10160
+ const update = {};
10161
+ metadata.forEach((field) => {
10162
+ let key = field.key;
10163
+ let value = field.value;
10164
+ const disabled = field.disabled;
10165
+ if (!key || !value) {
10365
10166
  return;
10366
10167
  }
10367
- if (data.quantity === 0) {
10368
- await removeActionItem(actionId, {
10369
- onSuccess: () => {
10370
- setEditing(false);
10371
- },
10372
- onError: (e) => {
10373
- toast.error(e.message);
10374
- }
10375
- });
10168
+ if (disabled) {
10169
+ update[key] = value;
10376
10170
  return;
10377
10171
  }
10378
- await updateActionItem(
10379
- {
10380
- action_id: actionId,
10381
- quantity: data.quantity,
10382
- unit_price: convertNumber(data.unit_price)
10383
- },
10384
- {
10385
- onSuccess: () => {
10386
- setEditing(false);
10387
- },
10388
- onError: (e) => {
10389
- toast.error(e.message);
10390
- }
10172
+ key = key.trim();
10173
+ value = value.trim();
10174
+ if (value === "true") {
10175
+ update[key] = true;
10176
+ } else if (value === "false") {
10177
+ update[key] = false;
10178
+ } else {
10179
+ const parsedNumber = parseFloat(value);
10180
+ if (!isNaN(parsedNumber)) {
10181
+ update[key] = parsedNumber;
10182
+ } else {
10183
+ update[key] = value;
10391
10184
  }
10392
- );
10185
+ }
10393
10186
  });
10394
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10395
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10396
- /* @__PURE__ */ jsx(
10397
- Thumbnail,
10398
- {
10399
- thumbnail: item.thumbnail,
10400
- alt: item.title ?? void 0
10401
- }
10402
- ),
10403
- editing ? /* @__PURE__ */ jsx(
10404
- Form$2.Field,
10405
- {
10406
- control: form.control,
10407
- name: "title",
10408
- render: ({ field }) => {
10409
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10410
- }
10411
- }
10412
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10413
- ] }),
10414
- editing ? /* @__PURE__ */ jsx(
10415
- Form$2.Field,
10416
- {
10417
- control: form.control,
10418
- name: "quantity",
10419
- render: ({ field }) => {
10420
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10421
- }
10187
+ return update;
10188
+ }
10189
+ function getHasUneditableRows(metadata) {
10190
+ if (!metadata) {
10191
+ return false;
10192
+ }
10193
+ return Object.values(metadata).some(
10194
+ (value) => !EDITABLE_TYPES.includes(typeof value)
10195
+ );
10196
+ }
10197
+ const NumberInput = forwardRef(
10198
+ ({
10199
+ value,
10200
+ onChange,
10201
+ size = "base",
10202
+ min = 0,
10203
+ max = 100,
10204
+ step = 1,
10205
+ className,
10206
+ disabled,
10207
+ ...props
10208
+ }, ref) => {
10209
+ const handleChange = (event) => {
10210
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
10211
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
10212
+ onChange(newValue);
10422
10213
  }
10423
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10424
- editing ? /* @__PURE__ */ jsx(
10425
- Form$2.Field,
10214
+ };
10215
+ const handleIncrement = () => {
10216
+ const newValue = value + step;
10217
+ if (max === void 0 || newValue <= max) {
10218
+ onChange(newValue);
10219
+ }
10220
+ };
10221
+ const handleDecrement = () => {
10222
+ const newValue = value - step;
10223
+ if (min === void 0 || newValue >= min) {
10224
+ onChange(newValue);
10225
+ }
10226
+ };
10227
+ return /* @__PURE__ */ jsxs(
10228
+ "div",
10426
10229
  {
10427
- control: form.control,
10428
- name: "unit_price",
10429
- render: ({ field: { onChange, ...field } }) => {
10430
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10431
- CurrencyInput,
10230
+ className: clx(
10231
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
10232
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
10233
+ {
10234
+ "h-7": size === "small",
10235
+ "h-8": size === "base"
10236
+ },
10237
+ className
10238
+ ),
10239
+ children: [
10240
+ /* @__PURE__ */ jsx(
10241
+ "input",
10242
+ {
10243
+ ref,
10244
+ type: "number",
10245
+ value,
10246
+ onChange: handleChange,
10247
+ min,
10248
+ max,
10249
+ step,
10250
+ className: clx(
10251
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
10252
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
10253
+ "placeholder:text-ui-fg-muted"
10254
+ ),
10255
+ ...props
10256
+ }
10257
+ ),
10258
+ /* @__PURE__ */ jsxs(
10259
+ "button",
10432
10260
  {
10433
- ...field,
10434
- symbol: getNativeSymbol(currencyCode),
10435
- code: currencyCode,
10436
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10261
+ className: clx(
10262
+ "flex items-center justify-center outline-none transition-fg",
10263
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10264
+ "focus:bg-ui-bg-field-component-hover",
10265
+ "hover:bg-ui-bg-field-component-hover",
10266
+ {
10267
+ "size-7": size === "small",
10268
+ "size-8": size === "base"
10269
+ }
10270
+ ),
10271
+ type: "button",
10272
+ onClick: handleDecrement,
10273
+ disabled: min !== void 0 && value <= min || disabled,
10274
+ children: [
10275
+ /* @__PURE__ */ jsx(Minus, {}),
10276
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
10277
+ ]
10437
10278
  }
10438
- ) }) });
10439
- }
10279
+ ),
10280
+ /* @__PURE__ */ jsxs(
10281
+ "button",
10282
+ {
10283
+ className: clx(
10284
+ "flex items-center justify-center outline-none transition-fg",
10285
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
10286
+ "focus:bg-ui-bg-field-hover",
10287
+ "hover:bg-ui-bg-field-hover",
10288
+ {
10289
+ "size-7": size === "small",
10290
+ "size-8": size === "base"
10291
+ }
10292
+ ),
10293
+ type: "button",
10294
+ onClick: handleIncrement,
10295
+ disabled: max !== void 0 && value >= max || disabled,
10296
+ children: [
10297
+ /* @__PURE__ */ jsx(Plus, {}),
10298
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
10299
+ ]
10300
+ }
10301
+ )
10302
+ ]
10440
10303
  }
10441
- ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10442
- /* @__PURE__ */ jsx(
10443
- IconButton,
10444
- {
10445
- type: "button",
10446
- size: "small",
10447
- onClick: editing ? onSubmit : () => {
10448
- setEditing(true);
10449
- },
10450
- disabled: isPending,
10451
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10304
+ );
10305
+ }
10306
+ );
10307
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
10308
+ const productVariantsQueryKeys = {
10309
+ list: (query2) => [
10310
+ PRODUCT_VARIANTS_QUERY_KEY,
10311
+ query2 ? query2 : void 0
10312
+ ]
10313
+ };
10314
+ const useProductVariants = (query2, options) => {
10315
+ const { data, ...rest } = useQuery({
10316
+ queryKey: productVariantsQueryKeys.list(query2),
10317
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
10318
+ ...options
10319
+ });
10320
+ return { ...data, ...rest };
10321
+ };
10322
+ const useCancelOrderEdit = ({ preview }) => {
10323
+ const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
10324
+ const onCancel = useCallback(async () => {
10325
+ if (!preview) {
10326
+ return true;
10327
+ }
10328
+ let res = false;
10329
+ await cancelOrderEdit(void 0, {
10330
+ onError: (e) => {
10331
+ toast.error(e.message);
10332
+ },
10333
+ onSuccess: () => {
10334
+ res = true;
10452
10335
  }
10453
- )
10454
- ] }) }) });
10336
+ });
10337
+ return res;
10338
+ }, [preview, cancelOrderEdit]);
10339
+ return { onCancel };
10455
10340
  };
10456
- const StackedModalTrigger$1 = ({
10457
- type,
10458
- setModalContent
10341
+ let IS_REQUEST_RUNNING = false;
10342
+ const useInitiateOrderEdit = ({
10343
+ preview
10459
10344
  }) => {
10460
- const { setIsOpen } = useStackedModal();
10461
- const onClick = useCallback(() => {
10462
- setModalContent(type);
10463
- setIsOpen(STACKED_MODAL_ID, true);
10464
- }, [setModalContent, setIsOpen, type]);
10465
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10466
- };
10467
- const VARIANT_PREFIX = "items";
10468
- const LIMIT = 50;
10469
- const ExistingItemsForm = ({ orderId, items }) => {
10470
- const { setIsOpen } = useStackedModal();
10471
- const [rowSelection, setRowSelection] = useState(
10472
- items.reduce((acc, item) => {
10473
- acc[item.variant_id] = true;
10474
- return acc;
10475
- }, {})
10476
- );
10345
+ const navigate = useNavigate();
10346
+ const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
10477
10347
  useEffect(() => {
10478
- setRowSelection(
10479
- items.reduce((acc, item) => {
10480
- if (item.variant_id) {
10481
- acc[item.variant_id] = true;
10348
+ async function run() {
10349
+ if (IS_REQUEST_RUNNING || !preview) {
10350
+ return;
10351
+ }
10352
+ if (preview.order_change) {
10353
+ return;
10354
+ }
10355
+ IS_REQUEST_RUNNING = true;
10356
+ await mutateAsync(void 0, {
10357
+ onError: (e) => {
10358
+ toast.error(e.message);
10359
+ navigate(`/draft-orders/${preview.id}`, { replace: true });
10360
+ return;
10482
10361
  }
10483
- return acc;
10484
- }, {})
10485
- );
10486
- }, [items]);
10487
- const { q, order, offset } = useQueryParams(
10488
- ["q", "order", "offset"],
10489
- VARIANT_PREFIX
10490
- );
10491
- const { variants, count, isPending, isError, error } = useProductVariants(
10362
+ });
10363
+ IS_REQUEST_RUNNING = false;
10364
+ }
10365
+ run();
10366
+ }, [preview, navigate, mutateAsync]);
10367
+ };
10368
+ function convertNumber(value) {
10369
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10370
+ }
10371
+ const STACKED_MODAL_ID = "items_stacked_modal";
10372
+ const Items = () => {
10373
+ const { id } = useParams();
10374
+ const {
10375
+ order: preview,
10376
+ isPending: isPreviewPending,
10377
+ isError: isPreviewError,
10378
+ error: previewError
10379
+ } = useOrderPreview(id, void 0, {
10380
+ placeholderData: keepPreviousData
10381
+ });
10382
+ useInitiateOrderEdit({ preview });
10383
+ const { draft_order, isPending, isError, error } = useDraftOrder(
10384
+ id,
10492
10385
  {
10493
- q,
10494
- order,
10495
- offset: offset ? parseInt(offset) : void 0,
10496
- limit: LIMIT
10386
+ fields: "currency_code"
10497
10387
  },
10498
10388
  {
10499
- placeholderData: keepPreviousData
10389
+ enabled: !!id
10500
10390
  }
10501
10391
  );
10502
- const columns = useColumns();
10503
- const { mutateAsync } = useDraftOrderAddItems(orderId);
10392
+ const { onCancel } = useCancelOrderEdit({ preview });
10393
+ if (isError) {
10394
+ throw error;
10395
+ }
10396
+ if (isPreviewError) {
10397
+ throw previewError;
10398
+ }
10399
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10400
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10401
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10402
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10403
+ ] }) });
10404
+ };
10405
+ const ItemsForm = ({ preview, currencyCode }) => {
10406
+ var _a;
10407
+ const [isSubmitting, setIsSubmitting] = useState(false);
10408
+ const [modalContent, setModalContent] = useState(
10409
+ null
10410
+ );
10411
+ const { handleSuccess } = useRouteModal();
10412
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10413
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10414
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10415
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10416
+ const matches = useMemo(() => {
10417
+ return matchSorter(preview.items, query2, {
10418
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
10419
+ });
10420
+ }, [preview.items, query2]);
10504
10421
  const onSubmit = async () => {
10505
- const ids = Object.keys(rowSelection).filter(
10506
- (id) => !items.find((i) => i.variant_id === id)
10507
- );
10508
- await mutateAsync(
10509
- {
10510
- items: ids.map((id) => ({
10511
- variant_id: id,
10512
- quantity: 1
10513
- }))
10422
+ setIsSubmitting(true);
10423
+ let requestSucceeded = false;
10424
+ await requestOrderEdit(void 0, {
10425
+ onError: (e) => {
10426
+ toast.error(`Failed to request order edit: ${e.message}`);
10514
10427
  },
10515
- {
10516
- onSuccess: () => {
10517
- setRowSelection({});
10518
- setIsOpen(STACKED_MODAL_ID, false);
10519
- },
10520
- onError: (e) => {
10521
- toast.error(e.message);
10522
- }
10428
+ onSuccess: () => {
10429
+ requestSucceeded = true;
10430
+ }
10431
+ });
10432
+ if (!requestSucceeded) {
10433
+ setIsSubmitting(false);
10434
+ return;
10435
+ }
10436
+ await confirmOrderEdit(void 0, {
10437
+ onError: (e) => {
10438
+ toast.error(`Failed to confirm order edit: ${e.message}`);
10439
+ },
10440
+ onSuccess: () => {
10441
+ handleSuccess();
10442
+ },
10443
+ onSettled: () => {
10444
+ setIsSubmitting(false);
10523
10445
  }
10524
- );
10446
+ });
10525
10447
  };
10526
- if (isError) {
10527
- throw error;
10528
- }
10529
- return /* @__PURE__ */ jsxs(
10530
- StackedFocusModal.Content,
10531
- {
10532
- onOpenAutoFocus: (e) => {
10533
- e.preventDefault();
10534
- const searchInput = document.querySelector(
10535
- "[data-modal-id='modal-search-input']"
10536
- );
10537
- if (searchInput) {
10538
- searchInput.focus();
10448
+ const onKeyDown = useCallback(
10449
+ (e) => {
10450
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10451
+ if (modalContent || isSubmitting) {
10452
+ return;
10539
10453
  }
10540
- },
10541
- children: [
10542
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10543
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10544
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10545
- ] }),
10546
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10547
- DataTable,
10548
- {
10549
- data: variants,
10550
- columns,
10551
- isLoading: isPending,
10552
- getRowId: (row) => row.id,
10553
- rowCount: count,
10554
- prefix: VARIANT_PREFIX,
10555
- layout: "fill",
10556
- rowSelection: {
10557
- state: rowSelection,
10558
- onRowSelectionChange: setRowSelection,
10559
- enableRowSelection: (row) => {
10560
- return !items.find((i) => i.variant_id === row.original.id);
10561
- }
10562
- },
10563
- autoFocusSearch: true
10564
- }
10565
- ) }),
10566
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10567
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10568
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10569
- ] }) })
10570
- ]
10571
- }
10454
+ onSubmit();
10455
+ }
10456
+ },
10457
+ [modalContent, isSubmitting, onSubmit]
10572
10458
  );
10573
- };
10574
- const columnHelper = createDataTableColumnHelper();
10575
- const useColumns = () => {
10576
- return useMemo(() => {
10577
- return [
10578
- columnHelper.select(),
10579
- columnHelper.accessor("product.title", {
10580
- header: "Product",
10581
- cell: ({ row }) => {
10582
- var _a, _b, _c;
10583
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10584
- /* @__PURE__ */ jsx(
10585
- Thumbnail,
10586
- {
10587
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10588
- alt: (_b = row.original.product) == null ? void 0 : _b.title
10589
- }
10590
- ),
10591
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10592
- ] });
10593
- },
10594
- enableSorting: true
10595
- }),
10596
- columnHelper.accessor("title", {
10597
- header: "Variant",
10598
- enableSorting: true
10599
- }),
10600
- columnHelper.accessor("sku", {
10601
- header: "SKU",
10602
- cell: ({ getValue }) => {
10603
- return getValue() ?? "-";
10604
- },
10605
- enableSorting: true
10606
- }),
10607
- columnHelper.accessor("updated_at", {
10608
- header: "Updated",
10609
- cell: ({ getValue }) => {
10610
- return /* @__PURE__ */ jsx(
10611
- Tooltip,
10612
- {
10613
- content: getFullDate({ date: getValue(), includeTime: true }),
10614
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10615
- }
10616
- );
10459
+ useEffect(() => {
10460
+ document.addEventListener("keydown", onKeyDown);
10461
+ return () => {
10462
+ document.removeEventListener("keydown", onKeyDown);
10463
+ };
10464
+ }, [onKeyDown]);
10465
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10466
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10467
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10468
+ StackedFocusModal,
10469
+ {
10470
+ id: STACKED_MODAL_ID,
10471
+ onOpenChangeCallback: (open) => {
10472
+ if (!open) {
10473
+ setModalContent(null);
10474
+ }
10617
10475
  },
10618
- enableSorting: true,
10619
- sortAscLabel: "Oldest first",
10620
- sortDescLabel: "Newest first"
10621
- }),
10622
- columnHelper.accessor("created_at", {
10623
- header: "Created",
10624
- cell: ({ getValue }) => {
10625
- return /* @__PURE__ */ jsx(
10626
- Tooltip,
10476
+ children: [
10477
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
10478
+ /* @__PURE__ */ jsxs("div", { children: [
10479
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10480
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order" }) })
10481
+ ] }),
10482
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10483
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10484
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10485
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10486
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10487
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10488
+ ] }),
10489
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10490
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10491
+ Input,
10492
+ {
10493
+ type: "search",
10494
+ placeholder: "Search items",
10495
+ value: searchValue,
10496
+ onChange: (e) => onSearchValueChange(e.target.value)
10497
+ }
10498
+ ) }),
10499
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10500
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10501
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10502
+ /* @__PURE__ */ jsx(
10503
+ StackedModalTrigger$1,
10504
+ {
10505
+ type: "add-items",
10506
+ setModalContent
10507
+ }
10508
+ ),
10509
+ /* @__PURE__ */ jsx(
10510
+ StackedModalTrigger$1,
10511
+ {
10512
+ type: "add-custom-item",
10513
+ setModalContent
10514
+ }
10515
+ )
10516
+ ] })
10517
+ ] })
10518
+ ] })
10519
+ ] }),
10520
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10521
+ /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
10522
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10523
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10524
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10525
+ /* @__PURE__ */ jsx("div", {})
10526
+ ] }) }),
10527
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10528
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10529
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10530
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10531
+ Item,
10532
+ {
10533
+ item,
10534
+ preview,
10535
+ currencyCode
10536
+ },
10537
+ item.id
10538
+ )) : /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10539
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10540
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10541
+ 'No items found for "',
10542
+ query2,
10543
+ '".'
10544
+ ] })
10545
+ ] }) })
10546
+ ] })
10547
+ ] }),
10548
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10549
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10550
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10551
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10552
+ Text,
10553
+ {
10554
+ size: "small",
10555
+ leading: "compact",
10556
+ className: "text-ui-fg-subtle",
10557
+ children: [
10558
+ itemCount,
10559
+ " ",
10560
+ itemCount === 1 ? "item" : "items"
10561
+ ]
10562
+ }
10563
+ ) }),
10564
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10565
+ ] })
10566
+ ] }) }),
10567
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10568
+ CustomItemForm,
10627
10569
  {
10628
- content: getFullDate({ date: getValue(), includeTime: true }),
10629
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10570
+ orderId: preview.id,
10571
+ currencyCode
10630
10572
  }
10631
- );
10632
- },
10633
- enableSorting: true,
10634
- sortAscLabel: "Oldest first",
10635
- sortDescLabel: "Newest first"
10636
- })
10637
- ];
10638
- }, []);
10573
+ ) : null)
10574
+ ]
10575
+ }
10576
+ ) }),
10577
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10578
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10579
+ /* @__PURE__ */ jsx(
10580
+ Button,
10581
+ {
10582
+ size: "small",
10583
+ type: "button",
10584
+ onClick: onSubmit,
10585
+ isLoading: isSubmitting,
10586
+ children: "Save"
10587
+ }
10588
+ )
10589
+ ] }) })
10590
+ ] });
10591
+ };
10592
+ const Item = ({ item, preview, currencyCode }) => {
10593
+ if (item.variant_id) {
10594
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10595
+ }
10596
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10639
10597
  };
10640
- const CustomItemForm = ({ orderId, currencyCode }) => {
10641
- const { setIsOpen } = useStackedModal();
10642
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10598
+ const VariantItem = ({ item, preview, currencyCode }) => {
10599
+ const [editing, setEditing] = useState(false);
10643
10600
  const form = useForm({
10644
10601
  defaultValues: {
10645
- title: "",
10646
- quantity: 1,
10647
- unit_price: ""
10602
+ quantity: item.quantity,
10603
+ unit_price: item.unit_price
10648
10604
  },
10649
- resolver: zodResolver(customItemSchema)
10605
+ resolver: zodResolver(variantItemSchema)
10650
10606
  });
10607
+ const actionId = useMemo(() => {
10608
+ var _a, _b;
10609
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10610
+ }, [item]);
10611
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10612
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10613
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10651
10614
  const onSubmit = form.handleSubmit(async (data) => {
10652
- await addItems(
10653
- {
10654
- items: [
10655
- {
10656
- title: data.title,
10657
- quantity: data.quantity,
10658
- unit_price: convertNumber(data.unit_price)
10615
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10616
+ setEditing(false);
10617
+ return;
10618
+ }
10619
+ if (!actionId) {
10620
+ await updateOriginalItem(
10621
+ {
10622
+ item_id: item.id,
10623
+ quantity: data.quantity,
10624
+ unit_price: convertNumber(data.unit_price)
10625
+ },
10626
+ {
10627
+ onSuccess: () => {
10628
+ setEditing(false);
10629
+ },
10630
+ onError: (e) => {
10631
+ toast.error(e.message);
10659
10632
  }
10660
- ]
10633
+ }
10634
+ );
10635
+ return;
10636
+ }
10637
+ await updateActionItem(
10638
+ {
10639
+ action_id: actionId,
10640
+ quantity: data.quantity,
10641
+ unit_price: convertNumber(data.unit_price)
10661
10642
  },
10662
10643
  {
10663
10644
  onSuccess: () => {
10664
- setIsOpen(STACKED_MODAL_ID, false);
10645
+ setEditing(false);
10665
10646
  },
10666
10647
  onError: (e) => {
10667
10648
  toast.error(e.message);
@@ -10669,437 +10650,524 @@ const CustomItemForm = ({ orderId, currencyCode }) => {
10669
10650
  }
10670
10651
  );
10671
10652
  });
10672
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10673
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10674
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-2 py-16", children: [
10675
- /* @__PURE__ */ jsxs("div", { children: [
10676
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10677
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a custom item to the order. This will add a new line item that is not associated with an existing product." }) })
10678
- ] }),
10679
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10680
- /* @__PURE__ */ jsx(
10681
- Form$2.Field,
10682
- {
10683
- control: form.control,
10684
- name: "title",
10685
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10686
- /* @__PURE__ */ jsxs("div", { children: [
10687
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10688
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10689
- ] }),
10690
- /* @__PURE__ */ jsxs("div", { children: [
10691
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10692
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10693
- ] })
10694
- ] }) })
10695
- }
10696
- ),
10697
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10653
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10654
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10698
10655
  /* @__PURE__ */ jsx(
10699
- Form$2.Field,
10656
+ Thumbnail,
10700
10657
  {
10701
- control: form.control,
10702
- name: "unit_price",
10703
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10704
- /* @__PURE__ */ jsxs("div", { children: [
10705
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10706
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10707
- ] }),
10708
- /* @__PURE__ */ jsxs("div", { children: [
10709
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10710
- CurrencyInput,
10711
- {
10712
- symbol: getNativeSymbol(currencyCode),
10713
- code: currencyCode,
10714
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10715
- ...field
10716
- }
10717
- ) }),
10718
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10719
- ] })
10720
- ] }) })
10658
+ thumbnail: item.thumbnail,
10659
+ alt: item.product_title ?? void 0
10721
10660
  }
10722
10661
  ),
10723
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10724
- /* @__PURE__ */ jsx(
10725
- Form$2.Field,
10726
- {
10727
- control: form.control,
10728
- name: "quantity",
10729
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10730
- /* @__PURE__ */ jsxs("div", { children: [
10731
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10732
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10733
- ] }),
10734
- /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
10735
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10736
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10737
- ] })
10738
- ] }) })
10662
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10663
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10664
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10665
+ /* @__PURE__ */ jsxs(
10666
+ Text,
10667
+ {
10668
+ size: "small",
10669
+ leading: "compact",
10670
+ className: "text-ui-fg-subtle",
10671
+ children: [
10672
+ "(",
10673
+ item.variant_title,
10674
+ ")"
10675
+ ]
10676
+ }
10677
+ )
10678
+ ] }),
10679
+ /* @__PURE__ */ jsx(
10680
+ Text,
10681
+ {
10682
+ size: "small",
10683
+ leading: "compact",
10684
+ className: "text-ui-fg-subtle",
10685
+ children: item.variant_sku
10686
+ }
10687
+ )
10688
+ ] })
10689
+ ] }),
10690
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10691
+ Form$2.Field,
10692
+ {
10693
+ control: form.control,
10694
+ name: "quantity",
10695
+ render: ({ field }) => {
10696
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10739
10697
  }
10740
- )
10741
- ] }) }) }),
10742
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10743
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10744
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10745
- ] }) })
10746
- ] }) }) });
10747
- };
10748
- const customItemSchema = objectType({
10749
- title: stringType().min(1),
10750
- quantity: numberType(),
10751
- unit_price: unionType([numberType(), stringType()])
10752
- });
10753
- const InlineTip = forwardRef(
10754
- ({ variant = "tip", label, className, children, ...props }, ref) => {
10755
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10756
- return /* @__PURE__ */ jsxs(
10757
- "div",
10698
+ }
10699
+ ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10700
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10701
+ Form$2.Field,
10758
10702
  {
10759
- ref,
10760
- className: clx(
10761
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10762
- className
10763
- ),
10764
- ...props,
10765
- children: [
10766
- /* @__PURE__ */ jsx(
10767
- "div",
10703
+ control: form.control,
10704
+ name: "unit_price",
10705
+ render: ({ field: { onChange, ...field } }) => {
10706
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10707
+ CurrencyInput,
10768
10708
  {
10769
- role: "presentation",
10770
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10771
- "bg-ui-tag-orange-icon": variant === "warning"
10772
- })
10709
+ ...field,
10710
+ symbol: getNativeSymbol(currencyCode),
10711
+ code: currencyCode,
10712
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10773
10713
  }
10774
- ),
10775
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10776
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10777
- labelValue,
10778
- ":"
10779
- ] }),
10780
- " ",
10781
- children
10782
- ] })
10783
- ]
10714
+ ) }) });
10715
+ }
10784
10716
  }
10785
- );
10786
- }
10787
- );
10788
- InlineTip.displayName = "InlineTip";
10789
- const MetadataFieldSchema = objectType({
10790
- key: stringType(),
10791
- disabled: booleanType().optional(),
10792
- value: anyType()
10793
- });
10794
- const MetadataSchema = objectType({
10795
- metadata: arrayType(MetadataFieldSchema)
10796
- });
10797
- const Metadata = () => {
10798
- const { id } = useParams();
10799
- const { order, isPending, isError, error } = useOrder(id, {
10800
- fields: "metadata"
10801
- });
10802
- if (isError) {
10803
- throw error;
10804
- }
10805
- const isReady = !isPending && !!order;
10806
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10807
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10808
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10809
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10810
- ] }),
10811
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10812
- ] });
10717
+ ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10718
+ /* @__PURE__ */ jsx(
10719
+ IconButton,
10720
+ {
10721
+ type: "button",
10722
+ size: "small",
10723
+ onClick: editing ? onSubmit : () => {
10724
+ setEditing(true);
10725
+ },
10726
+ disabled: isPending,
10727
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10728
+ }
10729
+ )
10730
+ ] }) }) });
10813
10731
  };
10814
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10815
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10816
- const MetadataForm = ({ orderId, metadata }) => {
10817
- const { handleSuccess } = useRouteModal();
10818
- const hasUneditableRows = getHasUneditableRows(metadata);
10819
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10732
+ const variantItemSchema = objectType({
10733
+ quantity: numberType(),
10734
+ unit_price: unionType([numberType(), stringType()])
10735
+ });
10736
+ const CustomItem = ({ item, preview, currencyCode }) => {
10737
+ const [editing, setEditing] = useState(false);
10738
+ const { quantity, unit_price, title } = item;
10820
10739
  const form = useForm({
10821
10740
  defaultValues: {
10822
- metadata: getDefaultValues(metadata)
10741
+ title,
10742
+ quantity,
10743
+ unit_price
10823
10744
  },
10824
- resolver: zodResolver(MetadataSchema)
10745
+ resolver: zodResolver(customItemSchema)
10825
10746
  });
10826
- const handleSubmit = form.handleSubmit(async (data) => {
10827
- const parsedData = parseValues(data);
10828
- await mutateAsync(
10747
+ useEffect(() => {
10748
+ form.reset({
10749
+ title,
10750
+ quantity,
10751
+ unit_price
10752
+ });
10753
+ }, [form, title, quantity, unit_price]);
10754
+ const actionId = useMemo(() => {
10755
+ var _a, _b;
10756
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10757
+ }, [item]);
10758
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10759
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10760
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10761
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10762
+ const onSubmit = form.handleSubmit(async (data) => {
10763
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10764
+ setEditing(false);
10765
+ return;
10766
+ }
10767
+ if (!actionId) {
10768
+ await updateOriginalItem(
10769
+ {
10770
+ item_id: item.id,
10771
+ quantity: data.quantity,
10772
+ unit_price: convertNumber(data.unit_price)
10773
+ },
10774
+ {
10775
+ onSuccess: () => {
10776
+ setEditing(false);
10777
+ },
10778
+ onError: (e) => {
10779
+ toast.error(e.message);
10780
+ }
10781
+ }
10782
+ );
10783
+ return;
10784
+ }
10785
+ if (data.quantity === 0) {
10786
+ await removeActionItem(actionId, {
10787
+ onSuccess: () => {
10788
+ setEditing(false);
10789
+ },
10790
+ onError: (e) => {
10791
+ toast.error(e.message);
10792
+ }
10793
+ });
10794
+ return;
10795
+ }
10796
+ await updateActionItem(
10829
10797
  {
10830
- metadata: parsedData
10798
+ action_id: actionId,
10799
+ quantity: data.quantity,
10800
+ unit_price: convertNumber(data.unit_price)
10831
10801
  },
10832
10802
  {
10833
10803
  onSuccess: () => {
10834
- toast.success("Metadata updated");
10835
- handleSuccess();
10804
+ setEditing(false);
10836
10805
  },
10837
- onError: (error) => {
10838
- toast.error(error.message);
10806
+ onError: (e) => {
10807
+ toast.error(e.message);
10839
10808
  }
10840
10809
  }
10841
10810
  );
10842
10811
  });
10843
- const { fields, insert, remove } = useFieldArray({
10844
- control: form.control,
10845
- name: "metadata"
10846
- });
10847
- function deleteRow(index) {
10848
- remove(index);
10849
- if (fields.length === 1) {
10850
- insert(0, {
10851
- key: "",
10852
- value: "",
10853
- disabled: false
10854
- });
10855
- }
10856
- }
10857
- function insertRow(index, position) {
10858
- insert(index + (position === "above" ? 0 : 1), {
10859
- key: "",
10860
- value: "",
10861
- disabled: false
10862
- });
10863
- }
10864
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10865
- KeyboundForm,
10866
- {
10867
- onSubmit: handleSubmit,
10868
- className: "flex flex-1 flex-col overflow-hidden",
10869
- children: [
10870
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10871
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10872
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10873
- /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_KEY_LABEL_ID, children: "Key" }) }),
10874
- /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus text-ui-fg-subtle px-2 py-1.5", children: /* @__PURE__ */ jsx("label", { id: METADATA_VALUE_LABEL_ID, children: "Value" }) })
10875
- ] }),
10876
- fields.map((field, index) => {
10877
- const isDisabled = field.disabled || false;
10878
- let placeholder = "-";
10879
- if (typeof field.value === "object") {
10880
- placeholder = "{ ... }";
10881
- }
10882
- if (Array.isArray(field.value)) {
10883
- placeholder = "[ ... ]";
10884
- }
10885
- return /* @__PURE__ */ jsx(
10886
- ConditionalTooltip,
10887
- {
10888
- showTooltip: isDisabled,
10889
- content: "This row is disabled because it contains non-primitive data.",
10890
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10891
- /* @__PURE__ */ jsxs(
10892
- "div",
10893
- {
10894
- className: clx("grid grid-cols-2 divide-x", {
10895
- "overflow-hidden rounded-b-lg": index === fields.length - 1
10896
- }),
10897
- children: [
10898
- /* @__PURE__ */ jsx(
10899
- Form$2.Field,
10900
- {
10901
- control: form.control,
10902
- name: `metadata.${index}.key`,
10903
- render: ({ field: field2 }) => {
10904
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10905
- GridInput,
10906
- {
10907
- "aria-labelledby": METADATA_KEY_LABEL_ID,
10908
- ...field2,
10909
- disabled: isDisabled,
10910
- placeholder: "Key"
10911
- }
10912
- ) }) });
10913
- }
10914
- }
10915
- ),
10916
- /* @__PURE__ */ jsx(
10917
- Form$2.Field,
10918
- {
10919
- control: form.control,
10920
- name: `metadata.${index}.value`,
10921
- render: ({ field: { value, ...field2 } }) => {
10922
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10923
- GridInput,
10924
- {
10925
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10926
- ...field2,
10927
- value: isDisabled ? placeholder : value,
10928
- disabled: isDisabled,
10929
- placeholder: "Value"
10930
- }
10931
- ) }) });
10932
- }
10933
- }
10934
- )
10935
- ]
10936
- }
10937
- ),
10938
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10939
- /* @__PURE__ */ jsx(
10940
- DropdownMenu.Trigger,
10941
- {
10942
- className: clx(
10943
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10944
- {
10945
- hidden: isDisabled
10946
- }
10947
- ),
10948
- disabled: isDisabled,
10949
- asChild: true,
10950
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10951
- }
10952
- ),
10953
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10954
- /* @__PURE__ */ jsxs(
10955
- DropdownMenu.Item,
10956
- {
10957
- className: "gap-x-2",
10958
- onClick: () => insertRow(index, "above"),
10959
- children: [
10960
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10961
- "Insert row above"
10962
- ]
10963
- }
10964
- ),
10965
- /* @__PURE__ */ jsxs(
10966
- DropdownMenu.Item,
10967
- {
10968
- className: "gap-x-2",
10969
- onClick: () => insertRow(index, "below"),
10970
- children: [
10971
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10972
- "Insert row below"
10973
- ]
10974
- }
10975
- ),
10976
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10977
- /* @__PURE__ */ jsxs(
10978
- DropdownMenu.Item,
10979
- {
10980
- className: "gap-x-2",
10981
- onClick: () => deleteRow(index),
10982
- children: [
10983
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10984
- "Delete row"
10985
- ]
10986
- }
10987
- )
10988
- ] })
10989
- ] })
10990
- ] })
10991
- },
10992
- field.id
10993
- );
10994
- })
10995
- ] }),
10996
- hasUneditableRows && /* @__PURE__ */ jsx(InlineTip, { variant: "warning", label: "Some rows are disabled", children: "This object contains non-primitive metadata, such as arrays or objects, that can't be edited here. To edit the disabled rows, use the API directly." })
10997
- ] }),
10998
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10999
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11000
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11001
- ] }) })
11002
- ]
11003
- }
11004
- ) });
10812
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10813
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10814
+ /* @__PURE__ */ jsx(
10815
+ Thumbnail,
10816
+ {
10817
+ thumbnail: item.thumbnail,
10818
+ alt: item.title ?? void 0
10819
+ }
10820
+ ),
10821
+ editing ? /* @__PURE__ */ jsx(
10822
+ Form$2.Field,
10823
+ {
10824
+ control: form.control,
10825
+ name: "title",
10826
+ render: ({ field }) => {
10827
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10828
+ }
10829
+ }
10830
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10831
+ ] }),
10832
+ editing ? /* @__PURE__ */ jsx(
10833
+ Form$2.Field,
10834
+ {
10835
+ control: form.control,
10836
+ name: "quantity",
10837
+ render: ({ field }) => {
10838
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10839
+ }
10840
+ }
10841
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10842
+ editing ? /* @__PURE__ */ jsx(
10843
+ Form$2.Field,
10844
+ {
10845
+ control: form.control,
10846
+ name: "unit_price",
10847
+ render: ({ field: { onChange, ...field } }) => {
10848
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10849
+ CurrencyInput,
10850
+ {
10851
+ ...field,
10852
+ symbol: getNativeSymbol(currencyCode),
10853
+ code: currencyCode,
10854
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10855
+ }
10856
+ ) }) });
10857
+ }
10858
+ }
10859
+ ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10860
+ /* @__PURE__ */ jsx(
10861
+ IconButton,
10862
+ {
10863
+ type: "button",
10864
+ size: "small",
10865
+ onClick: editing ? onSubmit : () => {
10866
+ setEditing(true);
10867
+ },
10868
+ disabled: isPending,
10869
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10870
+ }
10871
+ )
10872
+ ] }) }) });
11005
10873
  };
11006
- const GridInput = forwardRef(({ className, ...props }, ref) => {
11007
- return /* @__PURE__ */ jsx(
11008
- "input",
10874
+ const StackedModalTrigger$1 = ({
10875
+ type,
10876
+ setModalContent
10877
+ }) => {
10878
+ const { setIsOpen } = useStackedModal();
10879
+ const onClick = useCallback(() => {
10880
+ setModalContent(type);
10881
+ setIsOpen(STACKED_MODAL_ID, true);
10882
+ }, [setModalContent, setIsOpen, type]);
10883
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10884
+ };
10885
+ const VARIANT_PREFIX = "items";
10886
+ const LIMIT = 50;
10887
+ const ExistingItemsForm = ({ orderId, items }) => {
10888
+ const { setIsOpen } = useStackedModal();
10889
+ const [rowSelection, setRowSelection] = useState(
10890
+ items.reduce((acc, item) => {
10891
+ acc[item.variant_id] = true;
10892
+ return acc;
10893
+ }, {})
10894
+ );
10895
+ useEffect(() => {
10896
+ setRowSelection(
10897
+ items.reduce((acc, item) => {
10898
+ if (item.variant_id) {
10899
+ acc[item.variant_id] = true;
10900
+ }
10901
+ return acc;
10902
+ }, {})
10903
+ );
10904
+ }, [items]);
10905
+ const { q, order, offset } = useQueryParams(
10906
+ ["q", "order", "offset"],
10907
+ VARIANT_PREFIX
10908
+ );
10909
+ const { variants, count, isPending, isError, error } = useProductVariants(
11009
10910
  {
11010
- ref,
11011
- ...props,
11012
- autoComplete: "off",
11013
- className: clx(
11014
- "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",
11015
- className
11016
- )
10911
+ q,
10912
+ order,
10913
+ offset: offset ? parseInt(offset) : void 0,
10914
+ limit: LIMIT
10915
+ },
10916
+ {
10917
+ placeholderData: keepPreviousData
11017
10918
  }
11018
10919
  );
11019
- });
11020
- GridInput.displayName = "MetadataForm.GridInput";
11021
- const PlaceholderInner = () => {
11022
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11023
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11024
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11025
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11026
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11027
- ] }) })
11028
- ] });
11029
- };
11030
- const EDITABLE_TYPES = ["string", "number", "boolean"];
11031
- function getDefaultValues(metadata) {
11032
- if (!metadata || !Object.keys(metadata).length) {
11033
- return [
10920
+ const columns = useColumns();
10921
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10922
+ const onSubmit = async () => {
10923
+ const ids = Object.keys(rowSelection).filter(
10924
+ (id) => !items.find((i) => i.variant_id === id)
10925
+ );
10926
+ await mutateAsync(
11034
10927
  {
11035
- key: "",
11036
- value: "",
11037
- disabled: false
10928
+ items: ids.map((id) => ({
10929
+ variant_id: id,
10930
+ quantity: 1
10931
+ }))
10932
+ },
10933
+ {
10934
+ onSuccess: () => {
10935
+ setRowSelection({});
10936
+ setIsOpen(STACKED_MODAL_ID, false);
10937
+ },
10938
+ onError: (e) => {
10939
+ toast.error(e.message);
10940
+ }
11038
10941
  }
11039
- ];
10942
+ );
10943
+ };
10944
+ if (isError) {
10945
+ throw error;
11040
10946
  }
11041
- return Object.entries(metadata).map(([key, value]) => {
11042
- if (!EDITABLE_TYPES.includes(typeof value)) {
11043
- return {
11044
- key,
11045
- value,
11046
- disabled: true
11047
- };
11048
- }
11049
- let stringValue = value;
11050
- if (typeof value !== "string") {
11051
- stringValue = JSON.stringify(value);
10947
+ return /* @__PURE__ */ jsxs(
10948
+ StackedFocusModal.Content,
10949
+ {
10950
+ onOpenAutoFocus: (e) => {
10951
+ e.preventDefault();
10952
+ const searchInput = document.querySelector(
10953
+ "[data-modal-id='modal-search-input']"
10954
+ );
10955
+ if (searchInput) {
10956
+ searchInput.focus();
10957
+ }
10958
+ },
10959
+ children: [
10960
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10961
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10962
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10963
+ ] }),
10964
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10965
+ DataTable,
10966
+ {
10967
+ data: variants,
10968
+ columns,
10969
+ isLoading: isPending,
10970
+ getRowId: (row) => row.id,
10971
+ rowCount: count,
10972
+ prefix: VARIANT_PREFIX,
10973
+ layout: "fill",
10974
+ rowSelection: {
10975
+ state: rowSelection,
10976
+ onRowSelectionChange: setRowSelection,
10977
+ enableRowSelection: (row) => {
10978
+ return !items.find((i) => i.variant_id === row.original.id);
10979
+ }
10980
+ },
10981
+ autoFocusSearch: true
10982
+ }
10983
+ ) }),
10984
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10985
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10986
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10987
+ ] }) })
10988
+ ]
11052
10989
  }
11053
- return {
11054
- key,
11055
- value: stringValue,
11056
- original_key: key
11057
- };
10990
+ );
10991
+ };
10992
+ const columnHelper = createDataTableColumnHelper();
10993
+ const useColumns = () => {
10994
+ return useMemo(() => {
10995
+ return [
10996
+ columnHelper.select(),
10997
+ columnHelper.accessor("product.title", {
10998
+ header: "Product",
10999
+ cell: ({ row }) => {
11000
+ var _a, _b, _c;
11001
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
11002
+ /* @__PURE__ */ jsx(
11003
+ Thumbnail,
11004
+ {
11005
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
11006
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
11007
+ }
11008
+ ),
11009
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
11010
+ ] });
11011
+ },
11012
+ enableSorting: true
11013
+ }),
11014
+ columnHelper.accessor("title", {
11015
+ header: "Variant",
11016
+ enableSorting: true
11017
+ }),
11018
+ columnHelper.accessor("sku", {
11019
+ header: "SKU",
11020
+ cell: ({ getValue }) => {
11021
+ return getValue() ?? "-";
11022
+ },
11023
+ enableSorting: true
11024
+ }),
11025
+ columnHelper.accessor("updated_at", {
11026
+ header: "Updated",
11027
+ cell: ({ getValue }) => {
11028
+ return /* @__PURE__ */ jsx(
11029
+ Tooltip,
11030
+ {
11031
+ content: getFullDate({ date: getValue(), includeTime: true }),
11032
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
11033
+ }
11034
+ );
11035
+ },
11036
+ enableSorting: true,
11037
+ sortAscLabel: "Oldest first",
11038
+ sortDescLabel: "Newest first"
11039
+ }),
11040
+ columnHelper.accessor("created_at", {
11041
+ header: "Created",
11042
+ cell: ({ getValue }) => {
11043
+ return /* @__PURE__ */ jsx(
11044
+ Tooltip,
11045
+ {
11046
+ content: getFullDate({ date: getValue(), includeTime: true }),
11047
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
11048
+ }
11049
+ );
11050
+ },
11051
+ enableSorting: true,
11052
+ sortAscLabel: "Oldest first",
11053
+ sortDescLabel: "Newest first"
11054
+ })
11055
+ ];
11056
+ }, []);
11057
+ };
11058
+ const CustomItemForm = ({ orderId, currencyCode }) => {
11059
+ const { setIsOpen } = useStackedModal();
11060
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
11061
+ const form = useForm({
11062
+ defaultValues: {
11063
+ title: "",
11064
+ quantity: 1,
11065
+ unit_price: ""
11066
+ },
11067
+ resolver: zodResolver(customItemSchema)
11058
11068
  });
11059
- }
11060
- function parseValues(values) {
11061
- const metadata = values.metadata;
11062
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11063
- if (isEmpty) {
11064
- return null;
11065
- }
11066
- const update = {};
11067
- metadata.forEach((field) => {
11068
- let key = field.key;
11069
- let value = field.value;
11070
- const disabled = field.disabled;
11071
- if (!key || !value) {
11072
- return;
11073
- }
11074
- if (disabled) {
11075
- update[key] = value;
11076
- return;
11077
- }
11078
- key = key.trim();
11079
- value = value.trim();
11080
- if (value === "true") {
11081
- update[key] = true;
11082
- } else if (value === "false") {
11083
- update[key] = false;
11084
- } else {
11085
- const parsedNumber = parseFloat(value);
11086
- if (!isNaN(parsedNumber)) {
11087
- update[key] = parsedNumber;
11088
- } else {
11089
- update[key] = value;
11069
+ const onSubmit = form.handleSubmit(async (data) => {
11070
+ await addItems(
11071
+ {
11072
+ items: [
11073
+ {
11074
+ title: data.title,
11075
+ quantity: data.quantity,
11076
+ unit_price: convertNumber(data.unit_price)
11077
+ }
11078
+ ]
11079
+ },
11080
+ {
11081
+ onSuccess: () => {
11082
+ setIsOpen(STACKED_MODAL_ID, false);
11083
+ },
11084
+ onError: (e) => {
11085
+ toast.error(e.message);
11086
+ }
11090
11087
  }
11091
- }
11088
+ );
11092
11089
  });
11093
- return update;
11094
- }
11095
- function getHasUneditableRows(metadata) {
11096
- if (!metadata) {
11097
- return false;
11098
- }
11099
- return Object.values(metadata).some(
11100
- (value) => !EDITABLE_TYPES.includes(typeof value)
11101
- );
11102
- }
11090
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
11091
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
11092
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-2 py-16", children: [
11093
+ /* @__PURE__ */ jsxs("div", { children: [
11094
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
11095
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a custom item to the order. This will add a new line item that is not associated with an existing product." }) })
11096
+ ] }),
11097
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11098
+ /* @__PURE__ */ jsx(
11099
+ Form$2.Field,
11100
+ {
11101
+ control: form.control,
11102
+ name: "title",
11103
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11104
+ /* @__PURE__ */ jsxs("div", { children: [
11105
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
11106
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
11107
+ ] }),
11108
+ /* @__PURE__ */ jsxs("div", { children: [
11109
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11110
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11111
+ ] })
11112
+ ] }) })
11113
+ }
11114
+ ),
11115
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11116
+ /* @__PURE__ */ jsx(
11117
+ Form$2.Field,
11118
+ {
11119
+ control: form.control,
11120
+ name: "unit_price",
11121
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11122
+ /* @__PURE__ */ jsxs("div", { children: [
11123
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
11124
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
11125
+ ] }),
11126
+ /* @__PURE__ */ jsxs("div", { children: [
11127
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11128
+ CurrencyInput,
11129
+ {
11130
+ symbol: getNativeSymbol(currencyCode),
11131
+ code: currencyCode,
11132
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
11133
+ ...field
11134
+ }
11135
+ ) }),
11136
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11137
+ ] })
11138
+ ] }) })
11139
+ }
11140
+ ),
11141
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11142
+ /* @__PURE__ */ jsx(
11143
+ Form$2.Field,
11144
+ {
11145
+ control: form.control,
11146
+ name: "quantity",
11147
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
11148
+ /* @__PURE__ */ jsxs("div", { children: [
11149
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
11150
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
11151
+ ] }),
11152
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
11153
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
11154
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11155
+ ] })
11156
+ ] }) })
11157
+ }
11158
+ )
11159
+ ] }) }) }),
11160
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11161
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11162
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
11163
+ ] }) })
11164
+ ] }) }) });
11165
+ };
11166
+ const customItemSchema = objectType({
11167
+ title: stringType().min(1),
11168
+ quantity: numberType(),
11169
+ unit_price: unionType([numberType(), stringType()])
11170
+ });
11103
11171
  const PROMOTION_QUERY_KEY = "promotions";
11104
11172
  const promotionsQueryKeys = {
11105
11173
  list: (query2) => [
@@ -11405,7 +11473,7 @@ const SalesChannelForm = ({ order }) => {
11405
11473
  defaultValues: {
11406
11474
  sales_channel_id: order.sales_channel_id || ""
11407
11475
  },
11408
- resolver: zodResolver(schema$3)
11476
+ resolver: zodResolver(schema$2)
11409
11477
  });
11410
11478
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11411
11479
  const { handleSuccess } = useRouteModal();
@@ -11480,7 +11548,7 @@ const SalesChannelField = ({ control, order }) => {
11480
11548
  }
11481
11549
  );
11482
11550
  };
11483
- const schema$3 = objectType({
11551
+ const schema$2 = objectType({
11484
11552
  sales_channel_id: stringType().min(1)
11485
11553
  });
11486
11554
  const STACKED_FOCUS_MODAL_ID = "shipping-form";
@@ -12322,7 +12390,7 @@ const ShippingAddressForm = ({ order }) => {
12322
12390
  postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12323
12391
  phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12324
12392
  },
12325
- resolver: zodResolver(schema$2)
12393
+ resolver: zodResolver(schema$1)
12326
12394
  });
12327
12395
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12328
12396
  const { handleSuccess } = useRouteModal();
@@ -12492,7 +12560,7 @@ const ShippingAddressForm = ({ order }) => {
12492
12560
  }
12493
12561
  ) });
12494
12562
  };
12495
- const schema$2 = addressSchema;
12563
+ const schema$1 = addressSchema;
12496
12564
  const TransferOwnership = () => {
12497
12565
  const { id } = useParams();
12498
12566
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -12516,7 +12584,7 @@ const TransferOwnershipForm = ({ order }) => {
12516
12584
  defaultValues: {
12517
12585
  customer_id: order.customer_id || ""
12518
12586
  },
12519
- resolver: zodResolver(schema$1)
12587
+ resolver: zodResolver(schema)
12520
12588
  });
12521
12589
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12522
12590
  const { handleSuccess } = useRouteModal();
@@ -12966,76 +13034,8 @@ const Illustration = () => {
12966
13034
  }
12967
13035
  );
12968
13036
  };
12969
- const schema$1 = objectType({
12970
- customer_id: stringType().min(1)
12971
- });
12972
- const Email = () => {
12973
- const { id } = useParams();
12974
- const { order, isPending, isError, error } = useOrder(id, {
12975
- fields: "+email"
12976
- });
12977
- if (isError) {
12978
- throw error;
12979
- }
12980
- const isReady = !isPending && !!order;
12981
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12982
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12983
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
12984
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
12985
- ] }),
12986
- isReady && /* @__PURE__ */ jsx(EmailForm, { order })
12987
- ] });
12988
- };
12989
- const EmailForm = ({ order }) => {
12990
- const form = useForm({
12991
- defaultValues: {
12992
- email: order.email ?? ""
12993
- },
12994
- resolver: zodResolver(schema)
12995
- });
12996
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12997
- const { handleSuccess } = useRouteModal();
12998
- const onSubmit = form.handleSubmit(async (data) => {
12999
- await mutateAsync(
13000
- { email: data.email },
13001
- {
13002
- onSuccess: () => {
13003
- handleSuccess();
13004
- },
13005
- onError: (error) => {
13006
- toast.error(error.message);
13007
- }
13008
- }
13009
- );
13010
- });
13011
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
13012
- KeyboundForm,
13013
- {
13014
- className: "flex flex-1 flex-col overflow-hidden",
13015
- onSubmit,
13016
- children: [
13017
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
13018
- Form$2.Field,
13019
- {
13020
- control: form.control,
13021
- name: "email",
13022
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13023
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
13024
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13025
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13026
- ] })
13027
- }
13028
- ) }),
13029
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13030
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
13031
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
13032
- ] }) })
13033
- ]
13034
- }
13035
- ) });
13036
- };
13037
13037
  const schema = objectType({
13038
- email: stringType().email()
13038
+ customer_id: stringType().min(1)
13039
13039
  });
13040
13040
  const widgetModule = { widgets: [] };
13041
13041
  const routeModule = {
@@ -13066,13 +13066,17 @@ const routeModule = {
13066
13066
  path: "/draft-orders/:id/custom-items"
13067
13067
  },
13068
13068
  {
13069
- Component: Items,
13070
- path: "/draft-orders/:id/items"
13069
+ Component: Email,
13070
+ path: "/draft-orders/:id/email"
13071
13071
  },
13072
13072
  {
13073
13073
  Component: Metadata,
13074
13074
  path: "/draft-orders/:id/metadata"
13075
13075
  },
13076
+ {
13077
+ Component: Items,
13078
+ path: "/draft-orders/:id/items"
13079
+ },
13076
13080
  {
13077
13081
  Component: Promotions,
13078
13082
  path: "/draft-orders/:id/promotions"
@@ -13092,10 +13096,6 @@ const routeModule = {
13092
13096
  {
13093
13097
  Component: TransferOwnership,
13094
13098
  path: "/draft-orders/:id/transfer-ownership"
13095
- },
13096
- {
13097
- Component: Email,
13098
- path: "/draft-orders/:id/email"
13099
13099
  }
13100
13100
  ]
13101
13101
  }