@medusajs/draft-order 2.11.4-preview-20251108210131 → 2.11.4-preview-20251109000311

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.
@@ -10814,632 +10814,632 @@ const customItemSchema = objectType({
10814
10814
  quantity: numberType(),
10815
10815
  unit_price: unionType([numberType(), stringType()])
10816
10816
  });
10817
- const InlineTip = forwardRef(
10818
- ({ variant = "tip", label, className, children, ...props }, ref) => {
10819
- const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
10820
- return /* @__PURE__ */ jsxs(
10821
- "div",
10822
- {
10823
- ref,
10824
- className: clx(
10825
- "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
10826
- className
10827
- ),
10828
- ...props,
10829
- children: [
10830
- /* @__PURE__ */ jsx(
10831
- "div",
10832
- {
10833
- role: "presentation",
10834
- className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
10835
- "bg-ui-tag-orange-icon": variant === "warning"
10836
- })
10837
- }
10838
- ),
10839
- /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
10840
- /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
10841
- labelValue,
10842
- ":"
10843
- ] }),
10844
- " ",
10845
- children
10846
- ] })
10847
- ]
10848
- }
10849
- );
10850
- }
10851
- );
10852
- InlineTip.displayName = "InlineTip";
10853
- const MetadataFieldSchema = objectType({
10854
- key: stringType(),
10855
- disabled: booleanType().optional(),
10856
- value: anyType()
10857
- });
10858
- const MetadataSchema = objectType({
10859
- metadata: arrayType(MetadataFieldSchema)
10860
- });
10861
- const Metadata = () => {
10862
- const { id } = useParams();
10863
- const { order, isPending, isError, error } = useOrder(id, {
10864
- fields: "metadata"
10817
+ const PROMOTION_QUERY_KEY = "promotions";
10818
+ const promotionsQueryKeys = {
10819
+ list: (query2) => [
10820
+ PROMOTION_QUERY_KEY,
10821
+ query2 ? query2 : void 0
10822
+ ],
10823
+ detail: (id, query2) => [
10824
+ PROMOTION_QUERY_KEY,
10825
+ id,
10826
+ query2 ? query2 : void 0
10827
+ ]
10828
+ };
10829
+ const usePromotions = (query2, options) => {
10830
+ const { data, ...rest } = useQuery({
10831
+ queryKey: promotionsQueryKeys.list(query2),
10832
+ queryFn: async () => sdk.admin.promotion.list(query2),
10833
+ ...options
10865
10834
  });
10866
- if (isError) {
10867
- throw error;
10835
+ return { ...data, ...rest };
10836
+ };
10837
+ const Promotions = () => {
10838
+ const { id } = useParams();
10839
+ const {
10840
+ order: preview,
10841
+ isError: isPreviewError,
10842
+ error: previewError
10843
+ } = useOrderPreview(id, void 0);
10844
+ useInitiateOrderEdit({ preview });
10845
+ const { onCancel } = useCancelOrderEdit({ preview });
10846
+ if (isPreviewError) {
10847
+ throw previewError;
10868
10848
  }
10869
- const isReady = !isPending && !!order;
10870
- return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
10871
- /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
10872
- /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
10873
- /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
10874
- ] }),
10875
- !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
10849
+ const isReady = !!preview;
10850
+ return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
10851
+ /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
10852
+ isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
10876
10853
  ] });
10877
10854
  };
10878
- const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
10879
- const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
10880
- const MetadataForm = ({ orderId, metadata }) => {
10855
+ const PromotionForm = ({ preview }) => {
10856
+ const { items, shipping_methods } = preview;
10857
+ const [isSubmitting, setIsSubmitting] = useState(false);
10858
+ const [comboboxValue, setComboboxValue] = useState("");
10881
10859
  const { handleSuccess } = useRouteModal();
10882
- const hasUneditableRows = getHasUneditableRows(metadata);
10883
- const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
10884
- const form = useForm({
10885
- defaultValues: {
10886
- metadata: getDefaultValues(metadata)
10860
+ const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
10861
+ const promoIds = getPromotionIds(items, shipping_methods);
10862
+ const { promotions, isPending, isError, error } = usePromotions(
10863
+ {
10864
+ id: promoIds
10887
10865
  },
10888
- resolver: zodResolver(MetadataSchema)
10866
+ {
10867
+ enabled: !!promoIds.length
10868
+ }
10869
+ );
10870
+ const comboboxData = useComboboxData({
10871
+ queryKey: ["promotions", "combobox", promoIds],
10872
+ queryFn: async (params) => {
10873
+ return await sdk.admin.promotion.list({
10874
+ ...params,
10875
+ id: {
10876
+ $nin: promoIds
10877
+ }
10878
+ });
10879
+ },
10880
+ getOptions: (data) => {
10881
+ return data.promotions.map((promotion) => ({
10882
+ label: promotion.code,
10883
+ value: promotion.code
10884
+ }));
10885
+ }
10889
10886
  });
10890
- const handleSubmit = form.handleSubmit(async (data) => {
10891
- const parsedData = parseValues(data);
10892
- await mutateAsync(
10887
+ const add = async (value) => {
10888
+ if (!value) {
10889
+ return;
10890
+ }
10891
+ addPromotions(
10893
10892
  {
10894
- metadata: parsedData
10893
+ promo_codes: [value]
10895
10894
  },
10896
10895
  {
10897
- onSuccess: () => {
10898
- toast.success("Metadata updated");
10899
- handleSuccess();
10896
+ onError: (e) => {
10897
+ toast.error(e.message);
10898
+ comboboxData.onSearchValueChange("");
10899
+ setComboboxValue("");
10900
10900
  },
10901
- onError: (error) => {
10902
- toast.error(error.message);
10901
+ onSuccess: () => {
10902
+ comboboxData.onSearchValueChange("");
10903
+ setComboboxValue("");
10903
10904
  }
10904
10905
  }
10905
10906
  );
10906
- });
10907
- const { fields, insert, remove } = useFieldArray({
10908
- control: form.control,
10909
- name: "metadata"
10910
- });
10911
- function deleteRow(index) {
10912
- remove(index);
10913
- if (fields.length === 1) {
10914
- insert(0, {
10915
- key: "",
10916
- value: "",
10917
- disabled: false
10918
- });
10907
+ };
10908
+ const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
10909
+ const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
10910
+ const onSubmit = async () => {
10911
+ setIsSubmitting(true);
10912
+ let requestSucceeded = false;
10913
+ await requestOrderEdit(void 0, {
10914
+ onError: (e) => {
10915
+ toast.error(e.message);
10916
+ },
10917
+ onSuccess: () => {
10918
+ requestSucceeded = true;
10919
+ }
10920
+ });
10921
+ if (!requestSucceeded) {
10922
+ setIsSubmitting(false);
10923
+ return;
10919
10924
  }
10920
- }
10921
- function insertRow(index, position) {
10922
- insert(index + (position === "above" ? 0 : 1), {
10923
- key: "",
10924
- value: "",
10925
- disabled: false
10925
+ await confirmOrderEdit(void 0, {
10926
+ onError: (e) => {
10927
+ toast.error(e.message);
10928
+ },
10929
+ onSuccess: () => {
10930
+ handleSuccess();
10931
+ },
10932
+ onSettled: () => {
10933
+ setIsSubmitting(false);
10934
+ }
10926
10935
  });
10936
+ };
10937
+ if (isError) {
10938
+ throw error;
10927
10939
  }
10928
- return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
10929
- KeyboundForm,
10930
- {
10931
- onSubmit: handleSubmit,
10932
- className: "flex flex-1 flex-col overflow-hidden",
10933
- children: [
10934
- /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
10935
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
10936
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
10937
- /* @__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" }) }),
10938
- /* @__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" }) })
10939
- ] }),
10940
- fields.map((field, index) => {
10941
- const isDisabled = field.disabled || false;
10942
- let placeholder = "-";
10943
- if (typeof field.value === "object") {
10944
- placeholder = "{ ... }";
10945
- }
10946
- if (Array.isArray(field.value)) {
10947
- placeholder = "[ ... ]";
10948
- }
10949
- return /* @__PURE__ */ jsx(
10950
- ConditionalTooltip,
10951
- {
10952
- showTooltip: isDisabled,
10953
- content: "This row is disabled because it contains non-primitive data.",
10954
- children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
10955
- /* @__PURE__ */ jsxs(
10956
- "div",
10957
- {
10958
- className: clx("grid grid-cols-2 divide-x", {
10959
- "overflow-hidden rounded-b-lg": index === fields.length - 1
10960
- }),
10961
- children: [
10962
- /* @__PURE__ */ jsx(
10963
- Form$2.Field,
10964
- {
10965
- control: form.control,
10966
- name: `metadata.${index}.key`,
10967
- render: ({ field: field2 }) => {
10968
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10969
- GridInput,
10970
- {
10971
- "aria-labelledby": METADATA_KEY_LABEL_ID,
10972
- ...field2,
10973
- disabled: isDisabled,
10974
- placeholder: "Key"
10975
- }
10976
- ) }) });
10977
- }
10978
- }
10979
- ),
10980
- /* @__PURE__ */ jsx(
10981
- Form$2.Field,
10982
- {
10983
- control: form.control,
10984
- name: `metadata.${index}.value`,
10985
- render: ({ field: { value, ...field2 } }) => {
10986
- return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
10987
- GridInput,
10988
- {
10989
- "aria-labelledby": METADATA_VALUE_LABEL_ID,
10990
- ...field2,
10991
- value: isDisabled ? placeholder : value,
10992
- disabled: isDisabled,
10993
- placeholder: "Value"
10994
- }
10995
- ) }) });
10996
- }
10997
- }
10998
- )
10999
- ]
11000
- }
11001
- ),
11002
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
11003
- /* @__PURE__ */ jsx(
11004
- DropdownMenu.Trigger,
11005
- {
11006
- className: clx(
11007
- "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
11008
- {
11009
- hidden: isDisabled
11010
- }
11011
- ),
11012
- disabled: isDisabled,
11013
- asChild: true,
11014
- children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
11015
- }
11016
- ),
11017
- /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
11018
- /* @__PURE__ */ jsxs(
11019
- DropdownMenu.Item,
11020
- {
11021
- className: "gap-x-2",
11022
- onClick: () => insertRow(index, "above"),
11023
- children: [
11024
- /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
11025
- "Insert row above"
11026
- ]
11027
- }
11028
- ),
11029
- /* @__PURE__ */ jsxs(
11030
- DropdownMenu.Item,
11031
- {
11032
- className: "gap-x-2",
11033
- onClick: () => insertRow(index, "below"),
11034
- children: [
11035
- /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
11036
- "Insert row below"
11037
- ]
11038
- }
11039
- ),
11040
- /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
11041
- /* @__PURE__ */ jsxs(
11042
- DropdownMenu.Item,
11043
- {
11044
- className: "gap-x-2",
11045
- onClick: () => deleteRow(index),
11046
- children: [
11047
- /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
11048
- "Delete row"
11049
- ]
11050
- }
11051
- )
11052
- ] })
11053
- ] })
11054
- ] })
11055
- },
11056
- field.id
11057
- );
11058
- })
11059
- ] }),
11060
- 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." })
10940
+ return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
10941
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
10942
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
10943
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
10944
+ /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
10945
+ /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11061
10946
  ] }),
11062
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11063
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11064
- /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11065
- ] }) })
11066
- ]
11067
- }
11068
- ) });
11069
- };
11070
- const GridInput = forwardRef(({ className, ...props }, ref) => {
11071
- return /* @__PURE__ */ jsx(
11072
- "input",
11073
- {
11074
- ref,
11075
- ...props,
11076
- autoComplete: "off",
11077
- className: clx(
11078
- "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",
11079
- className
10947
+ /* @__PURE__ */ jsx(
10948
+ Combobox,
10949
+ {
10950
+ id: "promotion-combobox",
10951
+ "aria-describedby": "promotion-combobox-hint",
10952
+ isFetchingNextPage: comboboxData.isFetchingNextPage,
10953
+ fetchNextPage: comboboxData.fetchNextPage,
10954
+ options: comboboxData.options,
10955
+ onSearchValueChange: comboboxData.onSearchValueChange,
10956
+ searchValue: comboboxData.searchValue,
10957
+ disabled: comboboxData.disabled || isAddingPromotions,
10958
+ onChange: add,
10959
+ value: comboboxValue
10960
+ }
10961
+ )
10962
+ ] }),
10963
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
10964
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
10965
+ PromotionItem,
10966
+ {
10967
+ promotion,
10968
+ orderId: preview.id,
10969
+ isLoading: isPending
10970
+ },
10971
+ promotion.id
10972
+ )) })
10973
+ ] }) }),
10974
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
10975
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
10976
+ /* @__PURE__ */ jsx(
10977
+ Button,
10978
+ {
10979
+ size: "small",
10980
+ type: "submit",
10981
+ isLoading: isSubmitting || isAddingPromotions,
10982
+ children: "Save"
10983
+ }
11080
10984
  )
11081
- }
11082
- );
11083
- });
11084
- GridInput.displayName = "MetadataForm.GridInput";
11085
- const PlaceholderInner = () => {
11086
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11087
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11088
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11089
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11090
- /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11091
10985
  ] }) })
11092
10986
  ] });
11093
10987
  };
11094
- const EDITABLE_TYPES = ["string", "number", "boolean"];
11095
- function getDefaultValues(metadata) {
11096
- if (!metadata || !Object.keys(metadata).length) {
11097
- return [
10988
+ const PromotionItem = ({
10989
+ promotion,
10990
+ orderId,
10991
+ isLoading
10992
+ }) => {
10993
+ var _a;
10994
+ const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
10995
+ const onRemove = async () => {
10996
+ removePromotions(
11098
10997
  {
11099
- key: "",
11100
- value: "",
11101
- disabled: false
10998
+ promo_codes: [promotion.code]
10999
+ },
11000
+ {
11001
+ onError: (e) => {
11002
+ toast.error(e.message);
11003
+ }
11102
11004
  }
11103
- ];
11005
+ );
11006
+ };
11007
+ const displayValue = getDisplayValue(promotion);
11008
+ return /* @__PURE__ */ jsxs(
11009
+ "div",
11010
+ {
11011
+ className: clx(
11012
+ "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11013
+ {
11014
+ "animate-pulse": isLoading
11015
+ }
11016
+ ),
11017
+ children: [
11018
+ /* @__PURE__ */ jsxs("div", { children: [
11019
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11020
+ /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11021
+ displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11022
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11023
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11024
+ ] }),
11025
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11026
+ ] })
11027
+ ] }),
11028
+ /* @__PURE__ */ jsx(
11029
+ IconButton,
11030
+ {
11031
+ size: "small",
11032
+ type: "button",
11033
+ variant: "transparent",
11034
+ onClick: onRemove,
11035
+ isLoading: isPending || isLoading,
11036
+ children: /* @__PURE__ */ jsx(XMark, {})
11037
+ }
11038
+ )
11039
+ ]
11040
+ },
11041
+ promotion.id
11042
+ );
11043
+ };
11044
+ function getDisplayValue(promotion) {
11045
+ var _a, _b, _c, _d;
11046
+ const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11047
+ if (!value) {
11048
+ return null;
11104
11049
  }
11105
- return Object.entries(metadata).map(([key, value]) => {
11106
- if (!EDITABLE_TYPES.includes(typeof value)) {
11107
- return {
11108
- key,
11109
- value,
11110
- disabled: true
11111
- };
11112
- }
11113
- let stringValue = value;
11114
- if (typeof value !== "string") {
11115
- stringValue = JSON.stringify(value);
11050
+ if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11051
+ const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11052
+ if (!currency) {
11053
+ return null;
11116
11054
  }
11117
- return {
11118
- key,
11119
- value: stringValue,
11120
- original_key: key
11121
- };
11122
- });
11055
+ return getLocaleAmount(value, currency);
11056
+ } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11057
+ return formatPercentage(value);
11058
+ }
11059
+ return null;
11123
11060
  }
11124
- function parseValues(values) {
11125
- const metadata = values.metadata;
11126
- const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11127
- if (isEmpty) {
11128
- return null;
11061
+ const formatter = new Intl.NumberFormat([], {
11062
+ style: "percent",
11063
+ minimumFractionDigits: 2
11064
+ });
11065
+ const formatPercentage = (value, isPercentageValue = false) => {
11066
+ let val = value || 0;
11067
+ if (!isPercentageValue) {
11068
+ val = val / 100;
11129
11069
  }
11130
- const update = {};
11131
- metadata.forEach((field) => {
11132
- let key = field.key;
11133
- let value = field.value;
11134
- const disabled = field.disabled;
11135
- if (!key || !value) {
11136
- return;
11137
- }
11138
- if (disabled) {
11139
- update[key] = value;
11140
- return;
11070
+ return formatter.format(val);
11071
+ };
11072
+ function getPromotionIds(items, shippingMethods) {
11073
+ const promotionIds = /* @__PURE__ */ new Set();
11074
+ for (const item of items) {
11075
+ if (item.adjustments) {
11076
+ for (const adjustment of item.adjustments) {
11077
+ if (adjustment.promotion_id) {
11078
+ promotionIds.add(adjustment.promotion_id);
11079
+ }
11080
+ }
11141
11081
  }
11142
- key = key.trim();
11143
- value = value.trim();
11144
- if (value === "true") {
11145
- update[key] = true;
11146
- } else if (value === "false") {
11147
- update[key] = false;
11148
- } else {
11149
- const parsedNumber = parseFloat(value);
11150
- if (!isNaN(parsedNumber)) {
11151
- update[key] = parsedNumber;
11152
- } else {
11153
- update[key] = value;
11082
+ }
11083
+ for (const shippingMethod of shippingMethods) {
11084
+ if (shippingMethod.adjustments) {
11085
+ for (const adjustment of shippingMethod.adjustments) {
11086
+ if (adjustment.promotion_id) {
11087
+ promotionIds.add(adjustment.promotion_id);
11088
+ }
11154
11089
  }
11155
11090
  }
11156
- });
11157
- return update;
11158
- }
11159
- function getHasUneditableRows(metadata) {
11160
- if (!metadata) {
11161
- return false;
11162
11091
  }
11163
- return Object.values(metadata).some(
11164
- (value) => !EDITABLE_TYPES.includes(typeof value)
11165
- );
11092
+ return Array.from(promotionIds);
11166
11093
  }
11167
- const PROMOTION_QUERY_KEY = "promotions";
11168
- const promotionsQueryKeys = {
11169
- list: (query2) => [
11170
- PROMOTION_QUERY_KEY,
11171
- query2 ? query2 : void 0
11172
- ],
11173
- detail: (id, query2) => [
11174
- PROMOTION_QUERY_KEY,
11175
- id,
11176
- query2 ? query2 : void 0
11177
- ]
11178
- };
11179
- const usePromotions = (query2, options) => {
11180
- const { data, ...rest } = useQuery({
11181
- queryKey: promotionsQueryKeys.list(query2),
11182
- queryFn: async () => sdk.admin.promotion.list(query2),
11183
- ...options
11184
- });
11185
- return { ...data, ...rest };
11186
- };
11187
- const Promotions = () => {
11094
+ const InlineTip = forwardRef(
11095
+ ({ variant = "tip", label, className, children, ...props }, ref) => {
11096
+ const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
11097
+ return /* @__PURE__ */ jsxs(
11098
+ "div",
11099
+ {
11100
+ ref,
11101
+ className: clx(
11102
+ "bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
11103
+ className
11104
+ ),
11105
+ ...props,
11106
+ children: [
11107
+ /* @__PURE__ */ jsx(
11108
+ "div",
11109
+ {
11110
+ role: "presentation",
11111
+ className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
11112
+ "bg-ui-tag-orange-icon": variant === "warning"
11113
+ })
11114
+ }
11115
+ ),
11116
+ /* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
11117
+ /* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
11118
+ labelValue,
11119
+ ":"
11120
+ ] }),
11121
+ " ",
11122
+ children
11123
+ ] })
11124
+ ]
11125
+ }
11126
+ );
11127
+ }
11128
+ );
11129
+ InlineTip.displayName = "InlineTip";
11130
+ const MetadataFieldSchema = objectType({
11131
+ key: stringType(),
11132
+ disabled: booleanType().optional(),
11133
+ value: anyType()
11134
+ });
11135
+ const MetadataSchema = objectType({
11136
+ metadata: arrayType(MetadataFieldSchema)
11137
+ });
11138
+ const Metadata = () => {
11188
11139
  const { id } = useParams();
11189
- const {
11190
- order: preview,
11191
- isError: isPreviewError,
11192
- error: previewError
11193
- } = useOrderPreview(id, void 0);
11194
- useInitiateOrderEdit({ preview });
11195
- const { onCancel } = useCancelOrderEdit({ preview });
11196
- if (isPreviewError) {
11197
- throw previewError;
11140
+ const { order, isPending, isError, error } = useOrder(id, {
11141
+ fields: "metadata"
11142
+ });
11143
+ if (isError) {
11144
+ throw error;
11198
11145
  }
11199
- const isReady = !!preview;
11200
- return /* @__PURE__ */ jsxs(RouteDrawer, { onClose: onCancel, children: [
11201
- /* @__PURE__ */ jsx(RouteDrawer.Header, { children: /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Promotions" }) }) }),
11202
- isReady && /* @__PURE__ */ jsx(PromotionForm, { preview })
11146
+ const isReady = !isPending && !!order;
11147
+ return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
11148
+ /* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
11149
+ /* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Metadata" }) }),
11150
+ /* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Add metadata to the draft order." }) })
11151
+ ] }),
11152
+ !isReady ? /* @__PURE__ */ jsx(PlaceholderInner, {}) : /* @__PURE__ */ jsx(MetadataForm, { orderId: id, metadata: order == null ? void 0 : order.metadata })
11203
11153
  ] });
11204
11154
  };
11205
- const PromotionForm = ({ preview }) => {
11206
- const { items, shipping_methods } = preview;
11207
- const [isSubmitting, setIsSubmitting] = useState(false);
11208
- const [comboboxValue, setComboboxValue] = useState("");
11155
+ const METADATA_KEY_LABEL_ID = "metadata-form-key-label";
11156
+ const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
11157
+ const MetadataForm = ({ orderId, metadata }) => {
11209
11158
  const { handleSuccess } = useRouteModal();
11210
- const { mutateAsync: addPromotions, isPending: isAddingPromotions } = useDraftOrderAddPromotions(preview.id);
11211
- const promoIds = getPromotionIds(items, shipping_methods);
11212
- const { promotions, isPending, isError, error } = usePromotions(
11213
- {
11214
- id: promoIds
11215
- },
11216
- {
11217
- enabled: !!promoIds.length
11218
- }
11219
- );
11220
- const comboboxData = useComboboxData({
11221
- queryKey: ["promotions", "combobox", promoIds],
11222
- queryFn: async (params) => {
11223
- return await sdk.admin.promotion.list({
11224
- ...params,
11225
- id: {
11226
- $nin: promoIds
11227
- }
11228
- });
11159
+ const hasUneditableRows = getHasUneditableRows(metadata);
11160
+ const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
11161
+ const form = useForm({
11162
+ defaultValues: {
11163
+ metadata: getDefaultValues(metadata)
11229
11164
  },
11230
- getOptions: (data) => {
11231
- return data.promotions.map((promotion) => ({
11232
- label: promotion.code,
11233
- value: promotion.code
11234
- }));
11235
- }
11165
+ resolver: zodResolver(MetadataSchema)
11236
11166
  });
11237
- const add = async (value) => {
11238
- if (!value) {
11239
- return;
11240
- }
11241
- addPromotions(
11167
+ const handleSubmit = form.handleSubmit(async (data) => {
11168
+ const parsedData = parseValues(data);
11169
+ await mutateAsync(
11242
11170
  {
11243
- promo_codes: [value]
11171
+ metadata: parsedData
11244
11172
  },
11245
11173
  {
11246
- onError: (e) => {
11247
- toast.error(e.message);
11248
- comboboxData.onSearchValueChange("");
11249
- setComboboxValue("");
11250
- },
11251
11174
  onSuccess: () => {
11252
- comboboxData.onSearchValueChange("");
11253
- setComboboxValue("");
11175
+ toast.success("Metadata updated");
11176
+ handleSuccess();
11177
+ },
11178
+ onError: (error) => {
11179
+ toast.error(error.message);
11254
11180
  }
11255
11181
  }
11256
11182
  );
11257
- };
11258
- const { mutateAsync: confirmOrderEdit } = useDraftOrderConfirmEdit(preview.id);
11259
- const { mutateAsync: requestOrderEdit } = useOrderEditRequest(preview.id);
11260
- const onSubmit = async () => {
11261
- setIsSubmitting(true);
11262
- let requestSucceeded = false;
11263
- await requestOrderEdit(void 0, {
11264
- onError: (e) => {
11265
- toast.error(e.message);
11266
- },
11267
- onSuccess: () => {
11268
- requestSucceeded = true;
11269
- }
11270
- });
11271
- if (!requestSucceeded) {
11272
- setIsSubmitting(false);
11273
- return;
11183
+ });
11184
+ const { fields, insert, remove } = useFieldArray({
11185
+ control: form.control,
11186
+ name: "metadata"
11187
+ });
11188
+ function deleteRow(index) {
11189
+ remove(index);
11190
+ if (fields.length === 1) {
11191
+ insert(0, {
11192
+ key: "",
11193
+ value: "",
11194
+ disabled: false
11195
+ });
11274
11196
  }
11275
- await confirmOrderEdit(void 0, {
11276
- onError: (e) => {
11277
- toast.error(e.message);
11278
- },
11279
- onSuccess: () => {
11280
- handleSuccess();
11281
- },
11282
- onSettled: () => {
11283
- setIsSubmitting(false);
11284
- }
11197
+ }
11198
+ function insertRow(index, position) {
11199
+ insert(index + (position === "above" ? 0 : 1), {
11200
+ key: "",
11201
+ value: "",
11202
+ disabled: false
11285
11203
  });
11286
- };
11287
- if (isError) {
11288
- throw error;
11289
11204
  }
11290
- return /* @__PURE__ */ jsxs(KeyboundForm, { className: "flex flex-1 flex-col", onSubmit, children: [
11291
- /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
11292
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
11293
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
11294
- /* @__PURE__ */ jsx(Label$1, { size: "small", weight: "plus", htmlFor: "promotion-combobox", children: "Apply promotions" }),
11295
- /* @__PURE__ */ jsx(Hint$1, { id: "promotion-combobox-hint", children: "Manage promotions that should be applied to the order." })
11205
+ return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
11206
+ KeyboundForm,
11207
+ {
11208
+ onSubmit: handleSubmit,
11209
+ className: "flex flex-1 flex-col overflow-hidden",
11210
+ children: [
11211
+ /* @__PURE__ */ jsxs(RouteDrawer.Body, { className: "flex flex-1 flex-col gap-y-8 overflow-y-auto", children: [
11212
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-1 divide-y rounded-lg", children: [
11213
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle grid grid-cols-2 divide-x rounded-t-lg", children: [
11214
+ /* @__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" }) }),
11215
+ /* @__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" }) })
11216
+ ] }),
11217
+ fields.map((field, index) => {
11218
+ const isDisabled = field.disabled || false;
11219
+ let placeholder = "-";
11220
+ if (typeof field.value === "object") {
11221
+ placeholder = "{ ... }";
11222
+ }
11223
+ if (Array.isArray(field.value)) {
11224
+ placeholder = "[ ... ]";
11225
+ }
11226
+ return /* @__PURE__ */ jsx(
11227
+ ConditionalTooltip,
11228
+ {
11229
+ showTooltip: isDisabled,
11230
+ content: "This row is disabled because it contains non-primitive data.",
11231
+ children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
11232
+ /* @__PURE__ */ jsxs(
11233
+ "div",
11234
+ {
11235
+ className: clx("grid grid-cols-2 divide-x", {
11236
+ "overflow-hidden rounded-b-lg": index === fields.length - 1
11237
+ }),
11238
+ children: [
11239
+ /* @__PURE__ */ jsx(
11240
+ Form$2.Field,
11241
+ {
11242
+ control: form.control,
11243
+ name: `metadata.${index}.key`,
11244
+ render: ({ field: field2 }) => {
11245
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11246
+ GridInput,
11247
+ {
11248
+ "aria-labelledby": METADATA_KEY_LABEL_ID,
11249
+ ...field2,
11250
+ disabled: isDisabled,
11251
+ placeholder: "Key"
11252
+ }
11253
+ ) }) });
11254
+ }
11255
+ }
11256
+ ),
11257
+ /* @__PURE__ */ jsx(
11258
+ Form$2.Field,
11259
+ {
11260
+ control: form.control,
11261
+ name: `metadata.${index}.value`,
11262
+ render: ({ field: { value, ...field2 } }) => {
11263
+ return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
11264
+ GridInput,
11265
+ {
11266
+ "aria-labelledby": METADATA_VALUE_LABEL_ID,
11267
+ ...field2,
11268
+ value: isDisabled ? placeholder : value,
11269
+ disabled: isDisabled,
11270
+ placeholder: "Value"
11271
+ }
11272
+ ) }) });
11273
+ }
11274
+ }
11275
+ )
11276
+ ]
11277
+ }
11278
+ ),
11279
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
11280
+ /* @__PURE__ */ jsx(
11281
+ DropdownMenu.Trigger,
11282
+ {
11283
+ className: clx(
11284
+ "invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
11285
+ {
11286
+ hidden: isDisabled
11287
+ }
11288
+ ),
11289
+ disabled: isDisabled,
11290
+ asChild: true,
11291
+ children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
11292
+ }
11293
+ ),
11294
+ /* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
11295
+ /* @__PURE__ */ jsxs(
11296
+ DropdownMenu.Item,
11297
+ {
11298
+ className: "gap-x-2",
11299
+ onClick: () => insertRow(index, "above"),
11300
+ children: [
11301
+ /* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
11302
+ "Insert row above"
11303
+ ]
11304
+ }
11305
+ ),
11306
+ /* @__PURE__ */ jsxs(
11307
+ DropdownMenu.Item,
11308
+ {
11309
+ className: "gap-x-2",
11310
+ onClick: () => insertRow(index, "below"),
11311
+ children: [
11312
+ /* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
11313
+ "Insert row below"
11314
+ ]
11315
+ }
11316
+ ),
11317
+ /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
11318
+ /* @__PURE__ */ jsxs(
11319
+ DropdownMenu.Item,
11320
+ {
11321
+ className: "gap-x-2",
11322
+ onClick: () => deleteRow(index),
11323
+ children: [
11324
+ /* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
11325
+ "Delete row"
11326
+ ]
11327
+ }
11328
+ )
11329
+ ] })
11330
+ ] })
11331
+ ] })
11332
+ },
11333
+ field.id
11334
+ );
11335
+ })
11336
+ ] }),
11337
+ 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." })
11296
11338
  ] }),
11297
- /* @__PURE__ */ jsx(
11298
- Combobox,
11299
- {
11300
- id: "promotion-combobox",
11301
- "aria-describedby": "promotion-combobox-hint",
11302
- isFetchingNextPage: comboboxData.isFetchingNextPage,
11303
- fetchNextPage: comboboxData.fetchNextPage,
11304
- options: comboboxData.options,
11305
- onSearchValueChange: comboboxData.onSearchValueChange,
11306
- searchValue: comboboxData.searchValue,
11307
- disabled: comboboxData.disabled || isAddingPromotions,
11308
- onChange: add,
11309
- value: comboboxValue
11310
- }
11311
- )
11312
- ] }),
11313
- /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
11314
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: promotions == null ? void 0 : promotions.map((promotion) => /* @__PURE__ */ jsx(
11315
- PromotionItem,
11316
- {
11317
- promotion,
11318
- orderId: preview.id,
11319
- isLoading: isPending
11320
- },
11321
- promotion.id
11322
- )) })
11323
- ] }) }),
11324
- /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
11325
- /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
11326
- /* @__PURE__ */ jsx(
11327
- Button,
11328
- {
11329
- size: "small",
11330
- type: "submit",
11331
- isLoading: isSubmitting || isAddingPromotions,
11332
- children: "Save"
11333
- }
11339
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11340
+ /* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
11341
+ /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
11342
+ ] }) })
11343
+ ]
11344
+ }
11345
+ ) });
11346
+ };
11347
+ const GridInput = forwardRef(({ className, ...props }, ref) => {
11348
+ return /* @__PURE__ */ jsx(
11349
+ "input",
11350
+ {
11351
+ ref,
11352
+ ...props,
11353
+ autoComplete: "off",
11354
+ className: clx(
11355
+ "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",
11356
+ className
11334
11357
  )
11358
+ }
11359
+ );
11360
+ });
11361
+ GridInput.displayName = "MetadataForm.GridInput";
11362
+ const PlaceholderInner = () => {
11363
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
11364
+ /* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
11365
+ /* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
11366
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
11367
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
11335
11368
  ] }) })
11336
11369
  ] });
11337
11370
  };
11338
- const PromotionItem = ({
11339
- promotion,
11340
- orderId,
11341
- isLoading
11342
- }) => {
11343
- var _a;
11344
- const { mutateAsync: removePromotions, isPending } = useDraftOrderRemovePromotions(orderId);
11345
- const onRemove = async () => {
11346
- removePromotions(
11347
- {
11348
- promo_codes: [promotion.code]
11349
- },
11371
+ const EDITABLE_TYPES = ["string", "number", "boolean"];
11372
+ function getDefaultValues(metadata) {
11373
+ if (!metadata || !Object.keys(metadata).length) {
11374
+ return [
11350
11375
  {
11351
- onError: (e) => {
11352
- toast.error(e.message);
11353
- }
11376
+ key: "",
11377
+ value: "",
11378
+ disabled: false
11354
11379
  }
11355
- );
11356
- };
11357
- const displayValue = getDisplayValue(promotion);
11358
- return /* @__PURE__ */ jsxs(
11359
- "div",
11360
- {
11361
- className: clx(
11362
- "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
11363
- {
11364
- "animate-pulse": isLoading
11365
- }
11366
- ),
11367
- children: [
11368
- /* @__PURE__ */ jsxs("div", { children: [
11369
- /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: promotion.code }),
11370
- /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle flex items-center gap-1.5", children: [
11371
- displayValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
11372
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: displayValue }),
11373
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "·" })
11374
- ] }),
11375
- /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "capitalize", children: (_a = promotion.application_method) == null ? void 0 : _a.allocation })
11376
- ] })
11377
- ] }),
11378
- /* @__PURE__ */ jsx(
11379
- IconButton,
11380
- {
11381
- size: "small",
11382
- type: "button",
11383
- variant: "transparent",
11384
- onClick: onRemove,
11385
- isLoading: isPending || isLoading,
11386
- children: /* @__PURE__ */ jsx(XMark, {})
11387
- }
11388
- )
11389
- ]
11390
- },
11391
- promotion.id
11392
- );
11393
- };
11394
- function getDisplayValue(promotion) {
11395
- var _a, _b, _c, _d;
11396
- const value = (_a = promotion.application_method) == null ? void 0 : _a.value;
11397
- if (!value) {
11398
- return null;
11380
+ ];
11399
11381
  }
11400
- if (((_b = promotion.application_method) == null ? void 0 : _b.type) === "fixed") {
11401
- const currency = (_c = promotion.application_method) == null ? void 0 : _c.currency_code;
11402
- if (!currency) {
11403
- return null;
11382
+ return Object.entries(metadata).map(([key, value]) => {
11383
+ if (!EDITABLE_TYPES.includes(typeof value)) {
11384
+ return {
11385
+ key,
11386
+ value,
11387
+ disabled: true
11388
+ };
11404
11389
  }
11405
- return getLocaleAmount(value, currency);
11406
- } else if (((_d = promotion.application_method) == null ? void 0 : _d.type) === "percentage") {
11407
- return formatPercentage(value);
11408
- }
11409
- return null;
11390
+ let stringValue = value;
11391
+ if (typeof value !== "string") {
11392
+ stringValue = JSON.stringify(value);
11393
+ }
11394
+ return {
11395
+ key,
11396
+ value: stringValue,
11397
+ original_key: key
11398
+ };
11399
+ });
11410
11400
  }
11411
- const formatter = new Intl.NumberFormat([], {
11412
- style: "percent",
11413
- minimumFractionDigits: 2
11414
- });
11415
- const formatPercentage = (value, isPercentageValue = false) => {
11416
- let val = value || 0;
11417
- if (!isPercentageValue) {
11418
- val = val / 100;
11401
+ function parseValues(values) {
11402
+ const metadata = values.metadata;
11403
+ const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
11404
+ if (isEmpty) {
11405
+ return null;
11419
11406
  }
11420
- return formatter.format(val);
11421
- };
11422
- function getPromotionIds(items, shippingMethods) {
11423
- const promotionIds = /* @__PURE__ */ new Set();
11424
- for (const item of items) {
11425
- if (item.adjustments) {
11426
- for (const adjustment of item.adjustments) {
11427
- if (adjustment.promotion_id) {
11428
- promotionIds.add(adjustment.promotion_id);
11429
- }
11430
- }
11407
+ const update = {};
11408
+ metadata.forEach((field) => {
11409
+ let key = field.key;
11410
+ let value = field.value;
11411
+ const disabled = field.disabled;
11412
+ if (!key || !value) {
11413
+ return;
11431
11414
  }
11432
- }
11433
- for (const shippingMethod of shippingMethods) {
11434
- if (shippingMethod.adjustments) {
11435
- for (const adjustment of shippingMethod.adjustments) {
11436
- if (adjustment.promotion_id) {
11437
- promotionIds.add(adjustment.promotion_id);
11438
- }
11415
+ if (disabled) {
11416
+ update[key] = value;
11417
+ return;
11418
+ }
11419
+ key = key.trim();
11420
+ value = value.trim();
11421
+ if (value === "true") {
11422
+ update[key] = true;
11423
+ } else if (value === "false") {
11424
+ update[key] = false;
11425
+ } else {
11426
+ const parsedNumber = parseFloat(value);
11427
+ if (!isNaN(parsedNumber)) {
11428
+ update[key] = parsedNumber;
11429
+ } else {
11430
+ update[key] = value;
11439
11431
  }
11440
11432
  }
11433
+ });
11434
+ return update;
11435
+ }
11436
+ function getHasUneditableRows(metadata) {
11437
+ if (!metadata) {
11438
+ return false;
11441
11439
  }
11442
- return Array.from(promotionIds);
11440
+ return Object.values(metadata).some(
11441
+ (value) => !EDITABLE_TYPES.includes(typeof value)
11442
+ );
11443
11443
  }
11444
11444
  const SalesChannel = () => {
11445
11445
  const { id } = useParams();
@@ -13069,14 +13069,14 @@ const routeModule = {
13069
13069
  Component: Items,
13070
13070
  path: "/draft-orders/:id/items"
13071
13071
  },
13072
- {
13073
- Component: Metadata,
13074
- path: "/draft-orders/:id/metadata"
13075
- },
13076
13072
  {
13077
13073
  Component: Promotions,
13078
13074
  path: "/draft-orders/:id/promotions"
13079
13075
  },
13076
+ {
13077
+ Component: Metadata,
13078
+ path: "/draft-orders/:id/metadata"
13079
+ },
13080
13080
  {
13081
13081
  Component: SalesChannel,
13082
13082
  path: "/draft-orders/:id/sales-channel"