@medusajs/draft-order 2.10.4-preview-20251005060154 → 2.10.4-preview-20251005090149

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.
@@ -9757,6 +9757,27 @@ const BillingAddressForm = ({ order }) => {
9757
9757
  ) });
9758
9758
  };
9759
9759
  const schema$5 = addressSchema;
9760
+ const CustomItems = () => {
9761
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
9762
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
9763
+ /* @__PURE__ */ jsx(CustomItemsForm, {})
9764
+ ] });
9765
+ };
9766
+ const CustomItemsForm = () => {
9767
+ const form = useForm({
9768
+ resolver: zodResolver(schema$4)
9769
+ });
9770
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
9771
+ /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
9772
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
9773
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
9774
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
9775
+ ] }) })
9776
+ ] }) });
9777
+ };
9778
+ const schema$4 = objectType({
9779
+ email: stringType().email()
9780
+ });
9760
9781
  const Email = () => {
9761
9782
  const { id } = useParams();
9762
9783
  const { order, isPending, isError, error } = useOrder(id, {
@@ -9779,7 +9800,7 @@ const EmailForm = ({ order }) => {
9779
9800
  defaultValues: {
9780
9801
  email: order.email ?? ""
9781
9802
  },
9782
- resolver: zodResolver(schema$4)
9803
+ resolver: zodResolver(schema$3)
9783
9804
  });
9784
9805
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
9785
9806
  const { handleSuccess } = useRouteModal();
@@ -9822,7 +9843,7 @@ const EmailForm = ({ order }) => {
9822
9843
  }
9823
9844
  ) });
9824
9845
  };
9825
- const schema$4 = objectType({
9846
+ const schema$3 = objectType({
9826
9847
  email: stringType().email()
9827
9848
  });
9828
9849
  const NumberInput = forwardRef(
@@ -10799,478 +10820,128 @@ const customItemSchema = objectType({
10799
10820
  quantity: numberType(),
10800
10821
  unit_price: unionType([numberType(), stringType()])
10801
10822
  });
10802
- const InlineTip = forwardRef(
10803
- ({ variant = "tip", label, className, children, ...props }, ref) => {
10804
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10805
- return /* @__PURE__ */ jsxs(
10806
- "div",
10807
- {
10808
- ref,
10809
- className: clx(
10810
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10811
- className
10812
- ),
10813
- ...props,
10814
- children: [
10815
- /* @__PURE__ */ jsx(
10816
- "div",
10817
- {
10818
- role: "presentation",
10819
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10820
- "bg-ui-tag-orange-icon": variant === "warning"
10821
- })
10822
- }
10823
- ),
10824
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10825
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10826
- labelValue,
10827
- ":"
10828
- ] }),
10829
- " ",
10830
- children
10831
- ] })
10832
- ]
10833
- }
10834
- );
10835
- }
10836
- );
10837
- InlineTip.displayName = "InlineTip";
10838
- const MetadataFieldSchema = objectType({
10839
- key: stringType(),
10840
- disabled: booleanType().optional(),
10841
- value: anyType()
10842
- });
10843
- const MetadataSchema = objectType({
10844
- metadata: arrayType(MetadataFieldSchema)
10845
- });
10846
- const Metadata = () => {
10847
- const { id } = useParams();
10848
- const { order, isPending, isError, error } = useOrder(id, {
10849
- fields: "metadata"
10823
+ const PROMOTION_QUERY_KEY = "promotions";
10824
+ const promotionsQueryKeys = {
10825
+ list: (query2) => [
10826
+ PROMOTION_QUERY_KEY,
10827
+ query2 ? query2 : void 0
10828
+ ],
10829
+ detail: (id, query2) => [
10830
+ PROMOTION_QUERY_KEY,
10831
+ id,
10832
+ query2 ? query2 : void 0
10833
+ ]
10834
+ };
10835
+ const usePromotions = (query2, options) => {
10836
+ const { data, ...rest } = useQuery({
10837
+ queryKey: promotionsQueryKeys.list(query2),
10838
+ queryFn: async () => sdk.admin.promotion.list(query2),
10839
+ ...options
10850
10840
  });
10851
- if (isError) {
10852
- throw error;
10841
+ return { ...data, ...rest };
10842
+ };
10843
+ const Promotions = () => {
10844
+ const { id } = useParams();
10845
+ const {
10846
+ order: preview,
10847
+ isError: isPreviewError,
10848
+ error: previewError
10849
+ } = useOrderPreview(id, void 0);
10850
+ useInitiateOrderEdit({ preview });
10851
+ const { onCancel } = useCancelOrderEdit({ preview });
10852
+ if (isPreviewError) {
10853
+ throw previewError;
10853
10854
  }
10854
- const isReady = !isPending && !!order;
10855
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10856
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10857
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10858
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10859
- ] }),
10860
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10855
+ const isReady = !!preview;
10856
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10857
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10858
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10861
10859
  ] });
10862
10860
  };
10863
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10864
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10865
- const MetadataForm = ({ orderId, metadata }) => {
10861
+ const PromotionForm = ({ preview }) => {
10862
+ const { items, shipping_methods } = preview;
10863
+ const [isSubmitting, setIsSubmitting] = useState(false);
10864
+ const [comboboxValue, setComboboxValue] = useState("");
10866
10865
  const { handleSuccess } = useRouteModal();
10867
- const hasUneditableRows = getHasUneditableRows(metadata);
10868
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10869
- const form = useForm({
10870
- defaultValues: {
10871
- metadata: getDefaultValues(metadata)
10866
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10867
+ const promoIds = getPromotionIds(items, shipping_methods);
10868
+ const { promotions, isPending, isError, error } = usePromotions(
10869
+ {
10870
+ id: promoIds
10872
10871
  },
10873
- resolver: zodResolver(MetadataSchema)
10872
+ {
10873
+ enabled: !!promoIds.length
10874
+ }
10875
+ );
10876
+ const comboboxData = useComboboxData({
10877
+ queryKey: ["promotions", "combobox", promoIds],
10878
+ queryFn: async (params) => {
10879
+ return await sdk.admin.promotion.list({
10880
+ ...params,
10881
+ id: {
10882
+ $nin: promoIds
10883
+ }
10884
+ });
10885
+ },
10886
+ getOptions: (data) => {
10887
+ return data.promotions.map((promotion) => ({
10888
+ label: promotion.code,
10889
+ value: promotion.code
10890
+ }));
10891
+ }
10874
10892
  });
10875
- const handleSubmit = form.handleSubmit(async (data) => {
10876
- const parsedData = parseValues(data);
10877
- await mutateAsync(
10893
+ const add = async (value) => {
10894
+ if (!value) {
10895
+ return;
10896
+ }
10897
+ addPromotions(
10878
10898
  {
10879
- metadata: parsedData
10899
+ promo_codes: [value]
10880
10900
  },
10881
10901
  {
10882
- onSuccess: () => {
10883
- toast.success("Metadata updated");
10884
- handleSuccess();
10902
+ onError: (e) => {
10903
+ toast.error(e.message);
10904
+ comboboxData.onSearchValueChange("");
10905
+ setComboboxValue("");
10885
10906
  },
10886
- onError: (error) => {
10887
- toast.error(error.message);
10907
+ onSuccess: () => {
10908
+ comboboxData.onSearchValueChange("");
10909
+ setComboboxValue("");
10888
10910
  }
10889
10911
  }
10890
10912
  );
10891
- });
10892
- const { fields, insert, remove } = useFieldArray({
10893
- control: form.control,
10894
- name: "metadata"
10895
- });
10896
- function deleteRow(index) {
10897
- remove(index);
10898
- if (fields.length === 1) {
10899
- insert(0, {
10900
- key: "",
10901
- value: "",
10902
- disabled: false
10903
- });
10913
+ };
10914
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10915
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10916
+ const onSubmit = async () => {
10917
+ setIsSubmitting(true);
10918
+ let requestSucceeded = false;
10919
+ await requestOrderEdit(void 0, {
10920
+ onError: (e) => {
10921
+ toast.error(e.message);
10922
+ },
10923
+ onSuccess: () => {
10924
+ requestSucceeded = true;
10925
+ }
10926
+ });
10927
+ if (!requestSucceeded) {
10928
+ setIsSubmitting(false);
10929
+ return;
10904
10930
  }
10905
- }
10906
- function insertRow(index, position) {
10907
- insert(index + (position === "above" ? 0 : 1), {
10908
- key: "",
10909
- value: "",
10910
- disabled: false
10931
+ await confirmOrderEdit(void 0, {
10932
+ onError: (e) => {
10933
+ toast.error(e.message);
10934
+ },
10935
+ onSuccess: () => {
10936
+ handleSuccess();
10937
+ },
10938
+ onSettled: () => {
10939
+ setIsSubmitting(false);
10940
+ }
10911
10941
  });
10912
- }
10913
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10914
- KeyboundForm,
10915
- {
10916
- onSubmit: handleSubmit,
10917
- className: "flex flex-1 flex-col overflow-hidden",
10918
- children: [
10919
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10920
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10921
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10922
- /* @__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" }) }),
10923
- /* @__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" }) })
10924
- ] }),
10925
- fields.map((field, index) => {
10926
- const isDisabled = field.disabled || false;
10927
- let placeholder = "-";
10928
- if (typeof field.value === "object") {
10929
- placeholder = "{ ... }";
10930
- }
10931
- if (Array.isArray(field.value)) {
10932
- placeholder = "[ ... ]";
10933
- }
10934
- return /* @__PURE__ */ jsx(
10935
- ConditionalTooltip,
10936
- {
10937
- showTooltip: isDisabled,
10938
- content: "This row is disabled because it contains non-primitive data.",
10939
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10940
- /* @__PURE__ */ jsxs(
10941
- "div",
10942
- {
10943
- className: clx("grid grid-cols-2 divide-x", {
10944
- "overflow-hidden rounded-b-lg": index === fields.length - 1
10945
- }),
10946
- children: [
10947
- /* @__PURE__ */ jsx(
10948
- Form$2.Field,
10949
- {
10950
- control: form.control,
10951
- name: `metadata.${index}.key`,
10952
- render: ({ field: field2 }) => {
10953
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10954
- GridInput,
10955
- {
10956
- "aria-labelledby": METADATA_KEY_LABEL_ID,
10957
- ...field2,
10958
- disabled: isDisabled,
10959
- placeholder: "Key"
10960
- }
10961
- ) }) });
10962
- }
10963
- }
10964
- ),
10965
- /* @__PURE__ */ jsx(
10966
- Form$2.Field,
10967
- {
10968
- control: form.control,
10969
- name: `metadata.${index}.value`,
10970
- render: ({ field: { value, ...field2 } }) => {
10971
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10972
- GridInput,
10973
- {
10974
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10975
- ...field2,
10976
- value: isDisabled ? placeholder : value,
10977
- disabled: isDisabled,
10978
- placeholder: "Value"
10979
- }
10980
- ) }) });
10981
- }
10982
- }
10983
- )
10984
- ]
10985
- }
10986
- ),
10987
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
10988
- /* @__PURE__ */ jsx(
10989
- DropdownMenu.Trigger,
10990
- {
10991
- className: clx(
10992
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
10993
- {
10994
- hidden: isDisabled
10995
- }
10996
- ),
10997
- disabled: isDisabled,
10998
- asChild: true,
10999
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
11000
- }
11001
- ),
11002
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
11003
- /* @__PURE__ */ jsxs(
11004
- DropdownMenu.Item,
11005
- {
11006
- className: "gap-x-2",
11007
- onClick: () => insertRow(index, "above"),
11008
- children: [
11009
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
11010
- "Insert row above"
11011
- ]
11012
- }
11013
- ),
11014
- /* @__PURE__ */ jsxs(
11015
- DropdownMenu.Item,
11016
- {
11017
- className: "gap-x-2",
11018
- onClick: () => insertRow(index, "below"),
11019
- children: [
11020
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
11021
- "Insert row below"
11022
- ]
11023
- }
11024
- ),
11025
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
11026
- /* @__PURE__ */ jsxs(
11027
- DropdownMenu.Item,
11028
- {
11029
- className: "gap-x-2",
11030
- onClick: () => deleteRow(index),
11031
- children: [
11032
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
11033
- "Delete row"
11034
- ]
11035
- }
11036
- )
11037
- ] })
11038
- ] })
11039
- ] })
11040
- },
11041
- field.id
11042
- );
11043
- })
11044
- ] }),
11045
- 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." })
11046
- ] }),
11047
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11048
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11049
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11050
- ] }) })
11051
- ]
11052
- }
11053
- ) });
11054
- };
11055
- const GridInput = forwardRef(({ className, ...props }, ref) => {
11056
- return /* @__PURE__ */ jsx(
11057
- "input",
11058
- {
11059
- ref,
11060
- ...props,
11061
- autoComplete: "off",
11062
- className: clx(
11063
- "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",
11064
- className
11065
- )
11066
- }
11067
- );
11068
- });
11069
- GridInput.displayName = "MetadataForm.GridInput";
11070
- const PlaceholderInner = () => {
11071
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11072
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11073
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11074
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11075
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11076
- ] }) })
11077
- ] });
11078
- };
11079
- const EDITABLE_TYPES = ["string", "number", "boolean"];
11080
- function getDefaultValues(metadata) {
11081
- if (!metadata || !Object.keys(metadata).length) {
11082
- return [
11083
- {
11084
- key: "",
11085
- value: "",
11086
- disabled: false
11087
- }
11088
- ];
11089
- }
11090
- return Object.entries(metadata).map(([key, value]) => {
11091
- if (!EDITABLE_TYPES.includes(typeof value)) {
11092
- return {
11093
- key,
11094
- value,
11095
- disabled: true
11096
- };
11097
- }
11098
- let stringValue = value;
11099
- if (typeof value !== "string") {
11100
- stringValue = JSON.stringify(value);
11101
- }
11102
- return {
11103
- key,
11104
- value: stringValue,
11105
- original_key: key
11106
- };
11107
- });
11108
- }
11109
- function parseValues(values) {
11110
- const metadata = values.metadata;
11111
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11112
- if (isEmpty) {
11113
- return null;
11114
- }
11115
- const update = {};
11116
- metadata.forEach((field) => {
11117
- let key = field.key;
11118
- let value = field.value;
11119
- const disabled = field.disabled;
11120
- if (!key || !value) {
11121
- return;
11122
- }
11123
- if (disabled) {
11124
- update[key] = value;
11125
- return;
11126
- }
11127
- key = key.trim();
11128
- value = value.trim();
11129
- if (value === "true") {
11130
- update[key] = true;
11131
- } else if (value === "false") {
11132
- update[key] = false;
11133
- } else {
11134
- const parsedNumber = parseFloat(value);
11135
- if (!isNaN(parsedNumber)) {
11136
- update[key] = parsedNumber;
11137
- } else {
11138
- update[key] = value;
11139
- }
11140
- }
11141
- });
11142
- return update;
11143
- }
11144
- function getHasUneditableRows(metadata) {
11145
- if (!metadata) {
11146
- return false;
11147
- }
11148
- return Object.values(metadata).some(
11149
- (value) => !EDITABLE_TYPES.includes(typeof value)
11150
- );
11151
- }
11152
- const PROMOTION_QUERY_KEY = "promotions";
11153
- const promotionsQueryKeys = {
11154
- list: (query2) => [
11155
- PROMOTION_QUERY_KEY,
11156
- query2 ? query2 : void 0
11157
- ],
11158
- detail: (id, query2) => [
11159
- PROMOTION_QUERY_KEY,
11160
- id,
11161
- query2 ? query2 : void 0
11162
- ]
11163
- };
11164
- const usePromotions = (query2, options) => {
11165
- const { data, ...rest } = useQuery({
11166
- queryKey: promotionsQueryKeys.list(query2),
11167
- queryFn: async () => sdk.admin.promotion.list(query2),
11168
- ...options
11169
- });
11170
- return { ...data, ...rest };
11171
- };
11172
- const Promotions = () => {
11173
- const { id } = useParams();
11174
- const {
11175
- order: preview,
11176
- isError: isPreviewError,
11177
- error: previewError
11178
- } = useOrderPreview(id, void 0);
11179
- useInitiateOrderEdit({ preview });
11180
- const { onCancel } = useCancelOrderEdit({ preview });
11181
- if (isPreviewError) {
11182
- throw previewError;
11183
- }
11184
- const isReady = !!preview;
11185
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
11186
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
11187
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
11188
- ] });
11189
- };
11190
- const PromotionForm = ({ preview }) => {
11191
- const { items, shipping_methods } = preview;
11192
- const [isSubmitting, setIsSubmitting] = useState(false);
11193
- const [comboboxValue, setComboboxValue] = useState("");
11194
- const { handleSuccess } = useRouteModal();
11195
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11196
- const promoIds = getPromotionIds(items, shipping_methods);
11197
- const { promotions, isPending, isError, error } = usePromotions(
11198
- {
11199
- id: promoIds
11200
- },
11201
- {
11202
- enabled: !!promoIds.length
11203
- }
11204
- );
11205
- const comboboxData = useComboboxData({
11206
- queryKey: ["promotions", "combobox", promoIds],
11207
- queryFn: async (params) => {
11208
- return await sdk.admin.promotion.list({
11209
- ...params,
11210
- id: {
11211
- $nin: promoIds
11212
- }
11213
- });
11214
- },
11215
- getOptions: (data) => {
11216
- return data.promotions.map((promotion) => ({
11217
- label: promotion.code,
11218
- value: promotion.code
11219
- }));
11220
- }
11221
- });
11222
- const add = async (value) => {
11223
- if (!value) {
11224
- return;
11225
- }
11226
- addPromotions(
11227
- {
11228
- promo_codes: [value]
11229
- },
11230
- {
11231
- onError: (e) => {
11232
- toast.error(e.message);
11233
- comboboxData.onSearchValueChange("");
11234
- setComboboxValue("");
11235
- },
11236
- onSuccess: () => {
11237
- comboboxData.onSearchValueChange("");
11238
- setComboboxValue("");
11239
- }
11240
- }
11241
- );
11242
- };
11243
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11244
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
11245
- const onSubmit = async () => {
11246
- setIsSubmitting(true);
11247
- let requestSucceeded = false;
11248
- await requestOrderEdit(void 0, {
11249
- onError: (e) => {
11250
- toast.error(e.message);
11251
- },
11252
- onSuccess: () => {
11253
- requestSucceeded = true;
11254
- }
11255
- });
11256
- if (!requestSucceeded) {
11257
- setIsSubmitting(false);
11258
- return;
11259
- }
11260
- await confirmOrderEdit(void 0, {
11261
- onError: (e) => {
11262
- toast.error(e.message);
11263
- },
11264
- onSuccess: () => {
11265
- handleSuccess();
11266
- },
11267
- onSettled: () => {
11268
- setIsSubmitting(false);
11269
- }
11270
- });
11271
- };
11272
- if (isError) {
11273
- throw error;
10942
+ };
10943
+ if (isError) {
10944
+ throw error;
11274
10945
  }
11275
10946
  return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11276
10947
  /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
@@ -11454,7 +11125,7 @@ const SalesChannelForm = ({ order }) => {
11454
11125
  defaultValues: {
11455
11126
  sales_channel_id: order.sales_channel_id || ""
11456
11127
  },
11457
- resolver: zodResolver(schema$3)
11128
+ resolver: zodResolver(schema$2)
11458
11129
  });
11459
11130
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
11460
11131
  const { handleSuccess } = useRouteModal();
@@ -11529,7 +11200,7 @@ const SalesChannelField = ({ control, order }) => {
11529
11200
  }
11530
11201
  );
11531
11202
  };
11532
- const schema$3 = objectType({
11203
+ const schema$2 = objectType({
11533
11204
  sales_channel_id: stringType().min(1)
11534
11205
  });
11535
11206
  const STACKED_FOCUS_MODAL_ID = "shipping-form";
@@ -12371,7 +12042,7 @@ const ShippingAddressForm = ({ order }) => {
12371
12042
  postal_code: ((_i = order.shipping_address) == null ? void 0 : _i.postal_code) ?? "",
12372
12043
  phone: ((_j = order.shipping_address) == null ? void 0 : _j.phone) ?? ""
12373
12044
  },
12374
- resolver: zodResolver(schema$2)
12045
+ resolver: zodResolver(schema$1)
12375
12046
  });
12376
12047
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12377
12048
  const { handleSuccess } = useRouteModal();
@@ -12541,7 +12212,7 @@ const ShippingAddressForm = ({ order }) => {
12541
12212
  }
12542
12213
  ) });
12543
12214
  };
12544
- const schema$2 = addressSchema;
12215
+ const schema$1 = addressSchema;
12545
12216
  const TransferOwnership = () => {
12546
12217
  const { id } = useParams();
12547
12218
  const { draft_order, isPending, isError, error } = useDraftOrder(id, {
@@ -12565,7 +12236,7 @@ const TransferOwnershipForm = ({ order }) => {
12565
12236
  defaultValues: {
12566
12237
  customer_id: order.customer_id || ""
12567
12238
  },
12568
- resolver: zodResolver(schema$1)
12239
+ resolver: zodResolver(schema)
12569
12240
  });
12570
12241
  const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
12571
12242
  const { handleSuccess } = useRouteModal();
@@ -13013,32 +12684,361 @@ const Illustration = () => {
13013
12684
  ] })
13014
12685
  ]
13015
12686
  }
13016
- );
12687
+ );
12688
+ };
12689
+ const schema = objectType({
12690
+ customer_id: stringType().min(1)
12691
+ });
12692
+ const InlineTip = forwardRef(
12693
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
12694
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
12695
+ return /* @__PURE__ */ jsxs(
12696
+ "div",
12697
+ {
12698
+ ref,
12699
+ className: clx(
12700
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
12701
+ className
12702
+ ),
12703
+ ...props,
12704
+ children: [
12705
+ /* @__PURE__ */ jsx(
12706
+ "div",
12707
+ {
12708
+ role: "presentation",
12709
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
12710
+ "bg-ui-tag-orange-icon": variant === "warning"
12711
+ })
12712
+ }
12713
+ ),
12714
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
12715
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
12716
+ labelValue,
12717
+ ":"
12718
+ ] }),
12719
+ " ",
12720
+ children
12721
+ ] })
12722
+ ]
12723
+ }
12724
+ );
12725
+ }
12726
+ );
12727
+ InlineTip.displayName = "InlineTip";
12728
+ const MetadataFieldSchema = objectType({
12729
+ key: stringType(),
12730
+ disabled: booleanType().optional(),
12731
+ value: anyType()
12732
+ });
12733
+ const MetadataSchema = objectType({
12734
+ metadata: arrayType(MetadataFieldSchema)
12735
+ });
12736
+ const Metadata = () => {
12737
+ const { id } = useParams();
12738
+ const { order, isPending, isError, error } = useOrder(id, {
12739
+ fields: "metadata"
12740
+ });
12741
+ if (isError) {
12742
+ throw error;
12743
+ }
12744
+ const isReady = !isPending && !!order;
12745
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
12746
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
12747
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
12748
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
12749
+ ] }),
12750
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
12751
+ ] });
12752
+ };
12753
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
12754
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
12755
+ const MetadataForm = ({ orderId, metadata }) => {
12756
+ const { handleSuccess } = useRouteModal();
12757
+ const hasUneditableRows = getHasUneditableRows(metadata);
12758
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
12759
+ const form = useForm({
12760
+ defaultValues: {
12761
+ metadata: getDefaultValues(metadata)
12762
+ },
12763
+ resolver: zodResolver(MetadataSchema)
12764
+ });
12765
+ const handleSubmit = form.handleSubmit(async (data) => {
12766
+ const parsedData = parseValues(data);
12767
+ await mutateAsync(
12768
+ {
12769
+ metadata: parsedData
12770
+ },
12771
+ {
12772
+ onSuccess: () => {
12773
+ toast.success("Metadata updated");
12774
+ handleSuccess();
12775
+ },
12776
+ onError: (error) => {
12777
+ toast.error(error.message);
12778
+ }
12779
+ }
12780
+ );
12781
+ });
12782
+ const { fields, insert, remove } = useFieldArray({
12783
+ control: form.control,
12784
+ name: "metadata"
12785
+ });
12786
+ function deleteRow(index) {
12787
+ remove(index);
12788
+ if (fields.length === 1) {
12789
+ insert(0, {
12790
+ key: "",
12791
+ value: "",
12792
+ disabled: false
12793
+ });
12794
+ }
12795
+ }
12796
+ function insertRow(index, position) {
12797
+ insert(index + (position === "above" ? 0 : 1), {
12798
+ key: "",
12799
+ value: "",
12800
+ disabled: false
12801
+ });
12802
+ }
12803
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
12804
+ KeyboundForm,
12805
+ {
12806
+ onSubmit: handleSubmit,
12807
+ className: "flex flex-1 flex-col overflow-hidden",
12808
+ children: [
12809
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
12810
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
12811
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
12812
+ /* @__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" }) }),
12813
+ /* @__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" }) })
12814
+ ] }),
12815
+ fields.map((field, index) => {
12816
+ const isDisabled = field.disabled || false;
12817
+ let placeholder = "-";
12818
+ if (typeof field.value === "object") {
12819
+ placeholder = "{ ... }";
12820
+ }
12821
+ if (Array.isArray(field.value)) {
12822
+ placeholder = "[ ... ]";
12823
+ }
12824
+ return /* @__PURE__ */ jsx(
12825
+ ConditionalTooltip,
12826
+ {
12827
+ showTooltip: isDisabled,
12828
+ content: "This row is disabled because it contains non-primitive data.",
12829
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
12830
+ /* @__PURE__ */ jsxs(
12831
+ "div",
12832
+ {
12833
+ className: clx("grid grid-cols-2 divide-x", {
12834
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
12835
+ }),
12836
+ children: [
12837
+ /* @__PURE__ */ jsx(
12838
+ Form$2.Field,
12839
+ {
12840
+ control: form.control,
12841
+ name: `metadata.${index}.key`,
12842
+ render: ({ field: field2 }) => {
12843
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12844
+ GridInput,
12845
+ {
12846
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
12847
+ ...field2,
12848
+ disabled: isDisabled,
12849
+ placeholder: "Key"
12850
+ }
12851
+ ) }) });
12852
+ }
12853
+ }
12854
+ ),
12855
+ /* @__PURE__ */ jsx(
12856
+ Form$2.Field,
12857
+ {
12858
+ control: form.control,
12859
+ name: `metadata.${index}.value`,
12860
+ render: ({ field: { value, ...field2 } }) => {
12861
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
12862
+ GridInput,
12863
+ {
12864
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
12865
+ ...field2,
12866
+ value: isDisabled ? placeholder : value,
12867
+ disabled: isDisabled,
12868
+ placeholder: "Value"
12869
+ }
12870
+ ) }) });
12871
+ }
12872
+ }
12873
+ )
12874
+ ]
12875
+ }
12876
+ ),
12877
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
12878
+ /* @__PURE__ */ jsx(
12879
+ DropdownMenu.Trigger,
12880
+ {
12881
+ className: clx(
12882
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
12883
+ {
12884
+ hidden: isDisabled
12885
+ }
12886
+ ),
12887
+ disabled: isDisabled,
12888
+ asChild: true,
12889
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
12890
+ }
12891
+ ),
12892
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
12893
+ /* @__PURE__ */ jsxs(
12894
+ DropdownMenu.Item,
12895
+ {
12896
+ className: "gap-x-2",
12897
+ onClick: () => insertRow(index, "above"),
12898
+ children: [
12899
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
12900
+ "Insert row above"
12901
+ ]
12902
+ }
12903
+ ),
12904
+ /* @__PURE__ */ jsxs(
12905
+ DropdownMenu.Item,
12906
+ {
12907
+ className: "gap-x-2",
12908
+ onClick: () => insertRow(index, "below"),
12909
+ children: [
12910
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
12911
+ "Insert row below"
12912
+ ]
12913
+ }
12914
+ ),
12915
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
12916
+ /* @__PURE__ */ jsxs(
12917
+ DropdownMenu.Item,
12918
+ {
12919
+ className: "gap-x-2",
12920
+ onClick: () => deleteRow(index),
12921
+ children: [
12922
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
12923
+ "Delete row"
12924
+ ]
12925
+ }
12926
+ )
12927
+ ] })
12928
+ ] })
12929
+ ] })
12930
+ },
12931
+ field.id
12932
+ );
12933
+ })
12934
+ ] }),
12935
+ 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." })
12936
+ ] }),
12937
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12938
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
12939
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
12940
+ ] }) })
12941
+ ]
12942
+ }
12943
+ ) });
13017
12944
  };
13018
- const schema$1 = objectType({
13019
- customer_id: stringType().min(1)
12945
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
12946
+ return /* @__PURE__ */ jsx(
12947
+ "input",
12948
+ {
12949
+ ref,
12950
+ ...props,
12951
+ autoComplete: "off",
12952
+ className: clx(
12953
+ "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",
12954
+ className
12955
+ )
12956
+ }
12957
+ );
13020
12958
  });
13021
- const CustomItems = () => {
13022
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
13023
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Custom Items" }) }) }),
13024
- /* @__PURE__ */ jsx(CustomItemsForm, {})
12959
+ GridInput.displayName = "MetadataForm.GridInput";
12960
+ const PlaceholderInner = () => {
12961
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
12962
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
12963
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
12964
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
12965
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
12966
+ ] }) })
13025
12967
  ] });
13026
12968
  };
13027
- const CustomItemsForm = () => {
13028
- const form = useForm({
13029
- resolver: zodResolver(schema)
12969
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
12970
+ function getDefaultValues(metadata) {
12971
+ if (!metadata || !Object.keys(metadata).length) {
12972
+ return [
12973
+ {
12974
+ key: "",
12975
+ value: "",
12976
+ disabled: false
12977
+ }
12978
+ ];
12979
+ }
12980
+ return Object.entries(metadata).map(([key, value]) => {
12981
+ if (!EDITABLE_TYPES.includes(typeof value)) {
12982
+ return {
12983
+ key,
12984
+ value,
12985
+ disabled: true
12986
+ };
12987
+ }
12988
+ let stringValue = value;
12989
+ if (typeof value !== "string") {
12990
+ stringValue = JSON.stringify(value);
12991
+ }
12992
+ return {
12993
+ key,
12994
+ value: stringValue,
12995
+ original_key: key
12996
+ };
13030
12997
  });
13031
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", children: [
13032
- /* @__PURE__ */ jsx(RouteDrawer.Body, {}),
13033
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
13034
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
13035
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", children: "Save" })
13036
- ] }) })
13037
- ] }) });
13038
- };
13039
- const schema = objectType({
13040
- email: stringType().email()
13041
- });
12998
+ }
12999
+ function parseValues(values) {
13000
+ const metadata = values.metadata;
13001
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
13002
+ if (isEmpty) {
13003
+ return null;
13004
+ }
13005
+ const update = {};
13006
+ metadata.forEach((field) => {
13007
+ let key = field.key;
13008
+ let value = field.value;
13009
+ const disabled = field.disabled;
13010
+ if (!key || !value) {
13011
+ return;
13012
+ }
13013
+ if (disabled) {
13014
+ update[key] = value;
13015
+ return;
13016
+ }
13017
+ key = key.trim();
13018
+ value = value.trim();
13019
+ if (value === "true") {
13020
+ update[key] = true;
13021
+ } else if (value === "false") {
13022
+ update[key] = false;
13023
+ } else {
13024
+ const parsedNumber = parseFloat(value);
13025
+ if (!isNaN(parsedNumber)) {
13026
+ update[key] = parsedNumber;
13027
+ } else {
13028
+ update[key] = value;
13029
+ }
13030
+ }
13031
+ });
13032
+ return update;
13033
+ }
13034
+ function getHasUneditableRows(metadata) {
13035
+ if (!metadata) {
13036
+ return false;
13037
+ }
13038
+ return Object.values(metadata).some(
13039
+ (value) => !EDITABLE_TYPES.includes(typeof value)
13040
+ );
13041
+ }
13042
13042
  const widgetModule = { widgets: [] };
13043
13043
  const routeModule = {
13044
13044
  routes: [
@@ -13063,6 +13063,10 @@ const routeModule = {
13063
13063
  Component: BillingAddress,
13064
13064
  path: "/draft-orders/:id/billing-address"
13065
13065
  },
13066
+ {
13067
+ Component: CustomItems,
13068
+ path: "/draft-orders/:id/custom-items"
13069
+ },
13066
13070
  {
13067
13071
  Component: Email,
13068
13072
  path: "/draft-orders/:id/email"
@@ -13071,10 +13075,6 @@ const routeModule = {
13071
13075
  Component: Items,
13072
13076
  path: "/draft-orders/:id/items"
13073
13077
  },
13074
- {
13075
- Component: Metadata,
13076
- path: "/draft-orders/:id/metadata"
13077
- },
13078
13078
  {
13079
13079
  Component: Promotions,
13080
13080
  path: "/draft-orders/:id/promotions"
@@ -13096,8 +13096,8 @@ const routeModule = {
13096
13096
  path: "/draft-orders/:id/transfer-ownership"
13097
13097
  },
13098
13098
  {
13099
- Component: CustomItems,
13100
- path: "/draft-orders/:id/custom-items"
13099
+ Component: Metadata,
13100
+ path: "/draft-orders/:id/metadata"
13101
13101
  }
13102
13102
  ]
13103
13103
  }