@medusajs/draft-order 2.10.4-preview-20251010210154 → 2.10.4-preview-20251011030926

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