@medusajs/draft-order 2.11.0-snapshot-20251017170018 → 2.11.0-snapshot-20251019075109
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.
- package/.medusa/server/src/admin/index.js +561 -561
- package/.medusa/server/src/admin/index.mjs +562 -562
- package/package.json +16 -16
|
@@ -4,7 +4,7 @@ import { Tooltip, DropdownMenu, clx, IconButton, useDataTable, DataTable as Data
|
|
|
4
4
|
import { useQuery, useQueryClient, useMutation, keepPreviousData, useInfiniteQuery } from "@tanstack/react-query";
|
|
5
5
|
import React, { useState, useCallback, useMemo, Fragment, createContext, forwardRef, useId, useContext, useTransition, useRef, useImperativeHandle, useDeferredValue, useEffect, Suspense } from "react";
|
|
6
6
|
import { useSearchParams, Link, useNavigate, Outlet, useBlocker, useLocation, useParams } from "react-router-dom";
|
|
7
|
-
import { EllipsisHorizontal, XMark, InformationCircleSolid, XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini, ExclamationCircleSolid, ArrowPath, FlyingBox, CurrencyDollar, Envelope, Channels, Trash, ArrowUpRightOnBox, TriangleDownMini, Check, SquareTwoStack, Photo, TriangleRightMini, Shopping, Buildings, TruckFast, Plus, ReceiptPercent,
|
|
7
|
+
import { EllipsisHorizontal, XMark, InformationCircleSolid, XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini, ExclamationCircleSolid, ArrowPath, FlyingBox, CurrencyDollar, Envelope, Channels, Trash, ArrowUpRightOnBox, TriangleDownMini, Check, SquareTwoStack, Photo, TriangleRightMini, Shopping, Buildings, TruckFast, Plus, ReceiptPercent, Minus, PencilSquare, EllipsisVertical, ArrowUpMini, ArrowDownMini } from "@medusajs/icons";
|
|
8
8
|
import Medusa from "@medusajs/js-sdk";
|
|
9
9
|
import { format, formatDistance, sub, subDays, subMonths } from "date-fns";
|
|
10
10
|
import { enUS } from "date-fns/locale";
|
|
@@ -9588,74 +9588,6 @@ const CustomItemsForm = () => {
|
|
|
9588
9588
|
const schema$5 = objectType({
|
|
9589
9589
|
email: stringType().email()
|
|
9590
9590
|
});
|
|
9591
|
-
const Email = () => {
|
|
9592
|
-
const { id } = useParams();
|
|
9593
|
-
const { order, isPending, isError, error } = useOrder(id, {
|
|
9594
|
-
fields: "+email"
|
|
9595
|
-
});
|
|
9596
|
-
if (isError) {
|
|
9597
|
-
throw error;
|
|
9598
|
-
}
|
|
9599
|
-
const isReady = !isPending && !!order;
|
|
9600
|
-
return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
|
|
9601
|
-
/* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
|
|
9602
|
-
/* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
|
|
9603
|
-
/* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
|
|
9604
|
-
] }),
|
|
9605
|
-
isReady && /* @__PURE__ */ jsx(EmailForm, { order })
|
|
9606
|
-
] });
|
|
9607
|
-
};
|
|
9608
|
-
const EmailForm = ({ order }) => {
|
|
9609
|
-
const form = useForm({
|
|
9610
|
-
defaultValues: {
|
|
9611
|
-
email: order.email ?? ""
|
|
9612
|
-
},
|
|
9613
|
-
resolver: zodResolver(schema$4)
|
|
9614
|
-
});
|
|
9615
|
-
const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
|
|
9616
|
-
const { handleSuccess } = useRouteModal();
|
|
9617
|
-
const onSubmit = form.handleSubmit(async (data) => {
|
|
9618
|
-
await mutateAsync(
|
|
9619
|
-
{ email: data.email },
|
|
9620
|
-
{
|
|
9621
|
-
onSuccess: () => {
|
|
9622
|
-
handleSuccess();
|
|
9623
|
-
},
|
|
9624
|
-
onError: (error) => {
|
|
9625
|
-
toast.error(error.message);
|
|
9626
|
-
}
|
|
9627
|
-
}
|
|
9628
|
-
);
|
|
9629
|
-
});
|
|
9630
|
-
return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
|
|
9631
|
-
KeyboundForm,
|
|
9632
|
-
{
|
|
9633
|
-
className: "flex flex-1 flex-col overflow-hidden",
|
|
9634
|
-
onSubmit,
|
|
9635
|
-
children: [
|
|
9636
|
-
/* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
9637
|
-
Form$2.Field,
|
|
9638
|
-
{
|
|
9639
|
-
control: form.control,
|
|
9640
|
-
name: "email",
|
|
9641
|
-
render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
|
|
9642
|
-
/* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
|
|
9643
|
-
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
|
|
9644
|
-
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
9645
|
-
] })
|
|
9646
|
-
}
|
|
9647
|
-
) }),
|
|
9648
|
-
/* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
9649
|
-
/* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
|
|
9650
|
-
/* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
|
|
9651
|
-
] }) })
|
|
9652
|
-
]
|
|
9653
|
-
}
|
|
9654
|
-
) });
|
|
9655
|
-
};
|
|
9656
|
-
const schema$4 = objectType({
|
|
9657
|
-
email: stringType().email()
|
|
9658
|
-
});
|
|
9659
9591
|
const BillingAddress = () => {
|
|
9660
9592
|
const { id } = useParams();
|
|
9661
9593
|
const { order, isPending, isError, error } = useOrder(id, {
|
|
@@ -9688,7 +9620,7 @@ const BillingAddressForm = ({ order }) => {
|
|
|
9688
9620
|
postal_code: ((_i = order.billing_address) == null ? void 0 : _i.postal_code) ?? "",
|
|
9689
9621
|
phone: ((_j = order.billing_address) == null ? void 0 : _j.phone) ?? ""
|
|
9690
9622
|
},
|
|
9691
|
-
resolver: zodResolver(schema$
|
|
9623
|
+
resolver: zodResolver(schema$4)
|
|
9692
9624
|
});
|
|
9693
9625
|
const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
|
|
9694
9626
|
const { handleSuccess } = useRouteModal();
|
|
@@ -9845,55 +9777,11 @@ const BillingAddressForm = ({ order }) => {
|
|
|
9845
9777
|
}
|
|
9846
9778
|
) });
|
|
9847
9779
|
};
|
|
9848
|
-
const schema$
|
|
9849
|
-
const
|
|
9850
|
-
({ variant = "tip", label, className, children, ...props }, ref) => {
|
|
9851
|
-
const labelValue = label || (variant === "warning" ? "Warning" : "Tip");
|
|
9852
|
-
return /* @__PURE__ */ jsxs(
|
|
9853
|
-
"div",
|
|
9854
|
-
{
|
|
9855
|
-
ref,
|
|
9856
|
-
className: clx(
|
|
9857
|
-
"bg-ui-bg-component txt-small text-ui-fg-subtle grid grid-cols-[4px_1fr] items-start gap-3 rounded-lg border p-3",
|
|
9858
|
-
className
|
|
9859
|
-
),
|
|
9860
|
-
...props,
|
|
9861
|
-
children: [
|
|
9862
|
-
/* @__PURE__ */ jsx(
|
|
9863
|
-
"div",
|
|
9864
|
-
{
|
|
9865
|
-
role: "presentation",
|
|
9866
|
-
className: clx("w-4px bg-ui-tag-neutral-icon h-full rounded-full", {
|
|
9867
|
-
"bg-ui-tag-orange-icon": variant === "warning"
|
|
9868
|
-
})
|
|
9869
|
-
}
|
|
9870
|
-
),
|
|
9871
|
-
/* @__PURE__ */ jsxs("div", { className: "text-pretty", children: [
|
|
9872
|
-
/* @__PURE__ */ jsxs("strong", { className: "txt-small-plus text-ui-fg-base", children: [
|
|
9873
|
-
labelValue,
|
|
9874
|
-
":"
|
|
9875
|
-
] }),
|
|
9876
|
-
" ",
|
|
9877
|
-
children
|
|
9878
|
-
] })
|
|
9879
|
-
]
|
|
9880
|
-
}
|
|
9881
|
-
);
|
|
9882
|
-
}
|
|
9883
|
-
);
|
|
9884
|
-
InlineTip.displayName = "InlineTip";
|
|
9885
|
-
const MetadataFieldSchema = objectType({
|
|
9886
|
-
key: stringType(),
|
|
9887
|
-
disabled: booleanType().optional(),
|
|
9888
|
-
value: anyType()
|
|
9889
|
-
});
|
|
9890
|
-
const MetadataSchema = objectType({
|
|
9891
|
-
metadata: arrayType(MetadataFieldSchema)
|
|
9892
|
-
});
|
|
9893
|
-
const Metadata = () => {
|
|
9780
|
+
const schema$4 = addressSchema;
|
|
9781
|
+
const Email = () => {
|
|
9894
9782
|
const { id } = useParams();
|
|
9895
9783
|
const { order, isPending, isError, error } = useOrder(id, {
|
|
9896
|
-
fields: "
|
|
9784
|
+
fields: "+email"
|
|
9897
9785
|
});
|
|
9898
9786
|
if (isError) {
|
|
9899
9787
|
throw error;
|
|
@@ -9901,33 +9789,26 @@ const Metadata = () => {
|
|
|
9901
9789
|
const isReady = !isPending && !!order;
|
|
9902
9790
|
return /* @__PURE__ */ jsxs(RouteDrawer, { children: [
|
|
9903
9791
|
/* @__PURE__ */ jsxs(RouteDrawer.Header, { children: [
|
|
9904
|
-
/* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "
|
|
9905
|
-
/* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "
|
|
9792
|
+
/* @__PURE__ */ jsx(RouteDrawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Edit Email" }) }),
|
|
9793
|
+
/* @__PURE__ */ jsx(RouteDrawer.Description, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Edit the email for the draft order" }) })
|
|
9906
9794
|
] }),
|
|
9907
|
-
|
|
9795
|
+
isReady && /* @__PURE__ */ jsx(EmailForm, { order })
|
|
9908
9796
|
] });
|
|
9909
9797
|
};
|
|
9910
|
-
const
|
|
9911
|
-
const METADATA_VALUE_LABEL_ID = "metadata-form-value-label";
|
|
9912
|
-
const MetadataForm = ({ orderId, metadata }) => {
|
|
9913
|
-
const { handleSuccess } = useRouteModal();
|
|
9914
|
-
const hasUneditableRows = getHasUneditableRows(metadata);
|
|
9915
|
-
const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
|
|
9798
|
+
const EmailForm = ({ order }) => {
|
|
9916
9799
|
const form = useForm({
|
|
9917
9800
|
defaultValues: {
|
|
9918
|
-
|
|
9801
|
+
email: order.email ?? ""
|
|
9919
9802
|
},
|
|
9920
|
-
resolver: zodResolver(
|
|
9803
|
+
resolver: zodResolver(schema$3)
|
|
9921
9804
|
});
|
|
9922
|
-
const
|
|
9923
|
-
|
|
9805
|
+
const { mutateAsync, isPending } = useUpdateDraftOrder(order.id);
|
|
9806
|
+
const { handleSuccess } = useRouteModal();
|
|
9807
|
+
const onSubmit = form.handleSubmit(async (data) => {
|
|
9924
9808
|
await mutateAsync(
|
|
9925
|
-
{
|
|
9926
|
-
metadata: parsedData
|
|
9927
|
-
},
|
|
9809
|
+
{ email: data.email },
|
|
9928
9810
|
{
|
|
9929
9811
|
onSuccess: () => {
|
|
9930
|
-
toast.success("Metadata updated");
|
|
9931
9812
|
handleSuccess();
|
|
9932
9813
|
},
|
|
9933
9814
|
onError: (error) => {
|
|
@@ -9936,266 +9817,35 @@ const MetadataForm = ({ orderId, metadata }) => {
|
|
|
9936
9817
|
}
|
|
9937
9818
|
);
|
|
9938
9819
|
});
|
|
9939
|
-
const { fields, insert, remove } = useFieldArray({
|
|
9940
|
-
control: form.control,
|
|
9941
|
-
name: "metadata"
|
|
9942
|
-
});
|
|
9943
|
-
function deleteRow(index) {
|
|
9944
|
-
remove(index);
|
|
9945
|
-
if (fields.length === 1) {
|
|
9946
|
-
insert(0, {
|
|
9947
|
-
key: "",
|
|
9948
|
-
value: "",
|
|
9949
|
-
disabled: false
|
|
9950
|
-
});
|
|
9951
|
-
}
|
|
9952
|
-
}
|
|
9953
|
-
function insertRow(index, position) {
|
|
9954
|
-
insert(index + (position === "above" ? 0 : 1), {
|
|
9955
|
-
key: "",
|
|
9956
|
-
value: "",
|
|
9957
|
-
disabled: false
|
|
9958
|
-
});
|
|
9959
|
-
}
|
|
9960
9820
|
return /* @__PURE__ */ jsx(RouteDrawer.Form, { form, children: /* @__PURE__ */ jsxs(
|
|
9961
9821
|
KeyboundForm,
|
|
9962
9822
|
{
|
|
9963
|
-
onSubmit: handleSubmit,
|
|
9964
9823
|
className: "flex flex-1 flex-col overflow-hidden",
|
|
9824
|
+
onSubmit,
|
|
9965
9825
|
children: [
|
|
9966
|
-
/* @__PURE__ */
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
}
|
|
9981
|
-
return /* @__PURE__ */ jsx(
|
|
9982
|
-
ConditionalTooltip,
|
|
9983
|
-
{
|
|
9984
|
-
showTooltip: isDisabled,
|
|
9985
|
-
content: "This row is disabled because it contains non-primitive data.",
|
|
9986
|
-
children: /* @__PURE__ */ jsxs("div", { className: "group/table relative", children: [
|
|
9987
|
-
/* @__PURE__ */ jsxs(
|
|
9988
|
-
"div",
|
|
9989
|
-
{
|
|
9990
|
-
className: clx("grid grid-cols-2 divide-x", {
|
|
9991
|
-
"overflow-hidden rounded-b-lg": index === fields.length - 1
|
|
9992
|
-
}),
|
|
9993
|
-
children: [
|
|
9994
|
-
/* @__PURE__ */ jsx(
|
|
9995
|
-
Form$2.Field,
|
|
9996
|
-
{
|
|
9997
|
-
control: form.control,
|
|
9998
|
-
name: `metadata.${index}.key`,
|
|
9999
|
-
render: ({ field: field2 }) => {
|
|
10000
|
-
return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
|
|
10001
|
-
GridInput,
|
|
10002
|
-
{
|
|
10003
|
-
"aria-labelledby": METADATA_KEY_LABEL_ID,
|
|
10004
|
-
...field2,
|
|
10005
|
-
disabled: isDisabled,
|
|
10006
|
-
placeholder: "Key"
|
|
10007
|
-
}
|
|
10008
|
-
) }) });
|
|
10009
|
-
}
|
|
10010
|
-
}
|
|
10011
|
-
),
|
|
10012
|
-
/* @__PURE__ */ jsx(
|
|
10013
|
-
Form$2.Field,
|
|
10014
|
-
{
|
|
10015
|
-
control: form.control,
|
|
10016
|
-
name: `metadata.${index}.value`,
|
|
10017
|
-
render: ({ field: { value, ...field2 } }) => {
|
|
10018
|
-
return /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
|
|
10019
|
-
GridInput,
|
|
10020
|
-
{
|
|
10021
|
-
"aria-labelledby": METADATA_VALUE_LABEL_ID,
|
|
10022
|
-
...field2,
|
|
10023
|
-
value: isDisabled ? placeholder : value,
|
|
10024
|
-
disabled: isDisabled,
|
|
10025
|
-
placeholder: "Value"
|
|
10026
|
-
}
|
|
10027
|
-
) }) });
|
|
10028
|
-
}
|
|
10029
|
-
}
|
|
10030
|
-
)
|
|
10031
|
-
]
|
|
10032
|
-
}
|
|
10033
|
-
),
|
|
10034
|
-
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
10035
|
-
/* @__PURE__ */ jsx(
|
|
10036
|
-
DropdownMenu.Trigger,
|
|
10037
|
-
{
|
|
10038
|
-
className: clx(
|
|
10039
|
-
"invisible absolute inset-y-0 -right-2.5 my-auto group-hover/table:visible data-[state='open']:visible",
|
|
10040
|
-
{
|
|
10041
|
-
hidden: isDisabled
|
|
10042
|
-
}
|
|
10043
|
-
),
|
|
10044
|
-
disabled: isDisabled,
|
|
10045
|
-
asChild: true,
|
|
10046
|
-
children: /* @__PURE__ */ jsx(IconButton, { size: "2xsmall", children: /* @__PURE__ */ jsx(EllipsisVertical, {}) })
|
|
10047
|
-
}
|
|
10048
|
-
),
|
|
10049
|
-
/* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
|
|
10050
|
-
/* @__PURE__ */ jsxs(
|
|
10051
|
-
DropdownMenu.Item,
|
|
10052
|
-
{
|
|
10053
|
-
className: "gap-x-2",
|
|
10054
|
-
onClick: () => insertRow(index, "above"),
|
|
10055
|
-
children: [
|
|
10056
|
-
/* @__PURE__ */ jsx(ArrowUpMini, { className: "text-ui-fg-subtle" }),
|
|
10057
|
-
"Insert row above"
|
|
10058
|
-
]
|
|
10059
|
-
}
|
|
10060
|
-
),
|
|
10061
|
-
/* @__PURE__ */ jsxs(
|
|
10062
|
-
DropdownMenu.Item,
|
|
10063
|
-
{
|
|
10064
|
-
className: "gap-x-2",
|
|
10065
|
-
onClick: () => insertRow(index, "below"),
|
|
10066
|
-
children: [
|
|
10067
|
-
/* @__PURE__ */ jsx(ArrowDownMini, { className: "text-ui-fg-subtle" }),
|
|
10068
|
-
"Insert row below"
|
|
10069
|
-
]
|
|
10070
|
-
}
|
|
10071
|
-
),
|
|
10072
|
-
/* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
|
|
10073
|
-
/* @__PURE__ */ jsxs(
|
|
10074
|
-
DropdownMenu.Item,
|
|
10075
|
-
{
|
|
10076
|
-
className: "gap-x-2",
|
|
10077
|
-
onClick: () => deleteRow(index),
|
|
10078
|
-
children: [
|
|
10079
|
-
/* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
|
|
10080
|
-
"Delete row"
|
|
10081
|
-
]
|
|
10082
|
-
}
|
|
10083
|
-
)
|
|
10084
|
-
] })
|
|
10085
|
-
] })
|
|
10086
|
-
] })
|
|
10087
|
-
},
|
|
10088
|
-
field.id
|
|
10089
|
-
);
|
|
10090
|
-
})
|
|
10091
|
-
] }),
|
|
10092
|
-
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." })
|
|
10093
|
-
] }),
|
|
10094
|
-
/* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
10095
|
-
/* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
|
|
9826
|
+
/* @__PURE__ */ jsx(RouteDrawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
9827
|
+
Form$2.Field,
|
|
9828
|
+
{
|
|
9829
|
+
control: form.control,
|
|
9830
|
+
name: "email",
|
|
9831
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(Form$2.Item, { children: [
|
|
9832
|
+
/* @__PURE__ */ jsx(Form$2.Label, { children: "Email" }),
|
|
9833
|
+
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
|
|
9834
|
+
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
9835
|
+
] })
|
|
9836
|
+
}
|
|
9837
|
+
) }),
|
|
9838
|
+
/* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
9839
|
+
/* @__PURE__ */ jsx(RouteDrawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
|
|
10096
9840
|
/* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading: isPending, children: "Save" })
|
|
10097
9841
|
] }) })
|
|
10098
9842
|
]
|
|
10099
9843
|
}
|
|
10100
9844
|
) });
|
|
10101
9845
|
};
|
|
10102
|
-
const
|
|
10103
|
-
|
|
10104
|
-
"input",
|
|
10105
|
-
{
|
|
10106
|
-
ref,
|
|
10107
|
-
...props,
|
|
10108
|
-
autoComplete: "off",
|
|
10109
|
-
className: clx(
|
|
10110
|
-
"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",
|
|
10111
|
-
className
|
|
10112
|
-
)
|
|
10113
|
-
}
|
|
10114
|
-
);
|
|
9846
|
+
const schema$3 = objectType({
|
|
9847
|
+
email: stringType().email()
|
|
10115
9848
|
});
|
|
10116
|
-
GridInput.displayName = "MetadataForm.GridInput";
|
|
10117
|
-
const PlaceholderInner = () => {
|
|
10118
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
|
|
10119
|
-
/* @__PURE__ */ jsx(RouteDrawer.Body, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[148ox] w-full rounded-lg" }) }),
|
|
10120
|
-
/* @__PURE__ */ jsx(RouteDrawer.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
10121
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" }),
|
|
10122
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-12 rounded-md" })
|
|
10123
|
-
] }) })
|
|
10124
|
-
] });
|
|
10125
|
-
};
|
|
10126
|
-
const EDITABLE_TYPES = ["string", "number", "boolean"];
|
|
10127
|
-
function getDefaultValues(metadata) {
|
|
10128
|
-
if (!metadata || !Object.keys(metadata).length) {
|
|
10129
|
-
return [
|
|
10130
|
-
{
|
|
10131
|
-
key: "",
|
|
10132
|
-
value: "",
|
|
10133
|
-
disabled: false
|
|
10134
|
-
}
|
|
10135
|
-
];
|
|
10136
|
-
}
|
|
10137
|
-
return Object.entries(metadata).map(([key, value]) => {
|
|
10138
|
-
if (!EDITABLE_TYPES.includes(typeof value)) {
|
|
10139
|
-
return {
|
|
10140
|
-
key,
|
|
10141
|
-
value,
|
|
10142
|
-
disabled: true
|
|
10143
|
-
};
|
|
10144
|
-
}
|
|
10145
|
-
let stringValue = value;
|
|
10146
|
-
if (typeof value !== "string") {
|
|
10147
|
-
stringValue = JSON.stringify(value);
|
|
10148
|
-
}
|
|
10149
|
-
return {
|
|
10150
|
-
key,
|
|
10151
|
-
value: stringValue,
|
|
10152
|
-
original_key: key
|
|
10153
|
-
};
|
|
10154
|
-
});
|
|
10155
|
-
}
|
|
10156
|
-
function parseValues(values) {
|
|
10157
|
-
const metadata = values.metadata;
|
|
10158
|
-
const isEmpty = !metadata.length || metadata.length === 1 && !metadata[0].key && !metadata[0].value;
|
|
10159
|
-
if (isEmpty) {
|
|
10160
|
-
return null;
|
|
10161
|
-
}
|
|
10162
|
-
const update = {};
|
|
10163
|
-
metadata.forEach((field) => {
|
|
10164
|
-
let key = field.key;
|
|
10165
|
-
let value = field.value;
|
|
10166
|
-
const disabled = field.disabled;
|
|
10167
|
-
if (!key || !value) {
|
|
10168
|
-
return;
|
|
10169
|
-
}
|
|
10170
|
-
if (disabled) {
|
|
10171
|
-
update[key] = value;
|
|
10172
|
-
return;
|
|
10173
|
-
}
|
|
10174
|
-
key = key.trim();
|
|
10175
|
-
value = value.trim();
|
|
10176
|
-
if (value === "true") {
|
|
10177
|
-
update[key] = true;
|
|
10178
|
-
} else if (value === "false") {
|
|
10179
|
-
update[key] = false;
|
|
10180
|
-
} else {
|
|
10181
|
-
const parsedNumber = parseFloat(value);
|
|
10182
|
-
if (!isNaN(parsedNumber)) {
|
|
10183
|
-
update[key] = parsedNumber;
|
|
10184
|
-
} else {
|
|
10185
|
-
update[key] = value;
|
|
10186
|
-
}
|
|
10187
|
-
}
|
|
10188
|
-
});
|
|
10189
|
-
return update;
|
|
10190
|
-
}
|
|
10191
|
-
function getHasUneditableRows(metadata) {
|
|
10192
|
-
if (!metadata) {
|
|
10193
|
-
return false;
|
|
10194
|
-
}
|
|
10195
|
-
return Object.values(metadata).some(
|
|
10196
|
-
(value) => !EDITABLE_TYPES.includes(typeof value)
|
|
10197
|
-
);
|
|
10198
|
-
}
|
|
10199
9849
|
const NumberInput = forwardRef(
|
|
10200
9850
|
({
|
|
10201
9851
|
value,
|
|
@@ -10991,185 +10641,535 @@ const ExistingItemsForm = ({ orderId, items }) => {
|
|
|
10991
10641
|
}
|
|
10992
10642
|
);
|
|
10993
10643
|
};
|
|
10994
|
-
const columnHelper = createDataTableColumnHelper();
|
|
10995
|
-
const useColumns = () => {
|
|
10996
|
-
return useMemo(() => {
|
|
10644
|
+
const columnHelper = createDataTableColumnHelper();
|
|
10645
|
+
const useColumns = () => {
|
|
10646
|
+
return useMemo(() => {
|
|
10647
|
+
return [
|
|
10648
|
+
columnHelper.select(),
|
|
10649
|
+
columnHelper.accessor("product.title", {
|
|
10650
|
+
header: "Product",
|
|
10651
|
+
cell: ({ row }) => {
|
|
10652
|
+
var _a, _b, _c;
|
|
10653
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
10654
|
+
/* @__PURE__ */ jsx(
|
|
10655
|
+
Thumbnail,
|
|
10656
|
+
{
|
|
10657
|
+
thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
|
|
10658
|
+
alt: (_b = row.original.product) == null ? void 0 : _b.title
|
|
10659
|
+
}
|
|
10660
|
+
),
|
|
10661
|
+
/* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
|
|
10662
|
+
] });
|
|
10663
|
+
},
|
|
10664
|
+
enableSorting: true
|
|
10665
|
+
}),
|
|
10666
|
+
columnHelper.accessor("title", {
|
|
10667
|
+
header: "Variant",
|
|
10668
|
+
enableSorting: true
|
|
10669
|
+
}),
|
|
10670
|
+
columnHelper.accessor("sku", {
|
|
10671
|
+
header: "SKU",
|
|
10672
|
+
cell: ({ getValue }) => {
|
|
10673
|
+
return getValue() ?? "-";
|
|
10674
|
+
},
|
|
10675
|
+
enableSorting: true
|
|
10676
|
+
}),
|
|
10677
|
+
columnHelper.accessor("updated_at", {
|
|
10678
|
+
header: "Updated",
|
|
10679
|
+
cell: ({ getValue }) => {
|
|
10680
|
+
return /* @__PURE__ */ jsx(
|
|
10681
|
+
Tooltip,
|
|
10682
|
+
{
|
|
10683
|
+
content: getFullDate({ date: getValue(), includeTime: true }),
|
|
10684
|
+
children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
|
|
10685
|
+
}
|
|
10686
|
+
);
|
|
10687
|
+
},
|
|
10688
|
+
enableSorting: true,
|
|
10689
|
+
sortAscLabel: "Oldest first",
|
|
10690
|
+
sortDescLabel: "Newest first"
|
|
10691
|
+
}),
|
|
10692
|
+
columnHelper.accessor("created_at", {
|
|
10693
|
+
header: "Created",
|
|
10694
|
+
cell: ({ getValue }) => {
|
|
10695
|
+
return /* @__PURE__ */ jsx(
|
|
10696
|
+
Tooltip,
|
|
10697
|
+
{
|
|
10698
|
+
content: getFullDate({ date: getValue(), includeTime: true }),
|
|
10699
|
+
children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
|
|
10700
|
+
}
|
|
10701
|
+
);
|
|
10702
|
+
},
|
|
10703
|
+
enableSorting: true,
|
|
10704
|
+
sortAscLabel: "Oldest first",
|
|
10705
|
+
sortDescLabel: "Newest first"
|
|
10706
|
+
})
|
|
10707
|
+
];
|
|
10708
|
+
}, []);
|
|
10709
|
+
};
|
|
10710
|
+
const CustomItemForm = ({ orderId, currencyCode }) => {
|
|
10711
|
+
const { setIsOpen } = useStackedModal();
|
|
10712
|
+
const { mutateAsync: addItems } = useDraftOrderAddItems(orderId);
|
|
10713
|
+
const form = useForm({
|
|
10714
|
+
defaultValues: {
|
|
10715
|
+
title: "",
|
|
10716
|
+
quantity: 1,
|
|
10717
|
+
unit_price: ""
|
|
10718
|
+
},
|
|
10719
|
+
resolver: zodResolver(customItemSchema)
|
|
10720
|
+
});
|
|
10721
|
+
const onSubmit = form.handleSubmit(async (data) => {
|
|
10722
|
+
await addItems(
|
|
10723
|
+
{
|
|
10724
|
+
items: [
|
|
10725
|
+
{
|
|
10726
|
+
title: data.title,
|
|
10727
|
+
quantity: data.quantity,
|
|
10728
|
+
unit_price: convertNumber(data.unit_price)
|
|
10729
|
+
}
|
|
10730
|
+
]
|
|
10731
|
+
},
|
|
10732
|
+
{
|
|
10733
|
+
onSuccess: () => {
|
|
10734
|
+
setIsOpen(STACKED_MODAL_ID, false);
|
|
10735
|
+
},
|
|
10736
|
+
onError: (e) => {
|
|
10737
|
+
toast.error(e.message);
|
|
10738
|
+
}
|
|
10739
|
+
}
|
|
10740
|
+
);
|
|
10741
|
+
});
|
|
10742
|
+
return /* @__PURE__ */ jsx(Form$2, { ...form, children: /* @__PURE__ */ jsx(KeyboundForm, { onSubmit, children: /* @__PURE__ */ jsxs(StackedFocusModal.Content, { children: [
|
|
10743
|
+
/* @__PURE__ */ jsx(StackedFocusModal.Header, {}),
|
|
10744
|
+
/* @__PURE__ */ jsx(StackedFocusModal.Body, { className: "flex flex-1 flex-col overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[720px] flex-col gap-y-6 px-2 py-16", children: [
|
|
10745
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10746
|
+
/* @__PURE__ */ jsx(StackedFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: "Add custom item" }) }),
|
|
10747
|
+
/* @__PURE__ */ jsx(StackedFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Add a custom item to the order. This will add a new line item that is not associated with an existing product." }) })
|
|
10748
|
+
] }),
|
|
10749
|
+
/* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
|
|
10750
|
+
/* @__PURE__ */ jsx(
|
|
10751
|
+
Form$2.Field,
|
|
10752
|
+
{
|
|
10753
|
+
control: form.control,
|
|
10754
|
+
name: "title",
|
|
10755
|
+
render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
|
|
10756
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10757
|
+
/* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
|
|
10758
|
+
/* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
|
|
10759
|
+
] }),
|
|
10760
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10761
|
+
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
|
|
10762
|
+
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
10763
|
+
] })
|
|
10764
|
+
] }) })
|
|
10765
|
+
}
|
|
10766
|
+
),
|
|
10767
|
+
/* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
|
|
10768
|
+
/* @__PURE__ */ jsx(
|
|
10769
|
+
Form$2.Field,
|
|
10770
|
+
{
|
|
10771
|
+
control: form.control,
|
|
10772
|
+
name: "unit_price",
|
|
10773
|
+
render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
|
|
10774
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10775
|
+
/* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
|
|
10776
|
+
/* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
|
|
10777
|
+
] }),
|
|
10778
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10779
|
+
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
|
|
10780
|
+
CurrencyInput,
|
|
10781
|
+
{
|
|
10782
|
+
symbol: getNativeSymbol(currencyCode),
|
|
10783
|
+
code: currencyCode,
|
|
10784
|
+
onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
|
|
10785
|
+
...field
|
|
10786
|
+
}
|
|
10787
|
+
) }),
|
|
10788
|
+
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
10789
|
+
] })
|
|
10790
|
+
] }) })
|
|
10791
|
+
}
|
|
10792
|
+
),
|
|
10793
|
+
/* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
|
|
10794
|
+
/* @__PURE__ */ jsx(
|
|
10795
|
+
Form$2.Field,
|
|
10796
|
+
{
|
|
10797
|
+
control: form.control,
|
|
10798
|
+
name: "quantity",
|
|
10799
|
+
render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
|
|
10800
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
10801
|
+
/* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
|
|
10802
|
+
/* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
|
|
10803
|
+
] }),
|
|
10804
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
|
|
10805
|
+
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
|
|
10806
|
+
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
10807
|
+
] })
|
|
10808
|
+
] }) })
|
|
10809
|
+
}
|
|
10810
|
+
)
|
|
10811
|
+
] }) }) }),
|
|
10812
|
+
/* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
10813
|
+
/* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
|
|
10814
|
+
/* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
|
|
10815
|
+
] }) })
|
|
10816
|
+
] }) }) });
|
|
10817
|
+
};
|
|
10818
|
+
const customItemSchema = objectType({
|
|
10819
|
+
title: stringType().min(1),
|
|
10820
|
+
quantity: numberType(),
|
|
10821
|
+
unit_price: unionType([numberType(), stringType()])
|
|
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"
|
|
10871
|
+
});
|
|
10872
|
+
if (isError) {
|
|
10873
|
+
throw error;
|
|
10874
|
+
}
|
|
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 })
|
|
10882
|
+
] });
|
|
10883
|
+
};
|
|
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 }) => {
|
|
10887
|
+
const { handleSuccess } = useRouteModal();
|
|
10888
|
+
const hasUneditableRows = getHasUneditableRows(metadata);
|
|
10889
|
+
const { mutateAsync, isPending } = useUpdateDraftOrder(orderId);
|
|
10890
|
+
const form = useForm({
|
|
10891
|
+
defaultValues: {
|
|
10892
|
+
metadata: getDefaultValues(metadata)
|
|
10893
|
+
},
|
|
10894
|
+
resolver: zodResolver(MetadataSchema)
|
|
10895
|
+
});
|
|
10896
|
+
const handleSubmit = form.handleSubmit(async (data) => {
|
|
10897
|
+
const parsedData = parseValues(data);
|
|
10898
|
+
await mutateAsync(
|
|
10899
|
+
{
|
|
10900
|
+
metadata: parsedData
|
|
10901
|
+
},
|
|
10902
|
+
{
|
|
10903
|
+
onSuccess: () => {
|
|
10904
|
+
toast.success("Metadata updated");
|
|
10905
|
+
handleSuccess();
|
|
10906
|
+
},
|
|
10907
|
+
onError: (error) => {
|
|
10908
|
+
toast.error(error.message);
|
|
10909
|
+
}
|
|
10910
|
+
}
|
|
10911
|
+
);
|
|
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
|
+
});
|
|
10925
|
+
}
|
|
10926
|
+
}
|
|
10927
|
+
function insertRow(index, position) {
|
|
10928
|
+
insert(index + (position === "above" ? 0 : 1), {
|
|
10929
|
+
key: "",
|
|
10930
|
+
value: "",
|
|
10931
|
+
disabled: false
|
|
10932
|
+
});
|
|
10933
|
+
}
|
|
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." })
|
|
11067
|
+
] }),
|
|
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
|
|
11086
|
+
)
|
|
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
|
+
] }) })
|
|
11098
|
+
] });
|
|
11099
|
+
};
|
|
11100
|
+
const EDITABLE_TYPES = ["string", "number", "boolean"];
|
|
11101
|
+
function getDefaultValues(metadata) {
|
|
11102
|
+
if (!metadata || !Object.keys(metadata).length) {
|
|
10997
11103
|
return [
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
11004
|
-
/* @__PURE__ */ jsx(
|
|
11005
|
-
Thumbnail,
|
|
11006
|
-
{
|
|
11007
|
-
thumbnail: (_a = row.original.product) == null ? void 0 : _a.thumbnail,
|
|
11008
|
-
alt: (_b = row.original.product) == null ? void 0 : _b.title
|
|
11009
|
-
}
|
|
11010
|
-
),
|
|
11011
|
-
/* @__PURE__ */ jsx("span", { children: (_c = row.original.product) == null ? void 0 : _c.title })
|
|
11012
|
-
] });
|
|
11013
|
-
},
|
|
11014
|
-
enableSorting: true
|
|
11015
|
-
}),
|
|
11016
|
-
columnHelper.accessor("title", {
|
|
11017
|
-
header: "Variant",
|
|
11018
|
-
enableSorting: true
|
|
11019
|
-
}),
|
|
11020
|
-
columnHelper.accessor("sku", {
|
|
11021
|
-
header: "SKU",
|
|
11022
|
-
cell: ({ getValue }) => {
|
|
11023
|
-
return getValue() ?? "-";
|
|
11024
|
-
},
|
|
11025
|
-
enableSorting: true
|
|
11026
|
-
}),
|
|
11027
|
-
columnHelper.accessor("updated_at", {
|
|
11028
|
-
header: "Updated",
|
|
11029
|
-
cell: ({ getValue }) => {
|
|
11030
|
-
return /* @__PURE__ */ jsx(
|
|
11031
|
-
Tooltip,
|
|
11032
|
-
{
|
|
11033
|
-
content: getFullDate({ date: getValue(), includeTime: true }),
|
|
11034
|
-
children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
|
|
11035
|
-
}
|
|
11036
|
-
);
|
|
11037
|
-
},
|
|
11038
|
-
enableSorting: true,
|
|
11039
|
-
sortAscLabel: "Oldest first",
|
|
11040
|
-
sortDescLabel: "Newest first"
|
|
11041
|
-
}),
|
|
11042
|
-
columnHelper.accessor("created_at", {
|
|
11043
|
-
header: "Created",
|
|
11044
|
-
cell: ({ getValue }) => {
|
|
11045
|
-
return /* @__PURE__ */ jsx(
|
|
11046
|
-
Tooltip,
|
|
11047
|
-
{
|
|
11048
|
-
content: getFullDate({ date: getValue(), includeTime: true }),
|
|
11049
|
-
children: /* @__PURE__ */ jsx("span", { children: getFullDate({ date: getValue() }) })
|
|
11050
|
-
}
|
|
11051
|
-
);
|
|
11052
|
-
},
|
|
11053
|
-
enableSorting: true,
|
|
11054
|
-
sortAscLabel: "Oldest first",
|
|
11055
|
-
sortDescLabel: "Newest first"
|
|
11056
|
-
})
|
|
11104
|
+
{
|
|
11105
|
+
key: "",
|
|
11106
|
+
value: "",
|
|
11107
|
+
disabled: false
|
|
11108
|
+
}
|
|
11057
11109
|
];
|
|
11058
|
-
}
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11110
|
+
}
|
|
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);
|
|
11122
|
+
}
|
|
11123
|
+
return {
|
|
11124
|
+
key,
|
|
11125
|
+
value: stringValue,
|
|
11126
|
+
original_key: key
|
|
11127
|
+
};
|
|
11070
11128
|
});
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11129
|
+
}
|
|
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;
|
|
11135
|
+
}
|
|
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;
|
|
11147
|
+
}
|
|
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;
|
|
11089
11160
|
}
|
|
11090
|
-
|
|
11161
|
+
}
|
|
11091
11162
|
});
|
|
11092
|
-
return
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
{
|
|
11103
|
-
control: form.control,
|
|
11104
|
-
name: "title",
|
|
11105
|
-
render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
|
|
11106
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
11107
|
-
/* @__PURE__ */ jsx(Form$2.Label, { children: "Title" }),
|
|
11108
|
-
/* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the title of the item" })
|
|
11109
|
-
] }),
|
|
11110
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
11111
|
-
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(Input, { ...field }) }),
|
|
11112
|
-
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
11113
|
-
] })
|
|
11114
|
-
] }) })
|
|
11115
|
-
}
|
|
11116
|
-
),
|
|
11117
|
-
/* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
|
|
11118
|
-
/* @__PURE__ */ jsx(
|
|
11119
|
-
Form$2.Field,
|
|
11120
|
-
{
|
|
11121
|
-
control: form.control,
|
|
11122
|
-
name: "unit_price",
|
|
11123
|
-
render: ({ field: { onChange, ...field } }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
|
|
11124
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
11125
|
-
/* @__PURE__ */ jsx(Form$2.Label, { children: "Unit price" }),
|
|
11126
|
-
/* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the unit price of the item" })
|
|
11127
|
-
] }),
|
|
11128
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
11129
|
-
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx(
|
|
11130
|
-
CurrencyInput,
|
|
11131
|
-
{
|
|
11132
|
-
symbol: getNativeSymbol(currencyCode),
|
|
11133
|
-
code: currencyCode,
|
|
11134
|
-
onValueChange: (_value, _name, values) => onChange(values == null ? void 0 : values.value),
|
|
11135
|
-
...field
|
|
11136
|
-
}
|
|
11137
|
-
) }),
|
|
11138
|
-
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
11139
|
-
] })
|
|
11140
|
-
] }) })
|
|
11141
|
-
}
|
|
11142
|
-
),
|
|
11143
|
-
/* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
|
|
11144
|
-
/* @__PURE__ */ jsx(
|
|
11145
|
-
Form$2.Field,
|
|
11146
|
-
{
|
|
11147
|
-
control: form.control,
|
|
11148
|
-
name: "quantity",
|
|
11149
|
-
render: ({ field }) => /* @__PURE__ */ jsx(Form$2.Item, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-3", children: [
|
|
11150
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
11151
|
-
/* @__PURE__ */ jsx(Form$2.Label, { children: "Quantity" }),
|
|
11152
|
-
/* @__PURE__ */ jsx(Form$2.Hint, { children: "Enter the quantity of the item" })
|
|
11153
|
-
] }),
|
|
11154
|
-
/* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
|
|
11155
|
-
/* @__PURE__ */ jsx(Form$2.Control, { children: /* @__PURE__ */ jsx("div", { className: "w-full flex-1", children: /* @__PURE__ */ jsx(NumberInput, { ...field, className: "w-full" }) }) }),
|
|
11156
|
-
/* @__PURE__ */ jsx(Form$2.ErrorMessage, {})
|
|
11157
|
-
] })
|
|
11158
|
-
] }) })
|
|
11159
|
-
}
|
|
11160
|
-
)
|
|
11161
|
-
] }) }) }),
|
|
11162
|
-
/* @__PURE__ */ jsx(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
11163
|
-
/* @__PURE__ */ jsx(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", type: "button", children: "Cancel" }) }),
|
|
11164
|
-
/* @__PURE__ */ jsx(Button, { size: "small", type: "button", onClick: onSubmit, children: "Add item" })
|
|
11165
|
-
] }) })
|
|
11166
|
-
] }) }) });
|
|
11167
|
-
};
|
|
11168
|
-
const customItemSchema = objectType({
|
|
11169
|
-
title: stringType().min(1),
|
|
11170
|
-
quantity: numberType(),
|
|
11171
|
-
unit_price: unionType([numberType(), stringType()])
|
|
11172
|
-
});
|
|
11163
|
+
return update;
|
|
11164
|
+
}
|
|
11165
|
+
function getHasUneditableRows(metadata) {
|
|
11166
|
+
if (!metadata) {
|
|
11167
|
+
return false;
|
|
11168
|
+
}
|
|
11169
|
+
return Object.values(metadata).some(
|
|
11170
|
+
(value) => !EDITABLE_TYPES.includes(typeof value)
|
|
11171
|
+
);
|
|
11172
|
+
}
|
|
11173
11173
|
const PROMOTION_QUERY_KEY = "promotions";
|
|
11174
11174
|
const promotionsQueryKeys = {
|
|
11175
11175
|
list: (query2) => [
|
|
@@ -13063,22 +13063,22 @@ const routeModule = {
|
|
|
13063
13063
|
Component: CustomItems,
|
|
13064
13064
|
path: "/draft-orders/:id/custom-items"
|
|
13065
13065
|
},
|
|
13066
|
-
{
|
|
13067
|
-
Component: Email,
|
|
13068
|
-
path: "/draft-orders/:id/email"
|
|
13069
|
-
},
|
|
13070
13066
|
{
|
|
13071
13067
|
Component: BillingAddress,
|
|
13072
13068
|
path: "/draft-orders/:id/billing-address"
|
|
13073
13069
|
},
|
|
13074
13070
|
{
|
|
13075
|
-
Component:
|
|
13076
|
-
path: "/draft-orders/:id/
|
|
13071
|
+
Component: Email,
|
|
13072
|
+
path: "/draft-orders/:id/email"
|
|
13077
13073
|
},
|
|
13078
13074
|
{
|
|
13079
13075
|
Component: Items,
|
|
13080
13076
|
path: "/draft-orders/:id/items"
|
|
13081
13077
|
},
|
|
13078
|
+
{
|
|
13079
|
+
Component: Metadata,
|
|
13080
|
+
path: "/draft-orders/:id/metadata"
|
|
13081
|
+
},
|
|
13082
13082
|
{
|
|
13083
13083
|
Component: Promotions,
|
|
13084
13084
|
path: "/draft-orders/:id/promotions"
|