@medusajs/draft-order 2.11.1-preview-20251024090150 → 2.11.1-preview-20251024150200

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.
@@ -9586,683 +9586,573 @@ const CustomItemsForm = () => {
9586
9586
  const schema$5 = objectType({
9587
9587
  email: stringType().email()
9588
9588
  });
9589
- const Email = () => {
9590
- const { id } = useParams();
9591
- const { order, isPending, isError, error } = useOrder(id, {
9592
- fields: "+email"
9593
- });
9594
- if (isError) {
9595
- throw error;
9596
- }
9597
- const isReady = !isPending && !!order;
9598
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9599
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9600
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
9601
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
9602
- ] }),
9603
- isReady && /* @__PURE__ */ jsx(EmailForm, { order })
9604
- ] });
9605
- };
9606
- const EmailForm = ({ order }) => {
9607
- const form = useForm({
9608
- defaultValues: {
9609
- email: order.email ?? ""
9610
- },
9611
- resolver: zodResolver(schema$4)
9612
- });
9613
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9614
- const { handleSuccess } = useRouteModal();
9615
- const onSubmit = form.handleSubmit(async (data) => {
9616
- await mutateAsync(
9617
- { email: data.email },
9589
+ const NumberInput = forwardRef(
9590
+ ({
9591
+ value,
9592
+ onChange,
9593
+ size = "base",
9594
+ min = 0,
9595
+ max = 100,
9596
+ step = 1,
9597
+ className,
9598
+ disabled,
9599
+ ...props
9600
+ }, ref) => {
9601
+ const handleChange = (event) => {
9602
+ const newValue = event.target.value === "" ? min : Number(event.target.value);
9603
+ if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9604
+ onChange(newValue);
9605
+ }
9606
+ };
9607
+ const handleIncrement = () => {
9608
+ const newValue = value + step;
9609
+ if (max === void 0 || newValue <= max) {
9610
+ onChange(newValue);
9611
+ }
9612
+ };
9613
+ const handleDecrement = () => {
9614
+ const newValue = value - step;
9615
+ if (min === void 0 || newValue >= min) {
9616
+ onChange(newValue);
9617
+ }
9618
+ };
9619
+ return /* @__PURE__ */ jsxs(
9620
+ "div",
9618
9621
  {
9619
- onSuccess: () => {
9620
- handleSuccess();
9621
- },
9622
- onError: (error) => {
9623
- toast.error(error.message);
9624
- }
9622
+ className: clx(
9623
+ "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9624
+ "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9625
+ {
9626
+ "h-7": size === "small",
9627
+ "h-8": size === "base"
9628
+ },
9629
+ className
9630
+ ),
9631
+ children: [
9632
+ /* @__PURE__ */ jsx(
9633
+ "input",
9634
+ {
9635
+ ref,
9636
+ type: "number",
9637
+ value,
9638
+ onChange: handleChange,
9639
+ min,
9640
+ max,
9641
+ step,
9642
+ className: clx(
9643
+ "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9644
+ "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9645
+ "placeholder:text-ui-fg-muted"
9646
+ ),
9647
+ ...props
9648
+ }
9649
+ ),
9650
+ /* @__PURE__ */ jsxs(
9651
+ "button",
9652
+ {
9653
+ className: clx(
9654
+ "flex items-center justify-center outline-none transition-fg",
9655
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9656
+ "focus:bg-ui-bg-field-component-hover",
9657
+ "hover:bg-ui-bg-field-component-hover",
9658
+ {
9659
+ "size-7": size === "small",
9660
+ "size-8": size === "base"
9661
+ }
9662
+ ),
9663
+ type: "button",
9664
+ onClick: handleDecrement,
9665
+ disabled: min !== void 0 && value <= min || disabled,
9666
+ children: [
9667
+ /* @__PURE__ */ jsx(Minus, {}),
9668
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9669
+ ]
9670
+ }
9671
+ ),
9672
+ /* @__PURE__ */ jsxs(
9673
+ "button",
9674
+ {
9675
+ className: clx(
9676
+ "flex items-center justify-center outline-none transition-fg",
9677
+ "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9678
+ "focus:bg-ui-bg-field-hover",
9679
+ "hover:bg-ui-bg-field-hover",
9680
+ {
9681
+ "size-7": size === "small",
9682
+ "size-8": size === "base"
9683
+ }
9684
+ ),
9685
+ type: "button",
9686
+ onClick: handleIncrement,
9687
+ disabled: max !== void 0 && value >= max || disabled,
9688
+ children: [
9689
+ /* @__PURE__ */ jsx(Plus, {}),
9690
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9691
+ ]
9692
+ }
9693
+ )
9694
+ ]
9625
9695
  }
9626
9696
  );
9697
+ }
9698
+ );
9699
+ const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9700
+ const productVariantsQueryKeys = {
9701
+ list: (query2) => [
9702
+ PRODUCT_VARIANTS_QUERY_KEY,
9703
+ query2 ? query2 : void 0
9704
+ ]
9705
+ };
9706
+ const useProductVariants = (query2, options) => {
9707
+ const { data, ...rest } = useQuery({
9708
+ queryKey: productVariantsQueryKeys.list(query2),
9709
+ queryFn: async () => await sdk.admin.productVariant.list(query2),
9710
+ ...options
9627
9711
  });
9628
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9629
- KeyboundForm,
9630
- {
9631
- className: "flex flex-1 flex-col overflow-hidden",
9632
- onSubmit,
9633
- children: [
9634
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
9635
- Form$2.Field,
9636
- {
9637
- control: form.control,
9638
- name: "email",
9639
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9640
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
9641
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9642
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9643
- ] })
9644
- }
9645
- ) }),
9646
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9647
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9648
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9649
- ] }) })
9650
- ]
9712
+ return { ...data, ...rest };
9713
+ };
9714
+ const useCancelOrderEdit = ({ preview }) => {
9715
+ const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
9716
+ const onCancel = useCallback(async () => {
9717
+ if (!preview) {
9718
+ return true;
9651
9719
  }
9652
- ) });
9720
+ let res = false;
9721
+ await cancelOrderEdit(void 0, {
9722
+ onError: (e) => {
9723
+ toast.error(e.message);
9724
+ },
9725
+ onSuccess: () => {
9726
+ res = true;
9727
+ }
9728
+ });
9729
+ return res;
9730
+ }, [preview, cancelOrderEdit]);
9731
+ return { onCancel };
9653
9732
  };
9654
- const schema$4 = objectType({
9655
- email: stringType().email()
9656
- });
9657
- const BillingAddress = () => {
9733
+ let IS_REQUEST_RUNNING = false;
9734
+ const useInitiateOrderEdit = ({
9735
+ preview
9736
+ }) => {
9737
+ const navigate = useNavigate();
9738
+ const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
9739
+ useEffect(() => {
9740
+ async function run() {
9741
+ if (IS_REQUEST_RUNNING || !preview) {
9742
+ return;
9743
+ }
9744
+ if (preview.order_change) {
9745
+ return;
9746
+ }
9747
+ IS_REQUEST_RUNNING = true;
9748
+ await mutateAsync(void 0, {
9749
+ onError: (e) => {
9750
+ toast.error(e.message);
9751
+ navigate(`/draft-orders/${preview.id}`, { replace: true });
9752
+ return;
9753
+ }
9754
+ });
9755
+ IS_REQUEST_RUNNING = false;
9756
+ }
9757
+ run();
9758
+ }, [preview, navigate, mutateAsync]);
9759
+ };
9760
+ function convertNumber(value) {
9761
+ return typeof value === "string" ? Number(value.replace(",", ".")) : value;
9762
+ }
9763
+ const STACKED_MODAL_ID = "items_stacked_modal";
9764
+ const Items = () => {
9658
9765
  const { id } = useParams();
9659
- const { order, isPending, isError, error } = useOrder(id, {
9660
- fields: "+billing_address"
9766
+ const {
9767
+ order: preview,
9768
+ isPending: isPreviewPending,
9769
+ isError: isPreviewError,
9770
+ error: previewError
9771
+ } = useOrderPreview(id, void 0, {
9772
+ placeholderData: keepPreviousData
9661
9773
  });
9774
+ useInitiateOrderEdit({ preview });
9775
+ const { draft_order, isPending, isError, error } = useDraftOrder(
9776
+ id,
9777
+ {
9778
+ fields: "currency_code"
9779
+ },
9780
+ {
9781
+ enabled: !!id
9782
+ }
9783
+ );
9784
+ const { onCancel } = useCancelOrderEdit({ preview });
9662
9785
  if (isError) {
9663
9786
  throw error;
9664
9787
  }
9665
- const isReady = !isPending && !!order;
9666
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9667
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
9668
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Billing Address" }) }),
9669
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the billing address for the draft order" }) })
9670
- ] }),
9671
- isReady && /* @__PURE__ */ jsx(BillingAddressForm, { order })
9788
+ if (isPreviewError) {
9789
+ throw previewError;
9790
+ }
9791
+ const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
9792
+ return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
9793
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
9794
+ /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
9795
+ ] }) });
9796
+ };
9797
+ const ItemsForm = ({ preview, currencyCode }) => {
9798
+ var _a;
9799
+ const [isSubmitting, setIsSubmitting] = useState(false);
9800
+ const [modalContent, setModalContent] = useState(
9801
+ null
9802
+ );
9803
+ const { handleSuccess } = useRouteModal();
9804
+ const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
9805
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
9806
+ const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
9807
+ const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
9808
+ const matches = useMemo(() => {
9809
+ return matchSorter(preview.items, query2, {
9810
+ keys: ["product_title", "variant_title", "variant_sku", "title"]
9811
+ });
9812
+ }, [preview.items, query2]);
9813
+ const onSubmit = async () => {
9814
+ setIsSubmitting(true);
9815
+ let requestSucceeded = false;
9816
+ await requestOrderEdit(void 0, {
9817
+ onError: (e) => {
9818
+ toast.error(`Failed to request order edit: ${e.message}`);
9819
+ },
9820
+ onSuccess: () => {
9821
+ requestSucceeded = true;
9822
+ }
9823
+ });
9824
+ if (!requestSucceeded) {
9825
+ setIsSubmitting(false);
9826
+ return;
9827
+ }
9828
+ await confirmOrderEdit(void 0, {
9829
+ onError: (e) => {
9830
+ toast.error(`Failed to confirm order edit: ${e.message}`);
9831
+ },
9832
+ onSuccess: () => {
9833
+ handleSuccess();
9834
+ },
9835
+ onSettled: () => {
9836
+ setIsSubmitting(false);
9837
+ }
9838
+ });
9839
+ };
9840
+ const onKeyDown = useCallback(
9841
+ (e) => {
9842
+ if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
9843
+ if (modalContent || isSubmitting) {
9844
+ return;
9845
+ }
9846
+ onSubmit();
9847
+ }
9848
+ },
9849
+ [modalContent, isSubmitting, onSubmit]
9850
+ );
9851
+ useEffect(() => {
9852
+ document.addEventListener("keydown", onKeyDown);
9853
+ return () => {
9854
+ document.removeEventListener("keydown", onKeyDown);
9855
+ };
9856
+ }, [onKeyDown]);
9857
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
9858
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
9859
+ /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
9860
+ StackedFocusModal,
9861
+ {
9862
+ id: STACKED_MODAL_ID,
9863
+ onOpenChangeCallback: (open) => {
9864
+ if (!open) {
9865
+ setModalContent(null);
9866
+ }
9867
+ },
9868
+ children: [
9869
+ /* @__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: [
9870
+ /* @__PURE__ */ jsxs("div", { children: [
9871
+ /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
9872
+ /* @__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" }) })
9873
+ ] }),
9874
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
9875
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
9876
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
9877
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
9878
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
9879
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
9880
+ ] }),
9881
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9882
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
9883
+ Input,
9884
+ {
9885
+ type: "search",
9886
+ placeholder: "Search items",
9887
+ value: searchValue,
9888
+ onChange: (e) => onSearchValueChange(e.target.value)
9889
+ }
9890
+ ) }),
9891
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
9892
+ /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
9893
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
9894
+ /* @__PURE__ */ jsx(
9895
+ StackedModalTrigger$1,
9896
+ {
9897
+ type: "add-items",
9898
+ setModalContent
9899
+ }
9900
+ ),
9901
+ /* @__PURE__ */ jsx(
9902
+ StackedModalTrigger$1,
9903
+ {
9904
+ type: "add-custom-item",
9905
+ setModalContent
9906
+ }
9907
+ )
9908
+ ] })
9909
+ ] })
9910
+ ] })
9911
+ ] }),
9912
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
9913
+ /* @__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: [
9914
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
9915
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
9916
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
9917
+ /* @__PURE__ */ jsx("div", {})
9918
+ ] }) }),
9919
+ /* @__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: [
9920
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
9921
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
9922
+ ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
9923
+ Item,
9924
+ {
9925
+ item,
9926
+ preview,
9927
+ currencyCode
9928
+ },
9929
+ item.id
9930
+ )) : /* @__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: [
9931
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
9932
+ /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
9933
+ 'No items found for "',
9934
+ query2,
9935
+ '".'
9936
+ ] })
9937
+ ] }) })
9938
+ ] })
9939
+ ] }),
9940
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
9941
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
9942
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
9943
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
9944
+ Text,
9945
+ {
9946
+ size: "small",
9947
+ leading: "compact",
9948
+ className: "text-ui-fg-subtle",
9949
+ children: [
9950
+ itemCount,
9951
+ " ",
9952
+ itemCount === 1 ? "item" : "items"
9953
+ ]
9954
+ }
9955
+ ) }),
9956
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
9957
+ ] })
9958
+ ] }) }),
9959
+ modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
9960
+ CustomItemForm,
9961
+ {
9962
+ orderId: preview.id,
9963
+ currencyCode
9964
+ }
9965
+ ) : null)
9966
+ ]
9967
+ }
9968
+ ) }),
9969
+ /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
9970
+ /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
9971
+ /* @__PURE__ */ jsx(
9972
+ Button,
9973
+ {
9974
+ size: "small",
9975
+ type: "button",
9976
+ onClick: onSubmit,
9977
+ isLoading: isSubmitting,
9978
+ children: "Save"
9979
+ }
9980
+ )
9981
+ ] }) })
9672
9982
  ] });
9673
9983
  };
9674
- const BillingAddressForm = ({ order }) => {
9675
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
9984
+ const Item = ({ item, preview, currencyCode }) => {
9985
+ if (item.variant_id) {
9986
+ return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
9987
+ }
9988
+ return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
9989
+ };
9990
+ const VariantItem = ({ item, preview, currencyCode }) => {
9991
+ const [editing, setEditing] = useState(false);
9676
9992
  const form = useForm({
9677
9993
  defaultValues: {
9678
- first_name: ((_a = order.billing_address) == null ? void 0 : _a.first_name) ?? "",
9679
- last_name: ((_b = order.billing_address) == null ? void 0 : _b.last_name) ?? "",
9680
- company: ((_c = order.billing_address) == null ? void 0 : _c.company) ?? "",
9681
- address_1: ((_d = order.billing_address) == null ? void 0 : _d.address_1) ?? "",
9682
- address_2: ((_e = order.billing_address) == null ? void 0 : _e.address_2) ?? "",
9683
- city: ((_f = order.billing_address) == null ? void 0 : _f.city) ?? "",
9684
- province: ((_g = order.billing_address) == null ? void 0 : _g.province) ?? "",
9685
- country_code: ((_h = order.billing_address) == null ? void 0 : _h.country_code) ?? "",
9686
- postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
9687
- phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
9994
+ quantity: item.quantity,
9995
+ unit_price: item.unit_price
9688
9996
  },
9689
- resolver: zodResolver(schema$3)
9997
+ resolver: zodResolver(variantItemSchema)
9690
9998
  });
9691
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9692
- const { handleSuccess } = useRouteModal();
9999
+ const actionId = useMemo(() => {
10000
+ var _a, _b;
10001
+ return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10002
+ }, [item]);
10003
+ const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10004
+ const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10005
+ const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
9693
10006
  const onSubmit = form.handleSubmit(async (data) => {
9694
- await mutateAsync(
9695
- { billing_address: data },
9696
- {
9697
- onSuccess: () => {
9698
- handleSuccess();
10007
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10008
+ setEditing(false);
10009
+ return;
10010
+ }
10011
+ if (!actionId) {
10012
+ await updateOriginalItem(
10013
+ {
10014
+ item_id: item.id,
10015
+ quantity: data.quantity,
10016
+ unit_price: convertNumber(data.unit_price)
9699
10017
  },
9700
- onError: (error) => {
9701
- toast.error(error.message);
10018
+ {
10019
+ onSuccess: () => {
10020
+ setEditing(false);
10021
+ },
10022
+ onError: (e) => {
10023
+ toast.error(e.message);
10024
+ }
9702
10025
  }
9703
- }
9704
- );
9705
- });
9706
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
9707
- KeyboundForm,
9708
- {
9709
- className: "flex flex-1 flex-col overflow-hidden",
9710
- onSubmit,
9711
- children: [
9712
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
9713
- /* @__PURE__ */ jsx(
9714
- Form$2.Field,
9715
- {
9716
- control: form.control,
9717
- name: "country_code",
9718
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9719
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
9720
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
9721
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9722
- ] })
9723
- }
9724
- ),
9725
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
9726
- /* @__PURE__ */ jsx(
9727
- Form$2.Field,
9728
- {
9729
- control: form.control,
9730
- name: "first_name",
9731
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9732
- /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
9733
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9734
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9735
- ] })
9736
- }
9737
- ),
9738
- /* @__PURE__ */ jsx(
9739
- Form$2.Field,
9740
- {
9741
- control: form.control,
9742
- name: "last_name",
9743
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9744
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
9745
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9746
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9747
- ] })
9748
- }
9749
- )
9750
- ] }),
9751
- /* @__PURE__ */ jsx(
9752
- Form$2.Field,
9753
- {
9754
- control: form.control,
9755
- name: "company",
9756
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9757
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
9758
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9759
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9760
- ] })
9761
- }
9762
- ),
9763
- /* @__PURE__ */ jsx(
9764
- Form$2.Field,
9765
- {
9766
- control: form.control,
9767
- name: "address_1",
9768
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9769
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
9770
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9771
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9772
- ] })
9773
- }
9774
- ),
9775
- /* @__PURE__ */ jsx(
9776
- Form$2.Field,
9777
- {
9778
- control: form.control,
9779
- name: "address_2",
9780
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9781
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
9782
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9783
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9784
- ] })
9785
- }
9786
- ),
9787
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
9788
- /* @__PURE__ */ jsx(
9789
- Form$2.Field,
9790
- {
9791
- control: form.control,
9792
- name: "postal_code",
9793
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9794
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
9795
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9796
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9797
- ] })
9798
- }
9799
- ),
9800
- /* @__PURE__ */ jsx(
9801
- Form$2.Field,
9802
- {
9803
- control: form.control,
9804
- name: "city",
9805
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9806
- /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
9807
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9808
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9809
- ] })
9810
- }
9811
- )
9812
- ] }),
9813
- /* @__PURE__ */ jsx(
9814
- Form$2.Field,
9815
- {
9816
- control: form.control,
9817
- name: "province",
9818
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9819
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
9820
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9821
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9822
- ] })
9823
- }
9824
- ),
9825
- /* @__PURE__ */ jsx(
9826
- Form$2.Field,
9827
- {
9828
- control: form.control,
9829
- name: "phone",
9830
- render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
9831
- /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
9832
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
9833
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
9834
- ] })
9835
- }
9836
- )
9837
- ] }) }),
9838
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9839
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9840
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
9841
- ] }) })
9842
- ]
9843
- }
9844
- ) });
9845
- };
9846
- const schema$3 = addressSchema;
9847
- const NumberInput = forwardRef(
9848
- ({
9849
- value,
9850
- onChange,
9851
- size = "base",
9852
- min = 0,
9853
- max = 100,
9854
- step = 1,
9855
- className,
9856
- disabled,
9857
- ...props
9858
- }, ref) => {
9859
- const handleChange = (event) => {
9860
- const newValue = event.target.value === "" ? min : Number(event.target.value);
9861
- if (!isNaN(newValue) && (max === void 0 || newValue <= max) && (min === void 0 || newValue >= min)) {
9862
- onChange(newValue);
9863
- }
9864
- };
9865
- const handleIncrement = () => {
9866
- const newValue = value + step;
9867
- if (max === void 0 || newValue <= max) {
9868
- onChange(newValue);
9869
- }
9870
- };
9871
- const handleDecrement = () => {
9872
- const newValue = value - step;
9873
- if (min === void 0 || newValue >= min) {
9874
- onChange(newValue);
9875
- }
9876
- };
9877
- return /* @__PURE__ */ jsxs(
9878
- "div",
9879
- {
9880
- className: clx(
9881
- "inline-flex rounded-md bg-ui-bg-field shadow-borders-base overflow-hidden divide-x transition-fg",
9882
- "[&:has(input:focus)]:shadow-borders-interactive-with-active",
9883
- {
9884
- "h-7": size === "small",
9885
- "h-8": size === "base"
9886
- },
9887
- className
9888
- ),
9889
- children: [
9890
- /* @__PURE__ */ jsx(
9891
- "input",
9892
- {
9893
- ref,
9894
- type: "number",
9895
- value,
9896
- onChange: handleChange,
9897
- min,
9898
- max,
9899
- step,
9900
- className: clx(
9901
- "flex-1 px-2 py-1 bg-transparent txt-compact-small text-ui-fg-base outline-none [appearance:textfield]",
9902
- "[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
9903
- "placeholder:text-ui-fg-muted"
9904
- ),
9905
- ...props
9906
- }
9907
- ),
9908
- /* @__PURE__ */ jsxs(
9909
- "button",
9910
- {
9911
- className: clx(
9912
- "flex items-center justify-center outline-none transition-fg",
9913
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9914
- "focus:bg-ui-bg-field-component-hover",
9915
- "hover:bg-ui-bg-field-component-hover",
9916
- {
9917
- "size-7": size === "small",
9918
- "size-8": size === "base"
9919
- }
9920
- ),
9921
- type: "button",
9922
- onClick: handleDecrement,
9923
- disabled: min !== void 0 && value <= min || disabled,
9924
- children: [
9925
- /* @__PURE__ */ jsx(Minus, {}),
9926
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Decrease by ${step}` })
9927
- ]
9928
- }
9929
- ),
9930
- /* @__PURE__ */ jsxs(
9931
- "button",
9932
- {
9933
- className: clx(
9934
- "flex items-center justify-center outline-none transition-fg",
9935
- "disabled:cursor-not-allowed disabled:text-ui-fg-muted",
9936
- "focus:bg-ui-bg-field-hover",
9937
- "hover:bg-ui-bg-field-hover",
9938
- {
9939
- "size-7": size === "small",
9940
- "size-8": size === "base"
9941
- }
9942
- ),
9943
- type: "button",
9944
- onClick: handleIncrement,
9945
- disabled: max !== void 0 && value >= max || disabled,
9946
- children: [
9947
- /* @__PURE__ */ jsx(Plus, {}),
9948
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: `Increase by ${step}` })
9949
- ]
9950
- }
9951
- )
9952
- ]
9953
- }
9954
- );
9955
- }
9956
- );
9957
- const PRODUCT_VARIANTS_QUERY_KEY = "product-variants";
9958
- const productVariantsQueryKeys = {
9959
- list: (query2) => [
9960
- PRODUCT_VARIANTS_QUERY_KEY,
9961
- query2 ? query2 : void 0
9962
- ]
9963
- };
9964
- const useProductVariants = (query2, options) => {
9965
- const { data, ...rest } = useQuery({
9966
- queryKey: productVariantsQueryKeys.list(query2),
9967
- queryFn: async () => await sdk.admin.productVariant.list(query2),
9968
- ...options
9969
- });
9970
- return { ...data, ...rest };
9971
- };
9972
- const useCancelOrderEdit = ({ preview }) => {
9973
- const { mutateAsync: cancelOrderEdit } = useDraftOrderCancelEdit(preview == null ? void 0 : preview.id);
9974
- const onCancel = useCallback(async () => {
9975
- if (!preview) {
9976
- return true;
9977
- }
9978
- let res = false;
9979
- await cancelOrderEdit(void 0, {
9980
- onError: (e) => {
9981
- toast.error(e.message);
9982
- },
9983
- onSuccess: () => {
9984
- res = true;
9985
- }
9986
- });
9987
- return res;
9988
- }, [preview, cancelOrderEdit]);
9989
- return { onCancel };
9990
- };
9991
- let IS_REQUEST_RUNNING = false;
9992
- const useInitiateOrderEdit = ({
9993
- preview
9994
- }) => {
9995
- const navigate = useNavigate();
9996
- const { mutateAsync } = useDraftOrderBeginEdit(preview == null ? void 0 : preview.id);
9997
- useEffect(() => {
9998
- async function run() {
9999
- if (IS_REQUEST_RUNNING || !preview) {
10000
- return;
10001
- }
10002
- if (preview.order_change) {
10003
- return;
10004
- }
10005
- IS_REQUEST_RUNNING = true;
10006
- await mutateAsync(void 0, {
10007
- onError: (e) => {
10008
- toast.error(e.message);
10009
- navigate(`/draft-orders/${preview.id}`, { replace: true });
10010
- return;
10011
- }
10012
- });
10013
- IS_REQUEST_RUNNING = false;
10014
- }
10015
- run();
10016
- }, [preview, navigate, mutateAsync]);
10017
- };
10018
- function convertNumber(value) {
10019
- return typeof value === "string" ? Number(value.replace(",", ".")) : value;
10020
- }
10021
- const STACKED_MODAL_ID = "items_stacked_modal";
10022
- const Items = () => {
10023
- const { id } = useParams();
10024
- const {
10025
- order: preview,
10026
- isPending: isPreviewPending,
10027
- isError: isPreviewError,
10028
- error: previewError
10029
- } = useOrderPreview(id, void 0, {
10030
- placeholderData: keepPreviousData
10031
- });
10032
- useInitiateOrderEdit({ preview });
10033
- const { draft_order, isPending, isError, error } = useDraftOrder(
10034
- id,
10035
- {
10036
- fields: "currency_code"
10037
- },
10038
- {
10039
- enabled: !!id
10040
- }
10041
- );
10042
- const { onCancel } = useCancelOrderEdit({ preview });
10043
- if (isError) {
10044
- throw error;
10045
- }
10046
- if (isPreviewError) {
10047
- throw previewError;
10048
- }
10049
- const ready = !!preview && !isPreviewPending && !!draft_order && !isPending;
10050
- return /* @__PURE__ */ jsx(RouteFocusModal, { onClose: onCancel, children: ready ? /* @__PURE__ */ jsx(ItemsForm, { preview, currencyCode: draft_order.currency_code }) : /* @__PURE__ */ jsxs("div", { children: [
10051
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit Items" }) }),
10052
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading data for the draft order, please wait..." }) })
10053
- ] }) });
10054
- };
10055
- const ItemsForm = ({ preview, currencyCode }) => {
10056
- var _a;
10057
- const [isSubmitting, setIsSubmitting] = useState(false);
10058
- const [modalContent, setModalContent] = useState(
10059
- null
10060
- );
10061
- const { handleSuccess } = useRouteModal();
10062
- const { searchValue, onSearchValueChange, query: query2 } = useDebouncedSearch();
10063
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10064
- const { mutateAsync: requestOrderEdit } = useDraftOrderRequestEdit(preview.id);
10065
- const itemCount = ((_a = preview.items) == null ? void 0 : _a.reduce((acc, item) => acc + item.quantity, 0)) || 0;
10066
- const matches = useMemo(() => {
10067
- return matchSorter(preview.items, query2, {
10068
- keys: ["product_title", "variant_title", "variant_sku", "title"]
10069
- });
10070
- }, [preview.items, query2]);
10071
- const onSubmit = async () => {
10072
- setIsSubmitting(true);
10073
- let requestSucceeded = false;
10074
- await requestOrderEdit(void 0, {
10075
- onError: (e) => {
10076
- toast.error(`Failed to request order edit: ${e.message}`);
10077
- },
10078
- onSuccess: () => {
10079
- requestSucceeded = true;
10080
- }
10081
- });
10082
- if (!requestSucceeded) {
10083
- setIsSubmitting(false);
10026
+ );
10084
10027
  return;
10085
10028
  }
10086
- await confirmOrderEdit(void 0, {
10087
- onError: (e) => {
10088
- toast.error(`Failed to confirm order edit: ${e.message}`);
10089
- },
10090
- onSuccess: () => {
10091
- handleSuccess();
10029
+ await updateActionItem(
10030
+ {
10031
+ action_id: actionId,
10032
+ quantity: data.quantity,
10033
+ unit_price: convertNumber(data.unit_price)
10092
10034
  },
10093
- onSettled: () => {
10094
- setIsSubmitting(false);
10035
+ {
10036
+ onSuccess: () => {
10037
+ setEditing(false);
10038
+ },
10039
+ onError: (e) => {
10040
+ toast.error(e.message);
10041
+ }
10095
10042
  }
10096
- });
10097
- };
10098
- const onKeyDown = useCallback(
10099
- (e) => {
10100
- if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
10101
- if (modalContent || isSubmitting) {
10102
- return;
10043
+ );
10044
+ });
10045
+ 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: [
10046
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10047
+ /* @__PURE__ */ jsx(
10048
+ Thumbnail,
10049
+ {
10050
+ thumbnail: item.thumbnail,
10051
+ alt: item.product_title ?? void 0
10052
+ }
10053
+ ),
10054
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10055
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10056
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10057
+ /* @__PURE__ */ jsxs(
10058
+ Text,
10059
+ {
10060
+ size: "small",
10061
+ leading: "compact",
10062
+ className: "text-ui-fg-subtle",
10063
+ children: [
10064
+ "(",
10065
+ item.variant_title,
10066
+ ")"
10067
+ ]
10068
+ }
10069
+ )
10070
+ ] }),
10071
+ /* @__PURE__ */ jsx(
10072
+ Text,
10073
+ {
10074
+ size: "small",
10075
+ leading: "compact",
10076
+ className: "text-ui-fg-subtle",
10077
+ children: item.variant_sku
10078
+ }
10079
+ )
10080
+ ] })
10081
+ ] }),
10082
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10083
+ Form$2.Field,
10084
+ {
10085
+ control: form.control,
10086
+ name: "quantity",
10087
+ render: ({ field }) => {
10088
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10103
10089
  }
10104
- onSubmit();
10105
10090
  }
10106
- },
10107
- [modalContent, isSubmitting, onSubmit]
10108
- );
10109
- useEffect(() => {
10110
- document.addEventListener("keydown", onKeyDown);
10111
- return () => {
10112
- document.removeEventListener("keydown", onKeyDown);
10113
- };
10114
- }, [onKeyDown]);
10115
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
10116
- /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
10117
- /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsxs(
10118
- StackedFocusModal,
10091
+ ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10092
+ editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10093
+ Form$2.Field,
10119
10094
  {
10120
- id: STACKED_MODAL_ID,
10121
- onOpenChangeCallback: (open) => {
10122
- if (!open) {
10123
- setModalContent(null);
10124
- }
10125
- },
10126
- children: [
10127
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-6 py-16", children: [
10128
- /* @__PURE__ */ jsxs("div", { children: [
10129
- /* @__PURE__ */ jsx(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Items" }) }),
10130
- /* @__PURE__ */ jsx(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Edit the items in the draft order" }) })
10131
- ] }),
10132
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10133
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
10134
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3", children: [
10135
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10136
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Items" }),
10137
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Choose items from the product catalog." })
10138
- ] }),
10139
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
10140
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
10141
- Input,
10142
- {
10143
- type: "search",
10144
- placeholder: "Search items",
10145
- value: searchValue,
10146
- onChange: (e) => onSearchValueChange(e.target.value)
10147
- }
10148
- ) }),
10149
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10150
- /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { type: "button", children: /* @__PURE__ */ jsx(Plus, {}) }) }),
10151
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10152
- /* @__PURE__ */ jsx(
10153
- StackedModalTrigger$1,
10154
- {
10155
- type: "add-items",
10156
- setModalContent
10157
- }
10158
- ),
10159
- /* @__PURE__ */ jsx(
10160
- StackedModalTrigger$1,
10161
- {
10162
- type: "add-custom-item",
10163
- setModalContent
10164
- }
10165
- )
10166
- ] })
10167
- ] })
10168
- ] })
10169
- ] }),
10170
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl", children: [
10171
- /* @__PURE__ */ jsx("div", { className: "px-[5px]", children: /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2", children: [
10172
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Item" }) }),
10173
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Quantity" }) }),
10174
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: "Price" }) }),
10175
- /* @__PURE__ */ jsx("div", {})
10176
- ] }) }),
10177
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-y-1.5 px-[5px] pb-[5px]", children: itemCount <= 0 ? /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10178
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "There are no items in this order" }),
10179
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add items to the order to get started." })
10180
- ] }) : matches.length > 0 ? matches == null ? void 0 : matches.map((item) => /* @__PURE__ */ jsx(
10181
- Item,
10182
- {
10183
- item,
10184
- preview,
10185
- currencyCode
10186
- },
10187
- item.id
10188
- )) : /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4", children: [
10189
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "No items found" }),
10190
- /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
10191
- 'No items found for "',
10192
- query2,
10193
- '".'
10194
- ] })
10195
- ] }) })
10196
- ] })
10197
- ] }),
10198
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10199
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_0.5fr_0.5fr] gap-3", children: [
10200
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: "Subtotal" }) }),
10201
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
10202
- Text,
10203
- {
10204
- size: "small",
10205
- leading: "compact",
10206
- className: "text-ui-fg-subtle",
10207
- children: [
10208
- itemCount,
10209
- " ",
10210
- itemCount === 1 ? "item" : "items"
10211
- ]
10212
- }
10213
- ) }),
10214
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: getStylizedAmount(preview.item_subtotal, currencyCode) }) })
10215
- ] })
10216
- ] }) }),
10217
- modalContent && (modalContent === "add-items" ? /* @__PURE__ */ jsx(ExistingItemsForm, { orderId: preview.id, items: preview.items }) : modalContent === "add-custom-item" ? /* @__PURE__ */ jsx(
10218
- CustomItemForm,
10095
+ control: form.control,
10096
+ name: "unit_price",
10097
+ render: ({ field: { onChange, ...field } }) => {
10098
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10099
+ CurrencyInput,
10219
10100
  {
10220
- orderId: preview.id,
10221
- currencyCode
10101
+ ...field,
10102
+ symbol: getNativeSymbol(currencyCode),
10103
+ code: currencyCode,
10104
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10222
10105
  }
10223
- ) : null)
10224
- ]
10225
- }
10226
- ) }),
10227
- /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10228
- /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10229
- /* @__PURE__ */ jsx(
10230
- Button,
10231
- {
10232
- size: "small",
10233
- type: "button",
10234
- onClick: onSubmit,
10235
- isLoading: isSubmitting,
10236
- children: "Save"
10106
+ ) }) });
10237
10107
  }
10238
- )
10239
- ] }) })
10240
- ] });
10241
- };
10242
- const Item = ({ item, preview, currencyCode }) => {
10243
- if (item.variant_id) {
10244
- return /* @__PURE__ */ jsx(VariantItem, { item, preview, currencyCode });
10245
- }
10246
- return /* @__PURE__ */ jsx(CustomItem, { item, preview, currencyCode });
10108
+ }
10109
+ ) }) : /* @__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) }) }),
10110
+ /* @__PURE__ */ jsx(
10111
+ IconButton,
10112
+ {
10113
+ type: "button",
10114
+ size: "small",
10115
+ onClick: editing ? onSubmit : () => {
10116
+ setEditing(true);
10117
+ },
10118
+ disabled: isPending,
10119
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10120
+ }
10121
+ )
10122
+ ] }) }) });
10247
10123
  };
10248
- const VariantItem = ({ item, preview, currencyCode }) => {
10124
+ const variantItemSchema = objectType({
10125
+ quantity: numberType(),
10126
+ unit_price: unionType([numberType(), stringType()])
10127
+ });
10128
+ const CustomItem = ({ item, preview, currencyCode }) => {
10249
10129
  const [editing, setEditing] = useState(false);
10130
+ const { quantity, unit_price, title } = item;
10250
10131
  const form = useForm({
10251
10132
  defaultValues: {
10252
- quantity: item.quantity,
10253
- unit_price: item.unit_price
10133
+ title,
10134
+ quantity,
10135
+ unit_price
10254
10136
  },
10255
- resolver: zodResolver(variantItemSchema)
10137
+ resolver: zodResolver(customItemSchema)
10256
10138
  });
10139
+ useEffect(() => {
10140
+ form.reset({
10141
+ title,
10142
+ quantity,
10143
+ unit_price
10144
+ });
10145
+ }, [form, title, quantity, unit_price]);
10257
10146
  const actionId = useMemo(() => {
10258
10147
  var _a, _b;
10259
10148
  return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10260
10149
  }, [item]);
10261
10150
  const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10151
+ const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10262
10152
  const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10263
10153
  const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10264
10154
  const onSubmit = form.handleSubmit(async (data) => {
10265
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity) {
10155
+ if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10266
10156
  setEditing(false);
10267
10157
  return;
10268
10158
  }
@@ -10284,6 +10174,17 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10284
10174
  );
10285
10175
  return;
10286
10176
  }
10177
+ if (data.quantity === 0) {
10178
+ await removeActionItem(actionId, {
10179
+ onSuccess: () => {
10180
+ setEditing(false);
10181
+ },
10182
+ onError: (e) => {
10183
+ toast.error(e.message);
10184
+ }
10185
+ });
10186
+ return;
10187
+ }
10287
10188
  await updateActionItem(
10288
10189
  {
10289
10190
  action_id: actionId,
@@ -10301,43 +10202,26 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10301
10202
  );
10302
10203
  });
10303
10204
  return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10304
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-x-3", children: [
10205
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10305
10206
  /* @__PURE__ */ jsx(
10306
10207
  Thumbnail,
10307
10208
  {
10308
10209
  thumbnail: item.thumbnail,
10309
- alt: item.product_title ?? void 0
10210
+ alt: item.title ?? void 0
10310
10211
  }
10311
10212
  ),
10312
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10313
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
10314
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
10315
- /* @__PURE__ */ jsxs(
10316
- Text,
10317
- {
10318
- size: "small",
10319
- leading: "compact",
10320
- className: "text-ui-fg-subtle",
10321
- children: [
10322
- "(",
10323
- item.variant_title,
10324
- ")"
10325
- ]
10326
- }
10327
- )
10328
- ] }),
10329
- /* @__PURE__ */ jsx(
10330
- Text,
10331
- {
10332
- size: "small",
10333
- leading: "compact",
10334
- className: "text-ui-fg-subtle",
10335
- children: item.variant_sku
10213
+ editing ? /* @__PURE__ */ jsx(
10214
+ Form$2.Field,
10215
+ {
10216
+ control: form.control,
10217
+ name: "title",
10218
+ render: ({ field }) => {
10219
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10336
10220
  }
10337
- )
10338
- ] })
10221
+ }
10222
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10339
10223
  ] }),
10340
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10224
+ editing ? /* @__PURE__ */ jsx(
10341
10225
  Form$2.Field,
10342
10226
  {
10343
10227
  control: form.control,
@@ -10346,8 +10230,8 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10346
10230
  return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10347
10231
  }
10348
10232
  }
10349
- ) }) : /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }) }),
10350
- editing ? /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(
10233
+ ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10234
+ editing ? /* @__PURE__ */ jsx(
10351
10235
  Form$2.Field,
10352
10236
  {
10353
10237
  control: form.control,
@@ -10356,102 +10240,238 @@ const VariantItem = ({ item, preview, currencyCode }) => {
10356
10240
  return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10357
10241
  CurrencyInput,
10358
10242
  {
10359
- ...field,
10360
- symbol: getNativeSymbol(currencyCode),
10361
- code: currencyCode,
10362
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10243
+ ...field,
10244
+ symbol: getNativeSymbol(currencyCode),
10245
+ code: currencyCode,
10246
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10247
+ }
10248
+ ) }) });
10249
+ }
10250
+ }
10251
+ ) : /* @__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) }) }),
10252
+ /* @__PURE__ */ jsx(
10253
+ IconButton,
10254
+ {
10255
+ type: "button",
10256
+ size: "small",
10257
+ onClick: editing ? onSubmit : () => {
10258
+ setEditing(true);
10259
+ },
10260
+ disabled: isPending,
10261
+ children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10262
+ }
10263
+ )
10264
+ ] }) }) });
10265
+ };
10266
+ const StackedModalTrigger$1 = ({
10267
+ type,
10268
+ setModalContent
10269
+ }) => {
10270
+ const { setIsOpen } = useStackedModal();
10271
+ const onClick = useCallback(() => {
10272
+ setModalContent(type);
10273
+ setIsOpen(STACKED_MODAL_ID, true);
10274
+ }, [setModalContent, setIsOpen, type]);
10275
+ return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10276
+ };
10277
+ const VARIANT_PREFIX = "items";
10278
+ const LIMIT = 50;
10279
+ const ExistingItemsForm = ({ orderId, items }) => {
10280
+ const { setIsOpen } = useStackedModal();
10281
+ const [rowSelection, setRowSelection] = useState(
10282
+ items.reduce((acc, item) => {
10283
+ acc[item.variant_id] = true;
10284
+ return acc;
10285
+ }, {})
10286
+ );
10287
+ useEffect(() => {
10288
+ setRowSelection(
10289
+ items.reduce((acc, item) => {
10290
+ if (item.variant_id) {
10291
+ acc[item.variant_id] = true;
10292
+ }
10293
+ return acc;
10294
+ }, {})
10295
+ );
10296
+ }, [items]);
10297
+ const { q, order, offset } = useQueryParams(
10298
+ ["q", "order", "offset"],
10299
+ VARIANT_PREFIX
10300
+ );
10301
+ const { variants, count, isPending, isError, error } = useProductVariants(
10302
+ {
10303
+ q,
10304
+ order,
10305
+ offset: offset ? parseInt(offset) : void 0,
10306
+ limit: LIMIT
10307
+ },
10308
+ {
10309
+ placeholderData: keepPreviousData
10310
+ }
10311
+ );
10312
+ const columns = useColumns();
10313
+ const { mutateAsync } = useDraftOrderAddItems(orderId);
10314
+ const onSubmit = async () => {
10315
+ const ids = Object.keys(rowSelection).filter(
10316
+ (id) => !items.find((i) => i.variant_id === id)
10317
+ );
10318
+ await mutateAsync(
10319
+ {
10320
+ items: ids.map((id) => ({
10321
+ variant_id: id,
10322
+ quantity: 1
10323
+ }))
10324
+ },
10325
+ {
10326
+ onSuccess: () => {
10327
+ setRowSelection({});
10328
+ setIsOpen(STACKED_MODAL_ID, false);
10329
+ },
10330
+ onError: (e) => {
10331
+ toast.error(e.message);
10332
+ }
10333
+ }
10334
+ );
10335
+ };
10336
+ if (isError) {
10337
+ throw error;
10338
+ }
10339
+ return /* @__PURE__ */ jsxs(
10340
+ StackedFocusModal.Content,
10341
+ {
10342
+ onOpenAutoFocus: (e) => {
10343
+ e.preventDefault();
10344
+ const searchInput = document.querySelector(
10345
+ "[data-modal-id='modal-search-input']"
10346
+ );
10347
+ if (searchInput) {
10348
+ searchInput.focus();
10349
+ }
10350
+ },
10351
+ children: [
10352
+ /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10353
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10354
+ /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10355
+ ] }),
10356
+ /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10357
+ DataTable,
10358
+ {
10359
+ data: variants,
10360
+ columns,
10361
+ isLoading: isPending,
10362
+ getRowId: (row) => row.id,
10363
+ rowCount: count,
10364
+ prefix: VARIANT_PREFIX,
10365
+ layout: "fill",
10366
+ rowSelection: {
10367
+ state: rowSelection,
10368
+ onRowSelectionChange: setRowSelection,
10369
+ enableRowSelection: (row) => {
10370
+ return !items.find((i) => i.variant_id === row.original.id);
10371
+ }
10372
+ },
10373
+ autoFocusSearch: true
10374
+ }
10375
+ ) }),
10376
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10377
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10378
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10379
+ ] }) })
10380
+ ]
10381
+ }
10382
+ );
10383
+ };
10384
+ const columnHelper = createDataTableColumnHelper();
10385
+ const useColumns = () => {
10386
+ return useMemo(() => {
10387
+ return [
10388
+ columnHelper.select(),
10389
+ columnHelper.accessor("product.title", {
10390
+ header: "Product",
10391
+ cell: ({ row }) => {
10392
+ var _a, _b, _c;
10393
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10394
+ /* @__PURE__ */ jsx(
10395
+ Thumbnail,
10396
+ {
10397
+ thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10398
+ alt: (_b = row.original.product) == null ? void 0 : _b.title
10399
+ }
10400
+ ),
10401
+ /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10402
+ ] });
10403
+ },
10404
+ enableSorting: true
10405
+ }),
10406
+ columnHelper.accessor("title", {
10407
+ header: "Variant",
10408
+ enableSorting: true
10409
+ }),
10410
+ columnHelper.accessor("sku", {
10411
+ header: "SKU",
10412
+ cell: ({ getValue }) => {
10413
+ return getValue() ?? "-";
10414
+ },
10415
+ enableSorting: true
10416
+ }),
10417
+ columnHelper.accessor("updated_at", {
10418
+ header: "Updated",
10419
+ cell: ({ getValue }) => {
10420
+ return /* @__PURE__ */ jsx(
10421
+ Tooltip,
10422
+ {
10423
+ content: getFullDate({ date: getValue(), includeTime: true }),
10424
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10425
+ }
10426
+ );
10427
+ },
10428
+ enableSorting: true,
10429
+ sortAscLabel: "Oldest first",
10430
+ sortDescLabel: "Newest first"
10431
+ }),
10432
+ columnHelper.accessor("created_at", {
10433
+ header: "Created",
10434
+ cell: ({ getValue }) => {
10435
+ return /* @__PURE__ */ jsx(
10436
+ Tooltip,
10437
+ {
10438
+ content: getFullDate({ date: getValue(), includeTime: true }),
10439
+ children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10363
10440
  }
10364
- ) }) });
10365
- }
10366
- }
10367
- ) }) : /* @__PURE__ */ jsx("div", { className: "flex w-full flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10368
- /* @__PURE__ */ jsx(
10369
- IconButton,
10370
- {
10371
- type: "button",
10372
- size: "small",
10373
- onClick: editing ? onSubmit : () => {
10374
- setEditing(true);
10441
+ );
10375
10442
  },
10376
- disabled: isPending,
10377
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10378
- }
10379
- )
10380
- ] }) }) });
10443
+ enableSorting: true,
10444
+ sortAscLabel: "Oldest first",
10445
+ sortDescLabel: "Newest first"
10446
+ })
10447
+ ];
10448
+ }, []);
10381
10449
  };
10382
- const variantItemSchema = objectType({
10383
- quantity: numberType(),
10384
- unit_price: unionType([numberType(), stringType()])
10385
- });
10386
- const CustomItem = ({ item, preview, currencyCode }) => {
10387
- const [editing, setEditing] = useState(false);
10388
- const { quantity, unit_price, title } = item;
10450
+ const CustomItemForm = ({ orderId, currencyCode }) => {
10451
+ const { setIsOpen } = useStackedModal();
10452
+ const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10389
10453
  const form = useForm({
10390
10454
  defaultValues: {
10391
- title,
10392
- quantity,
10393
- unit_price
10455
+ title: "",
10456
+ quantity: 1,
10457
+ unit_price: ""
10394
10458
  },
10395
10459
  resolver: zodResolver(customItemSchema)
10396
10460
  });
10397
- useEffect(() => {
10398
- form.reset({
10399
- title,
10400
- quantity,
10401
- unit_price
10402
- });
10403
- }, [form, title, quantity, unit_price]);
10404
- const actionId = useMemo(() => {
10405
- var _a, _b;
10406
- return (_b = (_a = item.actions) == null ? void 0 : _a.find((a) => a.action === "ITEM_ADD")) == null ? void 0 : _b.id;
10407
- }, [item]);
10408
- const { mutateAsync: updateActionItem, isPending: isUpdatingActionItem } = useDraftOrderUpdateActionItem(preview.id);
10409
- const { mutateAsync: removeActionItem, isPending: isRemovingActionItem } = useDraftOrderRemoveActionItem(preview.id);
10410
- const { mutateAsync: updateOriginalItem, isPending: isUpdatingOriginalItem } = useDraftOrderUpdateItem(preview.id);
10411
- const isPending = isUpdatingActionItem || isUpdatingOriginalItem;
10412
10461
  const onSubmit = form.handleSubmit(async (data) => {
10413
- if (convertNumber(data.unit_price) === item.unit_price && data.quantity === item.quantity && data.title === item.title) {
10414
- setEditing(false);
10415
- return;
10416
- }
10417
- if (!actionId) {
10418
- await updateOriginalItem(
10419
- {
10420
- item_id: item.id,
10421
- quantity: data.quantity,
10422
- unit_price: convertNumber(data.unit_price)
10423
- },
10424
- {
10425
- onSuccess: () => {
10426
- setEditing(false);
10427
- },
10428
- onError: (e) => {
10429
- toast.error(e.message);
10430
- }
10431
- }
10432
- );
10433
- return;
10434
- }
10435
- if (data.quantity === 0) {
10436
- await removeActionItem(actionId, {
10437
- onSuccess: () => {
10438
- setEditing(false);
10439
- },
10440
- onError: (e) => {
10441
- toast.error(e.message);
10442
- }
10443
- });
10444
- return;
10445
- }
10446
- await updateActionItem(
10462
+ await addItems(
10447
10463
  {
10448
- action_id: actionId,
10449
- quantity: data.quantity,
10450
- unit_price: convertNumber(data.unit_price)
10464
+ items: [
10465
+ {
10466
+ title: data.title,
10467
+ quantity: data.quantity,
10468
+ unit_price: convertNumber(data.unit_price)
10469
+ }
10470
+ ]
10451
10471
  },
10452
10472
  {
10453
10473
  onSuccess: () => {
10454
- setEditing(false);
10474
+ setIsOpen(STACKED_MODAL_ID, false);
10455
10475
  },
10456
10476
  onError: (e) => {
10457
10477
  toast.error(e.message);
@@ -10459,365 +10479,437 @@ const CustomItem = ({ item, preview, currencyCode }) => {
10459
10479
  }
10460
10480
  );
10461
10481
  });
10462
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx("form", { onSubmit, children: /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2", children: [
10463
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
10482
+ return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10483
+ /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10484
+ /* @__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: [
10485
+ /* @__PURE__ */ jsxs("div", { children: [
10486
+ /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10487
+ /* @__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." }) })
10488
+ ] }),
10489
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10464
10490
  /* @__PURE__ */ jsx(
10465
- Thumbnail,
10491
+ Form$2.Field,
10466
10492
  {
10467
- thumbnail: item.thumbnail,
10468
- alt: item.title ?? void 0
10493
+ control: form.control,
10494
+ name: "title",
10495
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10496
+ /* @__PURE__ */ jsxs("div", { children: [
10497
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10498
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10499
+ ] }),
10500
+ /* @__PURE__ */ jsxs("div", { children: [
10501
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10502
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10503
+ ] })
10504
+ ] }) })
10469
10505
  }
10470
10506
  ),
10471
- editing ? /* @__PURE__ */ jsx(
10507
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10508
+ /* @__PURE__ */ jsx(
10472
10509
  Form$2.Field,
10473
10510
  {
10474
10511
  control: form.control,
10475
- name: "title",
10476
- render: ({ field }) => {
10477
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }) });
10478
- }
10512
+ name: "unit_price",
10513
+ render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10514
+ /* @__PURE__ */ jsxs("div", { children: [
10515
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10516
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10517
+ ] }),
10518
+ /* @__PURE__ */ jsxs("div", { children: [
10519
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10520
+ CurrencyInput,
10521
+ {
10522
+ symbol: getNativeSymbol(currencyCode),
10523
+ code: currencyCode,
10524
+ onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10525
+ ...field
10526
+ }
10527
+ ) }),
10528
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10529
+ ] })
10530
+ ] }) })
10479
10531
  }
10480
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.title })
10481
- ] }),
10482
- editing ? /* @__PURE__ */ jsx(
10483
- Form$2.Field,
10484
- {
10485
- control: form.control,
10486
- name: "quantity",
10487
- render: ({ field }) => {
10488
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(NumberInput, { ...field }) }) });
10532
+ ),
10533
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10534
+ /* @__PURE__ */ jsx(
10535
+ Form$2.Field,
10536
+ {
10537
+ control: form.control,
10538
+ name: "quantity",
10539
+ render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10540
+ /* @__PURE__ */ jsxs("div", { children: [
10541
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10542
+ /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10543
+ ] }),
10544
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
10545
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10546
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10547
+ ] })
10548
+ ] }) })
10489
10549
  }
10490
- }
10491
- ) : /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: item.quantity }),
10492
- editing ? /* @__PURE__ */ jsx(
10493
- Form$2.Field,
10550
+ )
10551
+ ] }) }) }),
10552
+ /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10553
+ /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10554
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10555
+ ] }) })
10556
+ ] }) }) });
10557
+ };
10558
+ const customItemSchema = objectType({
10559
+ title: stringType().min(1),
10560
+ quantity: numberType(),
10561
+ unit_price: unionType([numberType(), stringType()])
10562
+ });
10563
+ const InlineTip = forwardRef(
10564
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
10565
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10566
+ return /* @__PURE__ */ jsxs(
10567
+ "div",
10494
10568
  {
10495
- control: form.control,
10496
- name: "unit_price",
10497
- render: ({ field: { onChange, ...field } }) => {
10498
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10499
- CurrencyInput,
10569
+ ref,
10570
+ className: clx(
10571
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10572
+ className
10573
+ ),
10574
+ ...props,
10575
+ children: [
10576
+ /* @__PURE__ */ jsx(
10577
+ "div",
10500
10578
  {
10501
- ...field,
10502
- symbol: getNativeSymbol(currencyCode),
10503
- code: currencyCode,
10504
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value)
10579
+ role: "presentation",
10580
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10581
+ "bg-ui-tag-orange-icon": variant === "warning"
10582
+ })
10505
10583
  }
10506
- ) }) });
10507
- }
10508
- }
10509
- ) : /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-end", children: /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: getLocaleAmount(item.unit_price, currencyCode) }) }),
10510
- /* @__PURE__ */ jsx(
10511
- IconButton,
10512
- {
10513
- type: "button",
10514
- size: "small",
10515
- onClick: editing ? onSubmit : () => {
10516
- setEditing(true);
10517
- },
10518
- disabled: isPending,
10519
- children: editing ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(PencilSquare, {})
10584
+ ),
10585
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10586
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10587
+ labelValue,
10588
+ ":"
10589
+ ] }),
10590
+ " ",
10591
+ children
10592
+ ] })
10593
+ ]
10520
10594
  }
10521
- )
10522
- ] }) }) });
10523
- };
10524
- const StackedModalTrigger$1 = ({
10525
- type,
10526
- setModalContent
10527
- }) => {
10528
- const { setIsOpen } = useStackedModal();
10529
- const onClick = useCallback(() => {
10530
- setModalContent(type);
10531
- setIsOpen(STACKED_MODAL_ID, true);
10532
- }, [setModalContent, setIsOpen, type]);
10533
- return /* @__PURE__ */ jsx(StackedFocusModal.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Item, { onClick, children: type === "add-items" ? "Add items" : "Add custom item" }) });
10534
- };
10535
- const VARIANT_PREFIX = "items";
10536
- const LIMIT = 50;
10537
- const ExistingItemsForm = ({ orderId, items }) => {
10538
- const { setIsOpen } = useStackedModal();
10539
- const [rowSelection, setRowSelection] = useState(
10540
- items.reduce((acc, item) => {
10541
- acc[item.variant_id] = true;
10542
- return acc;
10543
- }, {})
10544
- );
10545
- useEffect(() => {
10546
- setRowSelection(
10547
- items.reduce((acc, item) => {
10548
- if (item.variant_id) {
10549
- acc[item.variant_id] = true;
10550
- }
10551
- return acc;
10552
- }, {})
10553
10595
  );
10554
- }, [items]);
10555
- const { q, order, offset } = useQueryParams(
10556
- ["q", "order", "offset"],
10557
- VARIANT_PREFIX
10558
- );
10559
- const { variants, count, isPending, isError, error } = useProductVariants(
10560
- {
10561
- q,
10562
- order,
10563
- offset: offset ? parseInt(offset) : void 0,
10564
- limit: LIMIT
10596
+ }
10597
+ );
10598
+ InlineTip.displayName = "InlineTip";
10599
+ const MetadataFieldSchema = objectType({
10600
+ key: stringType(),
10601
+ disabled: booleanType().optional(),
10602
+ value: anyType()
10603
+ });
10604
+ const MetadataSchema = objectType({
10605
+ metadata: arrayType(MetadataFieldSchema)
10606
+ });
10607
+ const Metadata = () => {
10608
+ const { id } = useParams();
10609
+ const { order, isPending, isError, error } = useOrder(id, {
10610
+ fields: "metadata"
10611
+ });
10612
+ if (isError) {
10613
+ throw error;
10614
+ }
10615
+ const isReady = !isPending && !!order;
10616
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10617
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10618
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10619
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10620
+ ] }),
10621
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10622
+ ] });
10623
+ };
10624
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10625
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10626
+ const MetadataForm = ({ orderId, metadata }) => {
10627
+ const { handleSuccess } = useRouteModal();
10628
+ const hasUneditableRows = getHasUneditableRows(metadata);
10629
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10630
+ const form = useForm({
10631
+ defaultValues: {
10632
+ metadata: getDefaultValues(metadata)
10565
10633
  },
10566
- {
10567
- placeholderData: keepPreviousData
10568
- }
10569
- );
10570
- const columns = useColumns();
10571
- const { mutateAsync } = useDraftOrderAddItems(orderId);
10572
- const onSubmit = async () => {
10573
- const ids = Object.keys(rowSelection).filter(
10574
- (id) => !items.find((i) => i.variant_id === id)
10575
- );
10634
+ resolver: zodResolver(MetadataSchema)
10635
+ });
10636
+ const handleSubmit = form.handleSubmit(async (data) => {
10637
+ const parsedData = parseValues(data);
10576
10638
  await mutateAsync(
10577
10639
  {
10578
- items: ids.map((id) => ({
10579
- variant_id: id,
10580
- quantity: 1
10581
- }))
10640
+ metadata: parsedData
10582
10641
  },
10583
10642
  {
10584
10643
  onSuccess: () => {
10585
- setRowSelection({});
10586
- setIsOpen(STACKED_MODAL_ID, false);
10644
+ toast.success("Metadata updated");
10645
+ handleSuccess();
10587
10646
  },
10588
- onError: (e) => {
10589
- toast.error(e.message);
10647
+ onError: (error) => {
10648
+ toast.error(error.message);
10590
10649
  }
10591
10650
  }
10592
10651
  );
10593
- };
10594
- if (isError) {
10595
- throw error;
10652
+ });
10653
+ const { fields, insert, remove } = useFieldArray({
10654
+ control: form.control,
10655
+ name: "metadata"
10656
+ });
10657
+ function deleteRow(index) {
10658
+ remove(index);
10659
+ if (fields.length === 1) {
10660
+ insert(0, {
10661
+ key: "",
10662
+ value: "",
10663
+ disabled: false
10664
+ });
10665
+ }
10596
10666
  }
10597
- return /* @__PURE__ */ jsxs(
10598
- StackedFocusModal.Content,
10667
+ function insertRow(index, position) {
10668
+ insert(index + (position === "above" ? 0 : 1), {
10669
+ key: "",
10670
+ value: "",
10671
+ disabled: false
10672
+ });
10673
+ }
10674
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10675
+ KeyboundForm,
10599
10676
  {
10600
- onOpenAutoFocus: (e) => {
10601
- e.preventDefault();
10602
- const searchInput = document.querySelector(
10603
- "[data-modal-id='modal-search-input']"
10604
- );
10605
- if (searchInput) {
10606
- searchInput.focus();
10607
- }
10608
- },
10677
+ onSubmit: handleSubmit,
10678
+ className: "flex flex-1 flex-col overflow-hidden",
10609
10679
  children: [
10610
- /* @__PURE__ */ jsxs(StackedFocusModal.Header, { children: [
10611
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Product Variants" }) }),
10612
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Choose product variants to add to the order." }) })
10680
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10681
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10682
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10683
+ /* @__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" }) }),
10684
+ /* @__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" }) })
10685
+ ] }),
10686
+ fields.map((field, index) => {
10687
+ const isDisabled = field.disabled || false;
10688
+ let placeholder = "-";
10689
+ if (typeof field.value === "object") {
10690
+ placeholder = "{ ... }";
10691
+ }
10692
+ if (Array.isArray(field.value)) {
10693
+ placeholder = "[ ... ]";
10694
+ }
10695
+ return /* @__PURE__ */ jsx(
10696
+ ConditionalTooltip,
10697
+ {
10698
+ showTooltip: isDisabled,
10699
+ content: "This row is disabled because it contains non-primitive data.",
10700
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10701
+ /* @__PURE__ */ jsxs(
10702
+ "div",
10703
+ {
10704
+ className: clx("grid grid-cols-2 divide-x", {
10705
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
10706
+ }),
10707
+ children: [
10708
+ /* @__PURE__ */ jsx(
10709
+ Form$2.Field,
10710
+ {
10711
+ control: form.control,
10712
+ name: `metadata.${index}.key`,
10713
+ render: ({ field: field2 }) => {
10714
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10715
+ GridInput,
10716
+ {
10717
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
10718
+ ...field2,
10719
+ disabled: isDisabled,
10720
+ placeholder: "Key"
10721
+ }
10722
+ ) }) });
10723
+ }
10724
+ }
10725
+ ),
10726
+ /* @__PURE__ */ jsx(
10727
+ Form$2.Field,
10728
+ {
10729
+ control: form.control,
10730
+ name: `metadata.${index}.value`,
10731
+ render: ({ field: { value, ...field2 } }) => {
10732
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10733
+ GridInput,
10734
+ {
10735
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
10736
+ ...field2,
10737
+ value: isDisabled ? placeholder : value,
10738
+ disabled: isDisabled,
10739
+ placeholder: "Value"
10740
+ }
10741
+ ) }) });
10742
+ }
10743
+ }
10744
+ )
10745
+ ]
10746
+ }
10747
+ ),
10748
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10749
+ /* @__PURE__ */ jsx(
10750
+ DropdownMenu.Trigger,
10751
+ {
10752
+ className: clx(
10753
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10754
+ {
10755
+ hidden: isDisabled
10756
+ }
10757
+ ),
10758
+ disabled: isDisabled,
10759
+ asChild: true,
10760
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
10761
+ }
10762
+ ),
10763
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
10764
+ /* @__PURE__ */ jsxs(
10765
+ DropdownMenu.Item,
10766
+ {
10767
+ className: "gap-x-2",
10768
+ onClick: () => insertRow(index, "above"),
10769
+ children: [
10770
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
10771
+ "Insert row above"
10772
+ ]
10773
+ }
10774
+ ),
10775
+ /* @__PURE__ */ jsxs(
10776
+ DropdownMenu.Item,
10777
+ {
10778
+ className: "gap-x-2",
10779
+ onClick: () => insertRow(index, "below"),
10780
+ children: [
10781
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
10782
+ "Insert row below"
10783
+ ]
10784
+ }
10785
+ ),
10786
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
10787
+ /* @__PURE__ */ jsxs(
10788
+ DropdownMenu.Item,
10789
+ {
10790
+ className: "gap-x-2",
10791
+ onClick: () => deleteRow(index),
10792
+ children: [
10793
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
10794
+ "Delete row"
10795
+ ]
10796
+ }
10797
+ )
10798
+ ] })
10799
+ ] })
10800
+ ] })
10801
+ },
10802
+ field.id
10803
+ );
10804
+ })
10805
+ ] }),
10806
+ 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." })
10613
10807
  ] }),
10614
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
10615
- DataTable,
10616
- {
10617
- data: variants,
10618
- columns,
10619
- isLoading: isPending,
10620
- getRowId: (row) => row.id,
10621
- rowCount: count,
10622
- prefix: VARIANT_PREFIX,
10623
- layout: "fill",
10624
- rowSelection: {
10625
- state: rowSelection,
10626
- onRowSelectionChange: setRowSelection,
10627
- enableRowSelection: (row) => {
10628
- return !items.find((i) => i.variant_id === row.original.id);
10629
- }
10630
- },
10631
- autoFocusSearch: true
10632
- }
10633
- ) }),
10634
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10635
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10636
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Update items" })
10808
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10809
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10810
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
10637
10811
  ] }) })
10638
10812
  ]
10639
10813
  }
10640
- );
10641
- };
10642
- const columnHelper = createDataTableColumnHelper();
10643
- const useColumns = () => {
10644
- return useMemo(() => {
10645
- return [
10646
- columnHelper.select(),
10647
- columnHelper.accessor("product.title", {
10648
- header: "Product",
10649
- cell: ({ row }) => {
10650
- var _a, _b, _c;
10651
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
10652
- /* @__PURE__ */ jsx(
10653
- Thumbnail,
10654
- {
10655
- thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
10656
- alt: (_b = row.original.product) == null ? void 0 : _b.title
10657
- }
10658
- ),
10659
- /* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
10660
- ] });
10661
- },
10662
- enableSorting: true
10663
- }),
10664
- columnHelper.accessor("title", {
10665
- header: "Variant",
10666
- enableSorting: true
10667
- }),
10668
- columnHelper.accessor("sku", {
10669
- header: "SKU",
10670
- cell: ({ getValue }) => {
10671
- return getValue() ?? "-";
10672
- },
10673
- enableSorting: true
10674
- }),
10675
- columnHelper.accessor("updated_at", {
10676
- header: "Updated",
10677
- cell: ({ getValue }) => {
10678
- return /* @__PURE__ */ jsx(
10679
- Tooltip,
10680
- {
10681
- content: getFullDate({ date: getValue(), includeTime: true }),
10682
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10683
- }
10684
- );
10685
- },
10686
- enableSorting: true,
10687
- sortAscLabel: "Oldest first",
10688
- sortDescLabel: "Newest first"
10689
- }),
10690
- columnHelper.accessor("created_at", {
10691
- header: "Created",
10692
- cell: ({ getValue }) => {
10693
- return /* @__PURE__ */ jsx(
10694
- Tooltip,
10695
- {
10696
- content: getFullDate({ date: getValue(), includeTime: true }),
10697
- children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
10698
- }
10699
- );
10700
- },
10701
- enableSorting: true,
10702
- sortAscLabel: "Oldest first",
10703
- sortDescLabel: "Newest first"
10704
- })
10705
- ];
10706
- }, []);
10814
+ ) });
10707
10815
  };
10708
- const CustomItemForm = ({ orderId, currencyCode }) => {
10709
- const { setIsOpen } = useStackedModal();
10710
- const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
10711
- const form = useForm({
10712
- defaultValues: {
10713
- title: "",
10714
- quantity: 1,
10715
- unit_price: ""
10716
- },
10717
- resolver: zodResolver(customItemSchema)
10718
- });
10719
- const onSubmit = form.handleSubmit(async (data) => {
10720
- await addItems(
10721
- {
10722
- items: [
10723
- {
10724
- title: data.title,
10725
- quantity: data.quantity,
10726
- unit_price: convertNumber(data.unit_price)
10727
- }
10728
- ]
10729
- },
10730
- {
10731
- onSuccess: () => {
10732
- setIsOpen(STACKED_MODAL_ID, false);
10733
- },
10734
- onError: (e) => {
10735
- toast.error(e.message);
10736
- }
10737
- }
10738
- );
10739
- });
10740
- return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
10741
- /* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
10742
- /* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-2 py-16", children: [
10743
- /* @__PURE__ */ jsxs("div", { children: [
10744
- /* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
10745
- /* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a custom item to the order. This will add a new line item that is not associated with an existing product." }) })
10746
- ] }),
10747
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10748
- /* @__PURE__ */ jsx(
10749
- Form$2.Field,
10750
- {
10751
- control: form.control,
10752
- name: "title",
10753
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10754
- /* @__PURE__ */ jsxs("div", { children: [
10755
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
10756
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
10757
- ] }),
10758
- /* @__PURE__ */ jsxs("div", { children: [
10759
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
10760
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10761
- ] })
10762
- ] }) })
10763
- }
10764
- ),
10765
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10766
- /* @__PURE__ */ jsx(
10767
- Form$2.Field,
10768
- {
10769
- control: form.control,
10770
- name: "unit_price",
10771
- render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10772
- /* @__PURE__ */ jsxs("div", { children: [
10773
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
10774
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
10775
- ] }),
10776
- /* @__PURE__ */ jsxs("div", { children: [
10777
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10778
- CurrencyInput,
10779
- {
10780
- symbol: getNativeSymbol(currencyCode),
10781
- code: currencyCode,
10782
- onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
10783
- ...field
10784
- }
10785
- ) }),
10786
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10787
- ] })
10788
- ] }) })
10789
- }
10790
- ),
10791
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10792
- /* @__PURE__ */ jsx(
10793
- Form$2.Field,
10794
- {
10795
- control: form.control,
10796
- name: "quantity",
10797
- render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
10798
- /* @__PURE__ */ jsxs("div", { children: [
10799
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
10800
- /* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
10801
- ] }),
10802
- /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
10803
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
10804
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
10805
- ] })
10806
- ] }) })
10807
- }
10816
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
10817
+ return /* @__PURE__ */ jsx(
10818
+ "input",
10819
+ {
10820
+ ref,
10821
+ ...props,
10822
+ autoComplete: "off",
10823
+ className: clx(
10824
+ "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",
10825
+ className
10808
10826
  )
10809
- ] }) }) }),
10810
- /* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10811
- /* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
10812
- /* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
10827
+ }
10828
+ );
10829
+ });
10830
+ GridInput.displayName = "MetadataForm.GridInput";
10831
+ const PlaceholderInner = () => {
10832
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
10833
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
10834
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
10835
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
10836
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
10813
10837
  ] }) })
10814
- ] }) }) });
10838
+ ] });
10815
10839
  };
10816
- const customItemSchema = objectType({
10817
- title: stringType().min(1),
10818
- quantity: numberType(),
10819
- unit_price: unionType([numberType(), stringType()])
10820
- });
10840
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
10841
+ function getDefaultValues(metadata) {
10842
+ if (!metadata || !Object.keys(metadata).length) {
10843
+ return [
10844
+ {
10845
+ key: "",
10846
+ value: "",
10847
+ disabled: false
10848
+ }
10849
+ ];
10850
+ }
10851
+ return Object.entries(metadata).map(([key, value]) => {
10852
+ if (!EDITABLE_TYPES.includes(typeof value)) {
10853
+ return {
10854
+ key,
10855
+ value,
10856
+ disabled: true
10857
+ };
10858
+ }
10859
+ let stringValue = value;
10860
+ if (typeof value !== "string") {
10861
+ stringValue = JSON.stringify(value);
10862
+ }
10863
+ return {
10864
+ key,
10865
+ value: stringValue,
10866
+ original_key: key
10867
+ };
10868
+ });
10869
+ }
10870
+ function parseValues(values) {
10871
+ const metadata = values.metadata;
10872
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
10873
+ if (isEmpty) {
10874
+ return null;
10875
+ }
10876
+ const update = {};
10877
+ metadata.forEach((field) => {
10878
+ let key = field.key;
10879
+ let value = field.value;
10880
+ const disabled = field.disabled;
10881
+ if (!key || !value) {
10882
+ return;
10883
+ }
10884
+ if (disabled) {
10885
+ update[key] = value;
10886
+ return;
10887
+ }
10888
+ key = key.trim();
10889
+ value = value.trim();
10890
+ if (value === "true") {
10891
+ update[key] = true;
10892
+ } else if (value === "false") {
10893
+ update[key] = false;
10894
+ } else {
10895
+ const parsedNumber = parseFloat(value);
10896
+ if (!isNaN(parsedNumber)) {
10897
+ update[key] = parsedNumber;
10898
+ } else {
10899
+ update[key] = value;
10900
+ }
10901
+ }
10902
+ });
10903
+ return update;
10904
+ }
10905
+ function getHasUneditableRows(metadata) {
10906
+ if (!metadata) {
10907
+ return false;
10908
+ }
10909
+ return Object.values(metadata).some(
10910
+ (value) => !EDITABLE_TYPES.includes(typeof value)
10911
+ );
10912
+ }
10821
10913
  const PROMOTION_QUERY_KEY = "promotions";
10822
10914
  const promotionsQueryKeys = {
10823
10915
  list: (query2) => [
@@ -10999,102 +11091,276 @@ const PromotionItem = ({
10999
11091
  const onRemove = async () => {
11000
11092
  removePromotions(
11001
11093
  {
11002
- promo_codes: [promotion.code]
11094
+ promo_codes: [promotion.code]
11095
+ },
11096
+ {
11097
+ onError: (e) => {
11098
+ toast.error(e.message);
11099
+ }
11100
+ }
11101
+ );
11102
+ };
11103
+ const displayValue = getDisplayValue(promotion);
11104
+ return /* @__PURE__ */ jsxs(
11105
+ "div",
11106
+ {
11107
+ className: clx(
11108
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11109
+ {
11110
+ "animate-pulse": isLoading
11111
+ }
11112
+ ),
11113
+ children: [
11114
+ /* @__PURE__ */ jsxs("div", { children: [
11115
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11116
+ /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11117
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11118
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11119
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11120
+ ] }),
11121
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11122
+ ] })
11123
+ ] }),
11124
+ /* @__PURE__ */ jsx(
11125
+ IconButton,
11126
+ {
11127
+ size: "small",
11128
+ type: "button",
11129
+ variant: "transparent",
11130
+ onClick: onRemove,
11131
+ isLoading: isPending || isLoading,
11132
+ children: /* @__PURE__ */ jsx(XMark, {})
11133
+ }
11134
+ )
11135
+ ]
11136
+ },
11137
+ promotion.id
11138
+ );
11139
+ };
11140
+ function getDisplayValue(promotion) {
11141
+ var _a, _b, _c, _d;
11142
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11143
+ if (!value) {
11144
+ return null;
11145
+ }
11146
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11147
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11148
+ if (!currency) {
11149
+ return null;
11150
+ }
11151
+ return getLocaleAmount(value, currency);
11152
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11153
+ return formatPercentage(value);
11154
+ }
11155
+ return null;
11156
+ }
11157
+ const formatter = new Intl.NumberFormat([], {
11158
+ style: "percent",
11159
+ minimumFractionDigits: 2
11160
+ });
11161
+ const formatPercentage = (value, isPercentageValue = false) => {
11162
+ let val = value || 0;
11163
+ if (!isPercentageValue) {
11164
+ val = val / 100;
11165
+ }
11166
+ return formatter.format(val);
11167
+ };
11168
+ function getPromotionIds(items, shippingMethods) {
11169
+ const promotionIds = /* @__PURE__ */ new Set();
11170
+ for (const item of items) {
11171
+ if (item.adjustments) {
11172
+ for (const adjustment of item.adjustments) {
11173
+ if (adjustment.promotion_id) {
11174
+ promotionIds.add(adjustment.promotion_id);
11175
+ }
11176
+ }
11177
+ }
11178
+ }
11179
+ for (const shippingMethod of shippingMethods) {
11180
+ if (shippingMethod.adjustments) {
11181
+ for (const adjustment of shippingMethod.adjustments) {
11182
+ if (adjustment.promotion_id) {
11183
+ promotionIds.add(adjustment.promotion_id);
11184
+ }
11185
+ }
11186
+ }
11187
+ }
11188
+ return Array.from(promotionIds);
11189
+ }
11190
+ const Email = () => {
11191
+ const { id } = useParams();
11192
+ const { order, isPending, isError, error } = useOrder(id, {
11193
+ fields: "+email"
11194
+ });
11195
+ if (isError) {
11196
+ throw error;
11197
+ }
11198
+ const isReady = !isPending && !!order;
11199
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11200
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11201
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
11202
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
11203
+ ] }),
11204
+ isReady && /* @__PURE__ */ jsx(EmailForm, { order })
11205
+ ] });
11206
+ };
11207
+ const EmailForm = ({ order }) => {
11208
+ const form = useForm({
11209
+ defaultValues: {
11210
+ email: order.email ?? ""
11211
+ },
11212
+ resolver: zodResolver(schema$4)
11213
+ });
11214
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11215
+ const { handleSuccess } = useRouteModal();
11216
+ const onSubmit = form.handleSubmit(async (data) => {
11217
+ await mutateAsync(
11218
+ { email: data.email },
11219
+ {
11220
+ onSuccess: () => {
11221
+ handleSuccess();
11222
+ },
11223
+ onError: (error) => {
11224
+ toast.error(error.message);
11225
+ }
11226
+ }
11227
+ );
11228
+ });
11229
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11230
+ KeyboundForm,
11231
+ {
11232
+ className: "flex flex-1 flex-col overflow-hidden",
11233
+ onSubmit,
11234
+ children: [
11235
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
11236
+ Form$2.Field,
11237
+ {
11238
+ control: form.control,
11239
+ name: "email",
11240
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11241
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
11242
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
11243
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11244
+ ] })
11245
+ }
11246
+ ) }),
11247
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11248
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11249
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11250
+ ] }) })
11251
+ ]
11252
+ }
11253
+ ) });
11254
+ };
11255
+ const schema$4 = objectType({
11256
+ email: stringType().email()
11257
+ });
11258
+ const SalesChannel = () => {
11259
+ const { id } = useParams();
11260
+ const { draft_order, isPending, isError, error } = useDraftOrder(
11261
+ id,
11262
+ {
11263
+ fields: "+sales_channel_id"
11264
+ },
11265
+ {
11266
+ enabled: !!id
11267
+ }
11268
+ );
11269
+ if (isError) {
11270
+ throw error;
11271
+ }
11272
+ const ISrEADY = !!draft_order && !isPending;
11273
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11274
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11275
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
11276
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
11277
+ ] }),
11278
+ ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
11279
+ ] });
11280
+ };
11281
+ const SalesChannelForm = ({ order }) => {
11282
+ const form = useForm({
11283
+ defaultValues: {
11284
+ sales_channel_id: order.sales_channel_id || ""
11285
+ },
11286
+ resolver: zodResolver(schema$3)
11287
+ });
11288
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11289
+ const { handleSuccess } = useRouteModal();
11290
+ const onSubmit = form.handleSubmit(async (data) => {
11291
+ await mutateAsync(
11292
+ {
11293
+ sales_channel_id: data.sales_channel_id
11003
11294
  },
11004
11295
  {
11005
- onError: (e) => {
11006
- toast.error(e.message);
11296
+ onSuccess: () => {
11297
+ toast.success("Sales channel updated");
11298
+ handleSuccess();
11299
+ },
11300
+ onError: (error) => {
11301
+ toast.error(error.message);
11007
11302
  }
11008
11303
  }
11009
11304
  );
11010
- };
11011
- const displayValue = getDisplayValue(promotion);
11012
- return /* @__PURE__ */ jsxs(
11013
- "div",
11305
+ });
11306
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11307
+ KeyboundForm,
11014
11308
  {
11015
- className: clx(
11016
- "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11017
- {
11018
- "animate-pulse": isLoading
11019
- }
11020
- ),
11309
+ className: "flex flex-1 flex-col overflow-hidden",
11310
+ onSubmit,
11021
11311
  children: [
11022
- /* @__PURE__ */ jsxs("div", { children: [
11023
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11024
- /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11025
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11026
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11027
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11028
- ] }),
11029
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11030
- ] })
11031
- ] }),
11032
- /* @__PURE__ */ jsx(
11033
- IconButton,
11034
- {
11035
- size: "small",
11036
- type: "button",
11037
- variant: "transparent",
11038
- onClick: onRemove,
11039
- isLoading: isPending || isLoading,
11040
- children: /* @__PURE__ */ jsx(XMark, {})
11041
- }
11042
- )
11312
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
11313
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11314
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11315
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11316
+ ] }) })
11043
11317
  ]
11044
- },
11045
- promotion.id
11046
- );
11047
- };
11048
- function getDisplayValue(promotion) {
11049
- var _a, _b, _c, _d;
11050
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11051
- if (!value) {
11052
- return null;
11053
- }
11054
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11055
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11056
- if (!currency) {
11057
- return null;
11058
11318
  }
11059
- return getLocaleAmount(value, currency);
11060
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11061
- return formatPercentage(value);
11062
- }
11063
- return null;
11064
- }
11065
- const formatter = new Intl.NumberFormat([], {
11066
- style: "percent",
11067
- minimumFractionDigits: 2
11068
- });
11069
- const formatPercentage = (value, isPercentageValue = false) => {
11070
- let val = value || 0;
11071
- if (!isPercentageValue) {
11072
- val = val / 100;
11073
- }
11074
- return formatter.format(val);
11319
+ ) });
11075
11320
  };
11076
- function getPromotionIds(items, shippingMethods) {
11077
- const promotionIds = /* @__PURE__ */ new Set();
11078
- for (const item of items) {
11079
- if (item.adjustments) {
11080
- for (const adjustment of item.adjustments) {
11081
- if (adjustment.promotion_id) {
11082
- promotionIds.add(adjustment.promotion_id);
11083
- }
11084
- }
11085
- }
11086
- }
11087
- for (const shippingMethod of shippingMethods) {
11088
- if (shippingMethod.adjustments) {
11089
- for (const adjustment of shippingMethod.adjustments) {
11090
- if (adjustment.promotion_id) {
11091
- promotionIds.add(adjustment.promotion_id);
11092
- }
11321
+ const SalesChannelField = ({ control, order }) => {
11322
+ const salesChannels = useComboboxData({
11323
+ queryFn: async (params) => {
11324
+ return await sdk.admin.salesChannel.list(params);
11325
+ },
11326
+ queryKey: ["sales-channels"],
11327
+ getOptions: (data) => {
11328
+ return data.sales_channels.map((salesChannel) => ({
11329
+ label: salesChannel.name,
11330
+ value: salesChannel.id
11331
+ }));
11332
+ },
11333
+ defaultValue: order.sales_channel_id || void 0
11334
+ });
11335
+ return /* @__PURE__ */ jsx(
11336
+ Form$2.Field,
11337
+ {
11338
+ control,
11339
+ name: "sales_channel_id",
11340
+ render: ({ field }) => {
11341
+ return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11342
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
11343
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11344
+ Combobox,
11345
+ {
11346
+ options: salesChannels.options,
11347
+ fetchNextPage: salesChannels.fetchNextPage,
11348
+ isFetchingNextPage: salesChannels.isFetchingNextPage,
11349
+ searchValue: salesChannels.searchValue,
11350
+ onSearchValueChange: salesChannels.onSearchValueChange,
11351
+ placeholder: "Select sales channel",
11352
+ ...field
11353
+ }
11354
+ ) }),
11355
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
11356
+ ] });
11093
11357
  }
11094
11358
  }
11095
- }
11096
- return Array.from(promotionIds);
11097
- }
11359
+ );
11360
+ };
11361
+ const schema$3 = objectType({
11362
+ sales_channel_id: stringType().min(1)
11363
+ });
11098
11364
  const STACKED_FOCUS_MODAL_ID = "shipping-form";
11099
11365
  const Shipping = () => {
11100
11366
  var _a;
@@ -11889,125 +12155,19 @@ const CustomAmountField = ({
11889
12155
  /* @__PURE__ */ jsx(Form$2.Hint, { children: "Set a custom amount for the shipping option." })
11890
12156
  ] }),
11891
12157
  /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11892
- CurrencyInput,
11893
- {
11894
- ...field,
11895
- onValueChange: (value) => onChange(value),
11896
- symbol: getNativeSymbol(currencyCode),
11897
- code: currencyCode
11898
- }
11899
- ) })
11900
- ] });
11901
- }
11902
- }
11903
- );
11904
- };
11905
- const SalesChannel = () => {
11906
- const { id } = useParams();
11907
- const { draft_order, isPending, isError, error } = useDraftOrder(
11908
- id,
11909
- {
11910
- fields: "+sales_channel_id"
11911
- },
11912
- {
11913
- enabled: !!id
11914
- }
11915
- );
11916
- if (isError) {
11917
- throw error;
11918
- }
11919
- const ISrEADY = !!draft_order && !isPending;
11920
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11921
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11922
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Sales Channel" }) }),
11923
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Update which sales channel the draft order is associated with" }) })
11924
- ] }),
11925
- ISrEADY && /* @__PURE__ */ jsx(SalesChannelForm, { order: draft_order })
11926
- ] });
11927
- };
11928
- const SalesChannelForm = ({ order }) => {
11929
- const form = useForm({
11930
- defaultValues: {
11931
- sales_channel_id: order.sales_channel_id || ""
11932
- },
11933
- resolver: zodResolver(schema$2)
11934
- });
11935
- const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11936
- const { handleSuccess } = useRouteModal();
11937
- const onSubmit = form.handleSubmit(async (data) => {
11938
- await mutateAsync(
11939
- {
11940
- sales_channel_id: data.sales_channel_id
11941
- },
11942
- {
11943
- onSuccess: () => {
11944
- toast.success("Sales channel updated");
11945
- handleSuccess();
11946
- },
11947
- onError: (error) => {
11948
- toast.error(error.message);
11949
- }
11950
- }
11951
- );
11952
- });
11953
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11954
- KeyboundForm,
11955
- {
11956
- className: "flex flex-1 flex-col overflow-hidden",
11957
- onSubmit,
11958
- children: [
11959
- /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(SalesChannelField, { control: form.control, order }) }),
11960
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11961
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11962
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11963
- ] }) })
11964
- ]
11965
- }
11966
- ) });
11967
- };
11968
- const SalesChannelField = ({ control, order }) => {
11969
- const salesChannels = useComboboxData({
11970
- queryFn: async (params) => {
11971
- return await sdk.admin.salesChannel.list(params);
11972
- },
11973
- queryKey: ["sales-channels"],
11974
- getOptions: (data) => {
11975
- return data.sales_channels.map((salesChannel) => ({
11976
- label: salesChannel.name,
11977
- value: salesChannel.id
11978
- }));
11979
- },
11980
- defaultValue: order.sales_channel_id || void 0
11981
- });
11982
- return /* @__PURE__ */ jsx(
11983
- Form$2.Field,
11984
- {
11985
- control,
11986
- name: "sales_channel_id",
11987
- render: ({ field }) => {
11988
- return /* @__PURE__ */ jsxs(Form$2.Item, { children: [
11989
- /* @__PURE__ */ jsx(Form$2.Label, { children: "Sales Channel" }),
11990
- /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11991
- Combobox,
12158
+ CurrencyInput,
11992
12159
  {
11993
- options: salesChannels.options,
11994
- fetchNextPage: salesChannels.fetchNextPage,
11995
- isFetchingNextPage: salesChannels.isFetchingNextPage,
11996
- searchValue: salesChannels.searchValue,
11997
- onSearchValueChange: salesChannels.onSearchValueChange,
11998
- placeholder: "Select sales channel",
11999
- ...field
12160
+ ...field,
12161
+ onValueChange: (value) => onChange(value),
12162
+ symbol: getNativeSymbol(currencyCode),
12163
+ code: currencyCode
12000
12164
  }
12001
- ) }),
12002
- /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12165
+ ) })
12003
12166
  ] });
12004
12167
  }
12005
12168
  }
12006
12169
  );
12007
12170
  };
12008
- const schema$2 = objectType({
12009
- sales_channel_id: stringType().min(1)
12010
- });
12011
12171
  const ShippingAddress = () => {
12012
12172
  const { id } = useParams();
12013
12173
  const { order, isPending, isError, error } = useOrder(id, {
@@ -12040,7 +12200,7 @@ const ShippingAddressForm = ({ order }) => {
12040
12200
  postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12041
12201
  phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12042
12202
  },
12043
- resolver: zodResolver(schema$1)
12203
+ resolver: zodResolver(schema$2)
12044
12204
  });
12045
12205
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12046
12206
  const { handleSuccess } = useRouteModal();
@@ -12210,7 +12370,7 @@ const ShippingAddressForm = ({ order }) => {
12210
12370
  }
12211
12371
  ) });
12212
12372
  };
12213
- const schema$1 = addressSchema;
12373
+ const schema$2 = addressSchema;
12214
12374
  const TransferOwnership = () => {
12215
12375
  const { id } = useParams();
12216
12376
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -12234,7 +12394,7 @@ const TransferOwnershipForm = ({ order }) => {
12234
12394
  defaultValues: {
12235
12395
  customer_id: order.customer_id || ""
12236
12396
  },
12237
- resolver: zodResolver(schema)
12397
+ resolver: zodResolver(schema$1)
12238
12398
  });
12239
12399
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12240
12400
  const { handleSuccess } = useRouteModal();
@@ -12684,57 +12844,13 @@ const Illustration = () => {
12684
12844
  }
12685
12845
  );
12686
12846
  };
12687
- const schema = objectType({
12847
+ const schema$1 = objectType({
12688
12848
  customer_id: stringType().min(1)
12689
12849
  });
12690
- const InlineTip = forwardRef(
12691
- ({ variant = "tip", label, className, children, ...props }, ref) => {
12692
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
12693
- return /* @__PURE__ */ jsxs(
12694
- "div",
12695
- {
12696
- ref,
12697
- className: clx(
12698
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
12699
- className
12700
- ),
12701
- ...props,
12702
- children: [
12703
- /* @__PURE__ */ jsx(
12704
- "div",
12705
- {
12706
- role: "presentation",
12707
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
12708
- "bg-ui-tag-orange-icon": variant === "warning"
12709
- })
12710
- }
12711
- ),
12712
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
12713
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
12714
- labelValue,
12715
- ":"
12716
- ] }),
12717
- " ",
12718
- children
12719
- ] })
12720
- ]
12721
- }
12722
- );
12723
- }
12724
- );
12725
- InlineTip.displayName = "InlineTip";
12726
- const MetadataFieldSchema = objectType({
12727
- key: stringType(),
12728
- disabled: booleanType().optional(),
12729
- value: anyType()
12730
- });
12731
- const MetadataSchema = objectType({
12732
- metadata: arrayType(MetadataFieldSchema)
12733
- });
12734
- const Metadata = () => {
12850
+ const BillingAddress = () => {
12735
12851
  const { id } = useParams();
12736
12852
  const { order, isPending, isError, error } = useOrder(id, {
12737
- fields: "metadata"
12853
+ fields: "+billing_address"
12738
12854
  });
12739
12855
  if (isError) {
12740
12856
  throw error;
@@ -12742,33 +12858,36 @@ const Metadata = () => {
12742
12858
  const isReady = !isPending && !!order;
12743
12859
  return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12744
12860
  /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12745
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
12746
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
12861
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Billing Address" }) }),
12862
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the billing address for the draft order" }) })
12747
12863
  ] }),
12748
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
12864
+ isReady && /* @__PURE__ */ jsx(BillingAddressForm, { order })
12749
12865
  ] });
12750
12866
  };
12751
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
12752
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
12753
- const MetadataForm = ({ orderId, metadata }) => {
12754
- const { handleSuccess } = useRouteModal();
12755
- const hasUneditableRows = getHasUneditableRows(metadata);
12756
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
12867
+ const BillingAddressForm = ({ order }) => {
12868
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
12757
12869
  const form = useForm({
12758
12870
  defaultValues: {
12759
- metadata: getDefaultValues(metadata)
12871
+ first_name: ((_a = order.billing_address) == null ? void 0 : _a.first_name) ?? "",
12872
+ last_name: ((_b = order.billing_address) == null ? void 0 : _b.last_name) ?? "",
12873
+ company: ((_c = order.billing_address) == null ? void 0 : _c.company) ?? "",
12874
+ address_1: ((_d = order.billing_address) == null ? void 0 : _d.address_1) ?? "",
12875
+ address_2: ((_e = order.billing_address) == null ? void 0 : _e.address_2) ?? "",
12876
+ city: ((_f = order.billing_address) == null ? void 0 : _f.city) ?? "",
12877
+ province: ((_g = order.billing_address) == null ? void 0 : _g.province) ?? "",
12878
+ country_code: ((_h = order.billing_address) == null ? void 0 : _h.country_code) ?? "",
12879
+ postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
12880
+ phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
12760
12881
  },
12761
- resolver: zodResolver(MetadataSchema)
12882
+ resolver: zodResolver(schema)
12762
12883
  });
12763
- const handleSubmit = form.handleSubmit(async (data) => {
12764
- const parsedData = parseValues(data);
12884
+ const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12885
+ const { handleSuccess } = useRouteModal();
12886
+ const onSubmit = form.handleSubmit(async (data) => {
12765
12887
  await mutateAsync(
12766
- {
12767
- metadata: parsedData
12768
- },
12888
+ { billing_address: data },
12769
12889
  {
12770
12890
  onSuccess: () => {
12771
- toast.success("Metadata updated");
12772
12891
  handleSuccess();
12773
12892
  },
12774
12893
  onError: (error) => {
@@ -12777,266 +12896,147 @@ const MetadataForm = ({ orderId, metadata }) => {
12777
12896
  }
12778
12897
  );
12779
12898
  });
12780
- const { fields, insert, remove } = useFieldArray({
12781
- control: form.control,
12782
- name: "metadata"
12783
- });
12784
- function deleteRow(index) {
12785
- remove(index);
12786
- if (fields.length === 1) {
12787
- insert(0, {
12788
- key: "",
12789
- value: "",
12790
- disabled: false
12791
- });
12792
- }
12793
- }
12794
- function insertRow(index, position) {
12795
- insert(index + (position === "above" ? 0 : 1), {
12796
- key: "",
12797
- value: "",
12798
- disabled: false
12799
- });
12800
- }
12801
12899
  return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12802
12900
  KeyboundForm,
12803
- {
12804
- onSubmit: handleSubmit,
12805
- className: "flex flex-1 flex-col overflow-hidden",
12806
- children: [
12807
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
12808
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
12809
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
12810
- /* @__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" }) }),
12811
- /* @__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" }) })
12812
- ] }),
12813
- fields.map((field, index) => {
12814
- const isDisabled = field.disabled || false;
12815
- let placeholder = "-";
12816
- if (typeof field.value === "object") {
12817
- placeholder = "{ ... }";
12818
- }
12819
- if (Array.isArray(field.value)) {
12820
- placeholder = "[ ... ]";
12821
- }
12822
- return /* @__PURE__ */ jsx(
12823
- ConditionalTooltip,
12824
- {
12825
- showTooltip: isDisabled,
12826
- content: "This row is disabled because it contains non-primitive data.",
12827
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
12828
- /* @__PURE__ */ jsxs(
12829
- "div",
12830
- {
12831
- className: clx("grid grid-cols-2 divide-x", {
12832
- "overflow-hidden rounded-b-lg": index === fields.length - 1
12833
- }),
12834
- children: [
12835
- /* @__PURE__ */ jsx(
12836
- Form$2.Field,
12837
- {
12838
- control: form.control,
12839
- name: `metadata.${index}.key`,
12840
- render: ({ field: field2 }) => {
12841
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12842
- GridInput,
12843
- {
12844
- "aria-labelledby": METADATA_KEY_LABEL_ID,
12845
- ...field2,
12846
- disabled: isDisabled,
12847
- placeholder: "Key"
12848
- }
12849
- ) }) });
12850
- }
12851
- }
12852
- ),
12853
- /* @__PURE__ */ jsx(
12854
- Form$2.Field,
12855
- {
12856
- control: form.control,
12857
- name: `metadata.${index}.value`,
12858
- render: ({ field: { value, ...field2 } }) => {
12859
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12860
- GridInput,
12861
- {
12862
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
12863
- ...field2,
12864
- value: isDisabled ? placeholder : value,
12865
- disabled: isDisabled,
12866
- placeholder: "Value"
12867
- }
12868
- ) }) });
12869
- }
12870
- }
12871
- )
12872
- ]
12873
- }
12874
- ),
12875
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
12876
- /* @__PURE__ */ jsx(
12877
- DropdownMenu.Trigger,
12878
- {
12879
- className: clx(
12880
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
12881
- {
12882
- hidden: isDisabled
12883
- }
12884
- ),
12885
- disabled: isDisabled,
12886
- asChild: true,
12887
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
12888
- }
12889
- ),
12890
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
12891
- /* @__PURE__ */ jsxs(
12892
- DropdownMenu.Item,
12893
- {
12894
- className: "gap-x-2",
12895
- onClick: () => insertRow(index, "above"),
12896
- children: [
12897
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
12898
- "Insert row above"
12899
- ]
12900
- }
12901
- ),
12902
- /* @__PURE__ */ jsxs(
12903
- DropdownMenu.Item,
12904
- {
12905
- className: "gap-x-2",
12906
- onClick: () => insertRow(index, "below"),
12907
- children: [
12908
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
12909
- "Insert row below"
12910
- ]
12911
- }
12912
- ),
12913
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
12914
- /* @__PURE__ */ jsxs(
12915
- DropdownMenu.Item,
12916
- {
12917
- className: "gap-x-2",
12918
- onClick: () => deleteRow(index),
12919
- children: [
12920
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
12921
- "Delete row"
12922
- ]
12923
- }
12924
- )
12925
- ] })
12926
- ] })
12927
- ] })
12928
- },
12929
- field.id
12930
- );
12931
- })
12901
+ {
12902
+ className: "flex flex-1 flex-col overflow-hidden",
12903
+ onSubmit,
12904
+ children: [
12905
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
12906
+ /* @__PURE__ */ jsx(
12907
+ Form$2.Field,
12908
+ {
12909
+ control: form.control,
12910
+ name: "country_code",
12911
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12912
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Country" }),
12913
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(CountrySelect, { ...field }) }),
12914
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12915
+ ] })
12916
+ }
12917
+ ),
12918
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12919
+ /* @__PURE__ */ jsx(
12920
+ Form$2.Field,
12921
+ {
12922
+ control: form.control,
12923
+ name: "first_name",
12924
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12925
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "First name" }),
12926
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12927
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12928
+ ] })
12929
+ }
12930
+ ),
12931
+ /* @__PURE__ */ jsx(
12932
+ Form$2.Field,
12933
+ {
12934
+ control: form.control,
12935
+ name: "last_name",
12936
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12937
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Last name" }),
12938
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12939
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12940
+ ] })
12941
+ }
12942
+ )
12932
12943
  ] }),
12933
- 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." })
12934
- ] }),
12935
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12936
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12944
+ /* @__PURE__ */ jsx(
12945
+ Form$2.Field,
12946
+ {
12947
+ control: form.control,
12948
+ name: "company",
12949
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12950
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Company" }),
12951
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12952
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12953
+ ] })
12954
+ }
12955
+ ),
12956
+ /* @__PURE__ */ jsx(
12957
+ Form$2.Field,
12958
+ {
12959
+ control: form.control,
12960
+ name: "address_1",
12961
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12962
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Address" }),
12963
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12964
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12965
+ ] })
12966
+ }
12967
+ ),
12968
+ /* @__PURE__ */ jsx(
12969
+ Form$2.Field,
12970
+ {
12971
+ control: form.control,
12972
+ name: "address_2",
12973
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12974
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Apartment, suite, etc." }),
12975
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12976
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12977
+ ] })
12978
+ }
12979
+ ),
12980
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
12981
+ /* @__PURE__ */ jsx(
12982
+ Form$2.Field,
12983
+ {
12984
+ control: form.control,
12985
+ name: "postal_code",
12986
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12987
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "Postal code" }),
12988
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
12989
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
12990
+ ] })
12991
+ }
12992
+ ),
12993
+ /* @__PURE__ */ jsx(
12994
+ Form$2.Field,
12995
+ {
12996
+ control: form.control,
12997
+ name: "city",
12998
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
12999
+ /* @__PURE__ */ jsx(Form$2.Label, { children: "City" }),
13000
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13001
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13002
+ ] })
13003
+ }
13004
+ )
13005
+ ] }),
13006
+ /* @__PURE__ */ jsx(
13007
+ Form$2.Field,
13008
+ {
13009
+ control: form.control,
13010
+ name: "province",
13011
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13012
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Province / State" }),
13013
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13014
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13015
+ ] })
13016
+ }
13017
+ ),
13018
+ /* @__PURE__ */ jsx(
13019
+ Form$2.Field,
13020
+ {
13021
+ control: form.control,
13022
+ name: "phone",
13023
+ render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
13024
+ /* @__PURE__ */ jsx(Form$2.Label, { optional: true, children: "Phone" }),
13025
+ /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
13026
+ /* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
13027
+ ] })
13028
+ }
13029
+ )
13030
+ ] }) }),
13031
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13032
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
12937
13033
  /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
12938
13034
  ] }) })
12939
13035
  ]
12940
13036
  }
12941
13037
  ) });
12942
13038
  };
12943
- const GridInput = forwardRef(({ className, ...props }, ref) => {
12944
- return /* @__PURE__ */ jsx(
12945
- "input",
12946
- {
12947
- ref,
12948
- ...props,
12949
- autoComplete: "off",
12950
- className: clx(
12951
- "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",
12952
- className
12953
- )
12954
- }
12955
- );
12956
- });
12957
- GridInput.displayName = "MetadataForm.GridInput";
12958
- const PlaceholderInner = () => {
12959
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
12960
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
12961
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12962
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
12963
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
12964
- ] }) })
12965
- ] });
12966
- };
12967
- const EDITABLE_TYPES = ["string", "number", "boolean"];
12968
- function getDefaultValues(metadata) {
12969
- if (!metadata || !Object.keys(metadata).length) {
12970
- return [
12971
- {
12972
- key: "",
12973
- value: "",
12974
- disabled: false
12975
- }
12976
- ];
12977
- }
12978
- return Object.entries(metadata).map(([key, value]) => {
12979
- if (!EDITABLE_TYPES.includes(typeof value)) {
12980
- return {
12981
- key,
12982
- value,
12983
- disabled: true
12984
- };
12985
- }
12986
- let stringValue = value;
12987
- if (typeof value !== "string") {
12988
- stringValue = JSON.stringify(value);
12989
- }
12990
- return {
12991
- key,
12992
- value: stringValue,
12993
- original_key: key
12994
- };
12995
- });
12996
- }
12997
- function parseValues(values) {
12998
- const metadata = values.metadata;
12999
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
13000
- if (isEmpty) {
13001
- return null;
13002
- }
13003
- const update = {};
13004
- metadata.forEach((field) => {
13005
- let key = field.key;
13006
- let value = field.value;
13007
- const disabled = field.disabled;
13008
- if (!key || !value) {
13009
- return;
13010
- }
13011
- if (disabled) {
13012
- update[key] = value;
13013
- return;
13014
- }
13015
- key = key.trim();
13016
- value = value.trim();
13017
- if (value === "true") {
13018
- update[key] = true;
13019
- } else if (value === "false") {
13020
- update[key] = false;
13021
- } else {
13022
- const parsedNumber = parseFloat(value);
13023
- if (!isNaN(parsedNumber)) {
13024
- update[key] = parsedNumber;
13025
- } else {
13026
- update[key] = value;
13027
- }
13028
- }
13029
- });
13030
- return update;
13031
- }
13032
- function getHasUneditableRows(metadata) {
13033
- if (!metadata) {
13034
- return false;
13035
- }
13036
- return Object.values(metadata).some(
13037
- (value) => !EDITABLE_TYPES.includes(typeof value)
13038
- );
13039
- }
13039
+ const schema = addressSchema;
13040
13040
  const widgetModule = { widgets: [] };
13041
13041
  const routeModule = {
13042
13042
  routes: [
@@ -13061,30 +13061,30 @@ const routeModule = {
13061
13061
  Component: CustomItems,
13062
13062
  path: "/draft-orders/:id/custom-items"
13063
13063
  },
13064
- {
13065
- Component: Email,
13066
- path: "/draft-orders/:id/email"
13067
- },
13068
- {
13069
- Component: BillingAddress,
13070
- path: "/draft-orders/:id/billing-address"
13071
- },
13072
13064
  {
13073
13065
  Component: Items,
13074
13066
  path: "/draft-orders/:id/items"
13075
13067
  },
13068
+ {
13069
+ Component: Metadata,
13070
+ path: "/draft-orders/:id/metadata"
13071
+ },
13076
13072
  {
13077
13073
  Component: Promotions,
13078
13074
  path: "/draft-orders/:id/promotions"
13079
13075
  },
13080
13076
  {
13081
- Component: Shipping,
13082
- path: "/draft-orders/:id/shipping"
13077
+ Component: Email,
13078
+ path: "/draft-orders/:id/email"
13083
13079
  },
13084
13080
  {
13085
13081
  Component: SalesChannel,
13086
13082
  path: "/draft-orders/:id/sales-channel"
13087
13083
  },
13084
+ {
13085
+ Component: Shipping,
13086
+ path: "/draft-orders/:id/shipping"
13087
+ },
13088
13088
  {
13089
13089
  Component: ShippingAddress,
13090
13090
  path: "/draft-orders/:id/shipping-address"
@@ -13094,8 +13094,8 @@ const routeModule = {
13094
13094
  path: "/draft-orders/:id/transfer-ownership"
13095
13095
  },
13096
13096
  {
13097
- Component: Metadata,
13098
- path: "/draft-orders/:id/metadata"
13097
+ Component: BillingAddress,
13098
+ path: "/draft-orders/:id/billing-address"
13099
13099
  }
13100
13100
  ]
13101
13101
  }