@medusajs/draft-order 0.0.1

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.
Files changed (82) hide show
  1. package/.medusa/server/src/admin/components/common/action-menu.js +77 -0
  2. package/.medusa/server/src/admin/components/common/conditional-tooltip.js +15 -0
  3. package/.medusa/server/src/admin/components/common/data-table.js +249 -0
  4. package/.medusa/server/src/admin/components/common/form.js +151 -0
  5. package/.medusa/server/src/admin/components/common/inline-tip.js +42 -0
  6. package/.medusa/server/src/admin/components/common/keybound-form.js +32 -0
  7. package/.medusa/server/src/admin/components/common/page-skeleton.js +51 -0
  8. package/.medusa/server/src/admin/components/common/thumbnail.js +15 -0
  9. package/.medusa/server/src/admin/components/draft-orders/activity-section.js +205 -0
  10. package/.medusa/server/src/admin/components/draft-orders/customer-section.js +165 -0
  11. package/.medusa/server/src/admin/components/draft-orders/general-section.js +36 -0
  12. package/.medusa/server/src/admin/components/draft-orders/json-view-section.js +140 -0
  13. package/.medusa/server/src/admin/components/draft-orders/metadata-section.js +28 -0
  14. package/.medusa/server/src/admin/components/draft-orders/shipping-section.js +211 -0
  15. package/.medusa/server/src/admin/components/draft-orders/summary-section.js +148 -0
  16. package/.medusa/server/src/admin/components/inputs/combobox.js +311 -0
  17. package/.medusa/server/src/admin/components/inputs/country-select.js +59 -0
  18. package/.medusa/server/src/admin/components/inputs/number-input.js +100 -0
  19. package/.medusa/server/src/admin/components/inputs/switch-block.js +30 -0
  20. package/.medusa/server/src/admin/components/modals/index.js +19 -0
  21. package/.medusa/server/src/admin/components/modals/route-drawer/index.js +4 -0
  22. package/.medusa/server/src/admin/components/modals/route-drawer/route-drawer.js +57 -0
  23. package/.medusa/server/src/admin/components/modals/route-focus-modal/index.js +4 -0
  24. package/.medusa/server/src/admin/components/modals/route-focus-modal/route-focus-modal.js +71 -0
  25. package/.medusa/server/src/admin/components/modals/route-modal-form/index.js +4 -0
  26. package/.medusa/server/src/admin/components/modals/route-modal-form/route-modal-form.js +60 -0
  27. package/.medusa/server/src/admin/components/modals/route-modal-provider/index.js +6 -0
  28. package/.medusa/server/src/admin/components/modals/route-modal-provider/route-modal-context.js +5 -0
  29. package/.medusa/server/src/admin/components/modals/route-modal-provider/route-provider.js +30 -0
  30. package/.medusa/server/src/admin/components/modals/route-modal-provider/use-route-modal.js +12 -0
  31. package/.medusa/server/src/admin/components/modals/stacked-drawer/index.js +5 -0
  32. package/.medusa/server/src/admin/components/modals/stacked-drawer/stacked-drawer.js +55 -0
  33. package/.medusa/server/src/admin/components/modals/stacked-focus-modal/index.js +5 -0
  34. package/.medusa/server/src/admin/components/modals/stacked-focus-modal/stacked-focus-modal.js +63 -0
  35. package/.medusa/server/src/admin/components/modals/stacked-modal-provider/index.js +6 -0
  36. package/.medusa/server/src/admin/components/modals/stacked-modal-provider/stacked-modal-context.js +5 -0
  37. package/.medusa/server/src/admin/components/modals/stacked-modal-provider/stacked-modal-provider.js +47 -0
  38. package/.medusa/server/src/admin/components/modals/stacked-modal-provider/use-stacked-modal.js +14 -0
  39. package/.medusa/server/src/admin/components/utilities/generic-forward-ref.js +7 -0
  40. package/.medusa/server/src/admin/hooks/api/customers.js +53 -0
  41. package/.medusa/server/src/admin/hooks/api/draft-orders.js +161 -0
  42. package/.medusa/server/src/admin/hooks/api/orders.js +274 -0
  43. package/.medusa/server/src/admin/hooks/api/product-variants.js +21 -0
  44. package/.medusa/server/src/admin/hooks/api/regions.js +35 -0
  45. package/.medusa/server/src/admin/hooks/api/sales-channels.js +35 -0
  46. package/.medusa/server/src/admin/hooks/api/shipping-options.js +35 -0
  47. package/.medusa/server/src/admin/hooks/api/users.js +26 -0
  48. package/.medusa/server/src/admin/hooks/common/use-combobox-data.js +61 -0
  49. package/.medusa/server/src/admin/hooks/common/use-data-table-date-filters.js +89 -0
  50. package/.medusa/server/src/admin/hooks/common/use-debounced-search.js +22 -0
  51. package/.medusa/server/src/admin/hooks/common/use-query-params.js +14 -0
  52. package/.medusa/server/src/admin/hooks/order-edits/use-cancel-order-edit.js +25 -0
  53. package/.medusa/server/src/admin/hooks/order-edits/use-initiate-order-edit.js +39 -0
  54. package/.medusa/server/src/admin/lib/data/countries.js +1762 -0
  55. package/.medusa/server/src/admin/lib/data/currencies.js +36 -0
  56. package/.medusa/server/src/admin/lib/queries/draft-order-details.js +1 -0
  57. package/.medusa/server/src/admin/lib/queries/sdk.js +10 -0
  58. package/.medusa/server/src/admin/lib/schemas/address.js +16 -0
  59. package/.medusa/server/src/admin/lib/utils/address-utils.js +57 -0
  60. package/.medusa/server/src/admin/lib/utils/date-utils.js +27 -0
  61. package/.medusa/server/src/admin/lib/utils/order-utils.js +13 -0
  62. package/.medusa/server/src/admin/routes/draft-orders/@create/page.js +659 -0
  63. package/.medusa/server/src/admin/routes/draft-orders/_id_/@billing-address/page.js +228 -0
  64. package/.medusa/server/src/admin/routes/draft-orders/_id_/@custom-items/page.js +38 -0
  65. package/.medusa/server/src/admin/routes/draft-orders/_id_/@email/page.js +89 -0
  66. package/.medusa/server/src/admin/routes/draft-orders/_id_/@items/page.js +576 -0
  67. package/.medusa/server/src/admin/routes/draft-orders/_id_/@metadata/page.js +338 -0
  68. package/.medusa/server/src/admin/routes/draft-orders/_id_/@promotions/page.js +70 -0
  69. package/.medusa/server/src/admin/routes/draft-orders/_id_/@sales-channel/page.js +113 -0
  70. package/.medusa/server/src/admin/routes/draft-orders/_id_/@shipping/page.js +465 -0
  71. package/.medusa/server/src/admin/routes/draft-orders/_id_/@shipping-address/page.js +241 -0
  72. package/.medusa/server/src/admin/routes/draft-orders/_id_/page.js +70 -0
  73. package/.medusa/server/src/admin/routes/draft-orders/page.js +148 -0
  74. package/.medusa/server/src/api/admin/draft-orders/[id]/convert/route.js +18 -0
  75. package/.medusa/server/src/types/http/draft-orders/payloads.js +3 -0
  76. package/.medusa/server/src/types/http/draft-orders/responses.js +3 -0
  77. package/.medusa/server/src/types/http/orders/entity.js +3 -0
  78. package/.medusa/server/src/types/http/orders/requests.js +3 -0
  79. package/.medusa/server/src/workflows/draft-orders/convert-draft-order-workflow.js +54 -0
  80. package/.medusa/server/tailwind.config.js +12 -0
  81. package/README.md +64 -0
  82. package/package.json +104 -0
@@ -0,0 +1,211 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { TriangleRightMini, Buildings, TruckFast, Shopping } from "@medusajs/icons";
3
+ import { Container, Heading, Divider, IconButton, Text, StatusBadge, Button } from "@medusajs/ui";
4
+ import { Accordion } from "radix-ui";
5
+ import { Link } from "react-router-dom";
6
+ import { useShippingOptions } from "../../hooks/api/shipping-options.js";
7
+ import { getUniqueShippingProfiles } from "../../lib/utils/order-utils.js";
8
+ import { Thumbnail } from "../common/thumbnail.js";
9
+ const ShippingSection = ({ order }) => {
10
+ const data = getShippingProfileData(order.items);
11
+ const orderHasShipping = order.shipping_methods.length > 0;
12
+ const {
13
+ shipping_options = [],
14
+ isPending,
15
+ isError,
16
+ error
17
+ } = useShippingOptions(
18
+ {
19
+ id: order.shipping_methods.map((method) => method.shipping_option_id).filter(Boolean),
20
+ fields: "+service_zone.*,+service_zone.fulfillment_set.*,+service_zone.fulfillment_set.location.*"
21
+ },
22
+ {
23
+ enabled: orderHasShipping
24
+ }
25
+ );
26
+ if (isError) {
27
+ throw error;
28
+ }
29
+ const ready = !orderHasShipping ? true : shipping_options && !isPending;
30
+ const isAllProfilesAssigned = data.every(
31
+ (profile) => shipping_options == null ? void 0 : shipping_options.find(
32
+ (option) => option.shipping_profile_id === profile.id
33
+ )
34
+ );
35
+ return /* @__PURE__ */ jsxs(Container, { className: "p-0 overflow-hidden", children: [
36
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Heading, { children: "Shipping" }) }),
37
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
38
+ /* @__PURE__ */ jsx(Accordion.Root, { type: "multiple", children: ready && data.map((profile, idx) => /* @__PURE__ */ jsx("div", { children: renderShippingProfile(
39
+ profile,
40
+ shipping_options,
41
+ idx === data.length - 1
42
+ ) }, profile.id)) }),
43
+ !isAllProfilesAssigned && /* @__PURE__ */ jsxs("div", { children: [
44
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
45
+ /* @__PURE__ */ jsx(Footer, {})
46
+ ] })
47
+ ] });
48
+ };
49
+ function renderShippingProfile(profile, shippingOptions, isLast) {
50
+ const shippingOption = shippingOptions.find(
51
+ (option) => option.shipping_profile_id === profile.id
52
+ );
53
+ if (shippingOption) {
54
+ return /* @__PURE__ */ jsx(
55
+ ProfileWithShipping,
56
+ {
57
+ profile,
58
+ shippingOption,
59
+ isLast
60
+ }
61
+ );
62
+ }
63
+ return /* @__PURE__ */ jsx(ProfileWithoutShipping, { profile, isLast });
64
+ }
65
+ const ProfileWithShipping = ({
66
+ profile,
67
+ shippingOption,
68
+ isLast
69
+ }) => {
70
+ var _a, _b, _c;
71
+ return /* @__PURE__ */ jsxs("div", { children: [
72
+ /* @__PURE__ */ jsxs(Accordion.Item, { value: profile.id, children: [
73
+ /* @__PURE__ */ jsx("div", { className: "flex items-center px-6 py-4 justify-between gap-x-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
74
+ /* @__PURE__ */ jsx(Accordion.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
75
+ IconButton,
76
+ {
77
+ size: "2xsmall",
78
+ variant: "transparent",
79
+ className: "group/trigger",
80
+ children: /* @__PURE__ */ jsx(TriangleRightMini, { className: "group-data-[state=open]/trigger:rotate-90 transition-transform" })
81
+ }
82
+ ) }),
83
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
84
+ /* @__PURE__ */ jsx(ShippingBadge, {}),
85
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-[5px] text-ui-fg-subtle", children: [
86
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: `${profile.items.length}x ${profile.items.length === 1 ? "item" : "items"}` }),
87
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "shipping from" }),
88
+ /* @__PURE__ */ jsx(Buildings, {}),
89
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", weight: "plus", children: (_c = (_b = (_a = shippingOption.service_zone) == null ? void 0 : _a.fulfillment_set) == null ? void 0 : _b.location) == null ? void 0 : _c.name }),
90
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "using" }),
91
+ /* @__PURE__ */ jsx(TruckFast, {}),
92
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", weight: "plus", children: shippingOption.name })
93
+ ] })
94
+ ] })
95
+ ] }) }),
96
+ /* @__PURE__ */ jsx(ShippingProfileItems, { profile })
97
+ ] }),
98
+ !isLast && /* @__PURE__ */ jsx(Divider, { variant: "dashed" })
99
+ ] });
100
+ };
101
+ const ProfileWithoutShipping = ({
102
+ profile,
103
+ isLast
104
+ }) => {
105
+ return /* @__PURE__ */ jsxs("div", { children: [
106
+ /* @__PURE__ */ jsxs(Accordion.Item, { value: profile.id, children: [
107
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3 justify-between px-6 py-4", children: [
108
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
109
+ /* @__PURE__ */ jsx(Accordion.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
110
+ IconButton,
111
+ {
112
+ size: "2xsmall",
113
+ variant: "transparent",
114
+ className: "group/trigger",
115
+ children: /* @__PURE__ */ jsx(TriangleRightMini, { className: "group-data-[state=open]/trigger:rotate-90 transition-transform" })
116
+ }
117
+ ) }),
118
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex items-center gap-x-3", children: [
119
+ /* @__PURE__ */ jsx(ShippingBadge, {}),
120
+ /* @__PURE__ */ jsxs("div", { children: [
121
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: profile.name }),
122
+ /* @__PURE__ */ jsx(
123
+ Text,
124
+ {
125
+ size: "small",
126
+ leading: "compact",
127
+ className: "text-ui-fg-subtle",
128
+ children: `${profile.items.length} ${profile.items.length === 1 ? "item" : "items"}`
129
+ }
130
+ )
131
+ ] })
132
+ ] })
133
+ ] }),
134
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(StatusBadge, { color: "orange", children: "Requires shipping" }) })
135
+ ] }),
136
+ /* @__PURE__ */ jsx(ShippingProfileItems, { profile })
137
+ ] }),
138
+ !isLast && /* @__PURE__ */ jsx(Divider, { variant: "dashed" })
139
+ ] });
140
+ };
141
+ const ShippingProfileItems = ({ profile }) => {
142
+ return /* @__PURE__ */ jsxs(Accordion.Content, { children: [
143
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
144
+ profile.items.map((item, idx) => {
145
+ var _a, _b, _c, _d, _e;
146
+ return /* @__PURE__ */ jsxs("div", { children: [
147
+ /* @__PURE__ */ jsxs("div", { className: "px-6 flex items-center gap-x-3", children: [
148
+ /* @__PURE__ */ jsx("div", { className: "w-5 h-[72px] flex flex-col justify-center items-center", children: /* @__PURE__ */ jsx(Divider, { variant: "dashed", orientation: "vertical" }) }),
149
+ /* @__PURE__ */ jsxs("div", { className: "py-4 flex items-center gap-x-3", children: [
150
+ /* @__PURE__ */ jsx("div", { className: "size-7 flex items-center justify-center tabular-nums", children: /* @__PURE__ */ jsxs(
151
+ Text,
152
+ {
153
+ size: "small",
154
+ leading: "compact",
155
+ className: "text-ui-fg-subtle",
156
+ children: [
157
+ item.quantity,
158
+ "x"
159
+ ]
160
+ }
161
+ ) }),
162
+ /* @__PURE__ */ jsx(Thumbnail, { thumbnail: item.thumbnail }),
163
+ /* @__PURE__ */ jsxs("div", { children: [
164
+ /* @__PURE__ */ jsxs(Text, { size: "small", leading: "compact", weight: "plus", children: [
165
+ (_b = (_a = item.variant) == null ? void 0 : _a.product) == null ? void 0 : _b.title,
166
+ " (",
167
+ (_c = item.variant) == null ? void 0 : _c.title,
168
+ ")"
169
+ ] }),
170
+ /* @__PURE__ */ jsx(
171
+ Text,
172
+ {
173
+ size: "small",
174
+ leading: "compact",
175
+ className: "text-ui-fg-subtle",
176
+ children: (_e = (_d = item.variant) == null ? void 0 : _d.options) == null ? void 0 : _e.map((option) => option.value).join(" · ")
177
+ }
178
+ )
179
+ ] })
180
+ ] })
181
+ ] }, item.id),
182
+ idx !== profile.items.length - 1 && /* @__PURE__ */ jsx(Divider, { variant: "dashed" })
183
+ ] }, item.id);
184
+ })
185
+ ] });
186
+ };
187
+ const Footer = () => {
188
+ return /* @__PURE__ */ jsx("div", { className: "px-6 py-4 flex items-center justify-end bg-ui-bg-component", children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", asChild: true, children: /* @__PURE__ */ jsx(Link, { to: "shipping", children: "Add shipping options" }) }) });
189
+ };
190
+ const ShippingBadge = () => {
191
+ return /* @__PURE__ */ jsx("div", { className: "size-7 rounded-md shadow-borders-base flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "size-6 rounded bg-ui-bg-component-hover flex items-center justify-center", children: /* @__PURE__ */ jsx(Shopping, { className: "text-ui-fg-subtle" }) }) });
192
+ };
193
+ function getShippingProfileData(items) {
194
+ const uniqueShippingProfiles = getUniqueShippingProfiles(items);
195
+ const output = uniqueShippingProfiles.map((profile) => {
196
+ return {
197
+ id: profile.id,
198
+ name: profile.name,
199
+ items: items.filter(
200
+ (item) => {
201
+ var _a, _b, _c;
202
+ return ((_c = (_b = (_a = item.variant) == null ? void 0 : _a.product) == null ? void 0 : _b.shipping_profile) == null ? void 0 : _c.id) === profile.id;
203
+ }
204
+ )
205
+ };
206
+ });
207
+ return output;
208
+ }
209
+ export {
210
+ ShippingSection
211
+ };
@@ -0,0 +1,148 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { Plus, ReceiptPercent } from "@medusajs/icons";
3
+ import { Container, Heading, Divider, Text, Button, toast } from "@medusajs/ui";
4
+ import { useNavigate } from "react-router-dom";
5
+ import { useConvertDraftOrder } from "../../hooks/api/draft-orders.js";
6
+ import { getLocaleAmount, getStylizedAmount } from "../../lib/data/currencies.js";
7
+ import { ActionMenu } from "../common/action-menu.js";
8
+ import { Thumbnail } from "../common/thumbnail.js";
9
+ const SummarySection = ({ order }) => {
10
+ return /* @__PURE__ */ jsxs(Container, { className: "p-0 overflow-hidden", children: [
11
+ /* @__PURE__ */ jsxs("div", { className: "px-6 py-4 flex items-center justify-between gap-x-4", children: [
12
+ /* @__PURE__ */ jsx(Heading, { children: "Summary" }),
13
+ /* @__PURE__ */ jsx(
14
+ ActionMenu,
15
+ {
16
+ groups: [
17
+ {
18
+ actions: [
19
+ {
20
+ label: "Edit items",
21
+ icon: /* @__PURE__ */ jsx(Plus, {}),
22
+ to: "items"
23
+ },
24
+ {
25
+ label: "Edit custom items",
26
+ icon: /* @__PURE__ */ jsx(Plus, {}),
27
+ to: "custom-items"
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ actions: [
33
+ {
34
+ label: "Edit promotions",
35
+ icon: /* @__PURE__ */ jsx(ReceiptPercent, {}),
36
+ to: "promotions"
37
+ }
38
+ ]
39
+ }
40
+ ]
41
+ }
42
+ )
43
+ ] }),
44
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
45
+ /* @__PURE__ */ jsx("div", { children: order.items.map((item, idx) => /* @__PURE__ */ jsxs("div", { children: [
46
+ /* @__PURE__ */ jsx(Item, { item, currencyCode: order.currency_code }),
47
+ idx !== order.items.length - 1 && /* @__PURE__ */ jsx(Divider, { variant: "dashed" })
48
+ ] }, item.id)) }),
49
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
50
+ /* @__PURE__ */ jsx(
51
+ Total,
52
+ {
53
+ currencyCode: order.currency_code,
54
+ total: order.total,
55
+ shippingSubtotal: order.shipping_subtotal,
56
+ taxTotal: order.tax_total
57
+ }
58
+ ),
59
+ /* @__PURE__ */ jsx(Divider, { variant: "dashed" }),
60
+ /* @__PURE__ */ jsx(Footer, { order })
61
+ ] });
62
+ };
63
+ const Item = ({ item, currencyCode }) => {
64
+ return /* @__PURE__ */ jsxs("div", { className: "px-6 py-4 grid grid-cols-2 gap-3", children: [
65
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
66
+ /* @__PURE__ */ jsx(Thumbnail, { thumbnail: item.thumbnail, alt: item.title }),
67
+ /* @__PURE__ */ jsxs("div", { children: [
68
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
69
+ /* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.product_title }),
70
+ /* @__PURE__ */ jsxs(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: [
71
+ "(",
72
+ item.variant_title,
73
+ ")"
74
+ ] })
75
+ ] }),
76
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: item.variant_sku })
77
+ ] })
78
+ ] }),
79
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 items-center gap-3 [&>div]:text-right text-ui-fg-subtle", children: [
80
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { children: getLocaleAmount(item.unit_price, currencyCode) }) }),
81
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(Text, { children: [
82
+ item.quantity,
83
+ "x"
84
+ ] }) }),
85
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { children: getLocaleAmount(item.subtotal, currencyCode) }) })
86
+ ] })
87
+ ] });
88
+ };
89
+ const Total = ({
90
+ total,
91
+ shippingSubtotal,
92
+ taxTotal,
93
+ currencyCode
94
+ }) => {
95
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col px-6 py-4 gap-y-2", children: [
96
+ shippingSubtotal !== null && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4 text-ui-fg-subtle", children: [
97
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "Shipping" }),
98
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: getLocaleAmount(shippingSubtotal, currencyCode) })
99
+ ] }),
100
+ taxTotal !== null && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4 text-ui-fg-subtle", children: [
101
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "Tax" }),
102
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: getLocaleAmount(taxTotal, currencyCode) })
103
+ ] }),
104
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
105
+ /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", weight: "plus", children: "Total" }),
106
+ /* @__PURE__ */ jsx(
107
+ Text,
108
+ {
109
+ size: "small",
110
+ leading: "compact",
111
+ weight: "plus",
112
+ className: "text-right",
113
+ children: getStylizedAmount(total, currencyCode)
114
+ }
115
+ )
116
+ ] })
117
+ ] });
118
+ };
119
+ const Footer = ({ order }) => {
120
+ const navigate = useNavigate();
121
+ const { mutateAsync: convertDraftOrder, isPending } = useConvertDraftOrder(
122
+ order.id
123
+ );
124
+ const handleConvert = async () => {
125
+ await convertDraftOrder(void 0, {
126
+ onSuccess: () => {
127
+ toast.success("Draft order converted to order");
128
+ navigate(`/orders/${order.id}`);
129
+ },
130
+ onError: (error) => {
131
+ toast.error(error.message);
132
+ }
133
+ });
134
+ };
135
+ return /* @__PURE__ */ jsx("div", { className: "px-6 py-4 flex items-center justify-end gap-x-2 bg-ui-bg-component", children: /* @__PURE__ */ jsx(
136
+ Button,
137
+ {
138
+ size: "small",
139
+ variant: "secondary",
140
+ isLoading: isPending,
141
+ onClick: handleConvert,
142
+ children: "Convert to order"
143
+ }
144
+ ) });
145
+ };
146
+ export {
147
+ SummarySection
148
+ };
@@ -0,0 +1,311 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { ComboboxProvider, Combobox as Combobox$1, ComboboxDisclosure, ComboboxPopover, ComboboxItem, ComboboxItemCheck, ComboboxItemValue, Separator } from "@ariakit/react";
3
+ import { XMarkMini, TrianglesMini, CheckMini, EllipseMiniSolid, PlusMini } from "@medusajs/icons";
4
+ import { clx, Text } from "@medusajs/ui";
5
+ import { matchSorter } from "match-sorter";
6
+ import { useState, useTransition, useRef, useImperativeHandle, useDeferredValue, useMemo, useCallback, Fragment } from "react";
7
+ import { genericForwardRef } from "../utilities/generic-forward-ref.js";
8
+ const TABLUAR_NUM_WIDTH = 8;
9
+ const TAG_BASE_WIDTH = 28;
10
+ const ComboboxImpl = ({
11
+ value: controlledValue,
12
+ onChange,
13
+ searchValue: controlledSearchValue,
14
+ onSearchValueChange,
15
+ options,
16
+ className,
17
+ placeholder,
18
+ fetchNextPage,
19
+ isFetchingNextPage,
20
+ onCreateOption,
21
+ noResultsPlaceholder,
22
+ ...inputProps
23
+ }, ref) => {
24
+ var _a;
25
+ const [open, setOpen] = useState(false);
26
+ const [isPending, startTransition] = useTransition();
27
+ const comboboxRef = useRef(null);
28
+ const listboxRef = useRef(null);
29
+ useImperativeHandle(ref, () => comboboxRef.current);
30
+ const isValueControlled = controlledValue !== void 0;
31
+ const isSearchControlled = controlledSearchValue !== void 0;
32
+ const isArrayValue = Array.isArray(controlledValue);
33
+ const emptyState = isArrayValue ? [] : "";
34
+ const [uncontrolledSearchValue, setUncontrolledSearchValue] = useState(
35
+ controlledSearchValue || ""
36
+ );
37
+ const defferedSearchValue = useDeferredValue(uncontrolledSearchValue);
38
+ const [uncontrolledValue, setUncontrolledValue] = useState(emptyState);
39
+ const searchValue = isSearchControlled ? controlledSearchValue : uncontrolledSearchValue;
40
+ const selectedValues = isValueControlled ? controlledValue : uncontrolledValue;
41
+ const handleValueChange = (newValues) => {
42
+ const exists = options.filter((o) => !o.disabled).find((o) => {
43
+ if (isArrayValue) {
44
+ return newValues == null ? void 0 : newValues.includes(o.value);
45
+ }
46
+ return o.value === newValues;
47
+ });
48
+ if (!exists && onCreateOption && newValues) {
49
+ onCreateOption(newValues);
50
+ }
51
+ if (!isValueControlled) {
52
+ setUncontrolledValue(newValues || emptyState);
53
+ }
54
+ if (onChange) {
55
+ onChange(newValues);
56
+ }
57
+ setUncontrolledSearchValue("");
58
+ };
59
+ const handleSearchChange = (query) => {
60
+ setUncontrolledSearchValue(query);
61
+ if (onSearchValueChange) {
62
+ onSearchValueChange(query);
63
+ }
64
+ };
65
+ const matches = useMemo(() => {
66
+ if (isSearchControlled) {
67
+ return [];
68
+ }
69
+ return matchSorter(options, defferedSearchValue, {
70
+ keys: ["label"]
71
+ });
72
+ }, [options, defferedSearchValue, isSearchControlled]);
73
+ const observer = useRef(
74
+ new IntersectionObserver(
75
+ (entries) => {
76
+ const first = entries[0];
77
+ if (first.isIntersecting) {
78
+ fetchNextPage == null ? void 0 : fetchNextPage();
79
+ }
80
+ },
81
+ { threshold: 1 }
82
+ )
83
+ );
84
+ const lastOptionRef = useCallback(
85
+ (node) => {
86
+ if (isFetchingNextPage) {
87
+ return;
88
+ }
89
+ if (observer.current) {
90
+ observer.current.disconnect();
91
+ }
92
+ if (node) {
93
+ observer.current.observe(node);
94
+ }
95
+ },
96
+ [isFetchingNextPage]
97
+ );
98
+ const handleOpenChange = (open2) => {
99
+ if (!open2) {
100
+ setUncontrolledSearchValue("");
101
+ }
102
+ setOpen(open2);
103
+ };
104
+ const hasValue = (selectedValues == null ? void 0 : selectedValues.length) > 0;
105
+ const showTag = hasValue && isArrayValue;
106
+ const showSelected = showTag && !searchValue && !open;
107
+ const hideInput = !isArrayValue && !open;
108
+ const selectedLabel = (_a = options.find((o) => o.value === selectedValues)) == null ? void 0 : _a.label;
109
+ const hidePlaceholder = showSelected || open;
110
+ const tagWidth = useMemo(() => {
111
+ if (!Array.isArray(selectedValues)) {
112
+ return TAG_BASE_WIDTH + TABLUAR_NUM_WIDTH;
113
+ }
114
+ const count = selectedValues.length;
115
+ const digits = count.toString().length;
116
+ return TAG_BASE_WIDTH + digits * TABLUAR_NUM_WIDTH;
117
+ }, [selectedValues]);
118
+ const results = useMemo(() => {
119
+ return isSearchControlled ? options : matches;
120
+ }, [matches, options, isSearchControlled]);
121
+ return /* @__PURE__ */ jsxs(
122
+ ComboboxProvider,
123
+ {
124
+ open,
125
+ setOpen: handleOpenChange,
126
+ selectedValue: selectedValues,
127
+ setSelectedValue: (value) => handleValueChange(value),
128
+ value: uncontrolledSearchValue,
129
+ setValue: (query) => {
130
+ startTransition(() => handleSearchChange(query));
131
+ },
132
+ children: [
133
+ /* @__PURE__ */ jsxs(
134
+ "div",
135
+ {
136
+ className: clx(
137
+ "relative flex cursor-pointer items-center gap-x-2 overflow-hidden",
138
+ "h-8 w-full rounded-md",
139
+ "bg-ui-bg-field transition-fg shadow-borders-base",
140
+ "has-[input:focus]:shadow-borders-interactive-with-active",
141
+ "has-[:invalid]:shadow-borders-error has-[[aria-invalid=true]]:shadow-borders-error",
142
+ "has-[:disabled]:bg-ui-bg-disabled has-[:disabled]:text-ui-fg-disabled has-[:disabled]:cursor-not-allowed",
143
+ className
144
+ ),
145
+ style: {
146
+ "--tag-width": `${tagWidth}px`
147
+ },
148
+ children: [
149
+ showTag && /* @__PURE__ */ jsxs(
150
+ "button",
151
+ {
152
+ type: "button",
153
+ onClick: (e) => {
154
+ e.preventDefault();
155
+ handleValueChange(void 0);
156
+ },
157
+ className: "bg-ui-bg-base hover:bg-ui-bg-base-hover txt-compact-small-plus text-ui-fg-subtle focus-within:border-ui-fg-interactive transition-fg absolute left-0.5 top-0.5 z-[1] flex h-[28px] items-center rounded-[4px] border py-[3px] pl-1.5 pr-1 outline-none",
158
+ children: [
159
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: selectedValues.length }),
160
+ /* @__PURE__ */ jsx(XMarkMini, { className: "text-ui-fg-muted" })
161
+ ]
162
+ }
163
+ ),
164
+ /* @__PURE__ */ jsxs("div", { className: "relative flex size-full items-center", children: [
165
+ showSelected && /* @__PURE__ */ jsx(
166
+ "div",
167
+ {
168
+ className: clx(
169
+ "pointer-events-none absolute inset-y-0 flex size-full items-center",
170
+ {
171
+ "left-[calc(var(--tag-width)+8px)]": showTag,
172
+ "left-2": !showTag
173
+ }
174
+ ),
175
+ children: /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: "Selected" })
176
+ }
177
+ ),
178
+ hideInput && /* @__PURE__ */ jsx(
179
+ "div",
180
+ {
181
+ className: clx(
182
+ "pointer-events-none absolute inset-y-0 flex size-full items-center overflow-hidden pr-10",
183
+ {
184
+ "left-[calc(var(--tag-width)+8px)]": showTag,
185
+ "left-2": !showTag
186
+ }
187
+ ),
188
+ children: /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "truncate", children: selectedLabel })
189
+ }
190
+ ),
191
+ /* @__PURE__ */ jsx(
192
+ Combobox$1,
193
+ {
194
+ autoSelect: true,
195
+ ref: comboboxRef,
196
+ onFocus: () => setOpen(true),
197
+ className: clx(
198
+ "txt-compact-small text-ui-fg-base !placeholder:text-ui-fg-muted transition-fg size-full cursor-pointer bg-transparent pl-2 pr-8 outline-none focus:cursor-text",
199
+ "hover:bg-ui-bg-field-hover",
200
+ {
201
+ "opacity-0": hideInput,
202
+ "pl-2": !showTag,
203
+ "pl-[calc(var(--tag-width)+8px)]": showTag
204
+ }
205
+ ),
206
+ placeholder: hidePlaceholder ? void 0 : placeholder,
207
+ ...inputProps
208
+ }
209
+ )
210
+ ] }),
211
+ /* @__PURE__ */ jsx(
212
+ ComboboxDisclosure,
213
+ {
214
+ render: (props) => {
215
+ return /* @__PURE__ */ jsx(
216
+ "button",
217
+ {
218
+ ...props,
219
+ type: "button",
220
+ className: "text-ui-fg-muted transition-fg hover:bg-ui-bg-field-hover absolute right-0 flex size-8 items-center justify-center rounded-r outline-none",
221
+ children: /* @__PURE__ */ jsx(TrianglesMini, {})
222
+ }
223
+ );
224
+ }
225
+ }
226
+ )
227
+ ]
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsxs(
231
+ ComboboxPopover,
232
+ {
233
+ gutter: 4,
234
+ sameWidth: true,
235
+ ref: listboxRef,
236
+ role: "listbox",
237
+ className: clx(
238
+ "shadow-elevation-flyout bg-ui-bg-base z-50 rounded-[8px] p-1",
239
+ "max-h-[200px] overflow-y-auto",
240
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
241
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
242
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
243
+ ),
244
+ style: {
245
+ pointerEvents: open ? "auto" : "none"
246
+ },
247
+ "aria-busy": isPending,
248
+ children: [
249
+ results.map(({ value, label, disabled }) => /* @__PURE__ */ jsxs(
250
+ ComboboxItem,
251
+ {
252
+ value,
253
+ focusOnHover: true,
254
+ setValueOnClick: false,
255
+ disabled,
256
+ className: clx(
257
+ "transition-fg bg-ui-bg-base data-[active-item=true]:bg-ui-bg-base-hover group flex cursor-pointer items-center gap-x-2 rounded-[4px] px-2 py-1",
258
+ {
259
+ "text-ui-fg-disabled": disabled,
260
+ "bg-ui-bg-component": disabled
261
+ }
262
+ ),
263
+ children: [
264
+ /* @__PURE__ */ jsx(ComboboxItemCheck, { className: "flex !size-5 items-center justify-center", children: isArrayValue ? /* @__PURE__ */ jsx(CheckMini, {}) : /* @__PURE__ */ jsx(EllipseMiniSolid, {}) }),
265
+ /* @__PURE__ */ jsx(ComboboxItemValue, { className: "txt-compact-small", children: label })
266
+ ]
267
+ },
268
+ value
269
+ )),
270
+ !!fetchNextPage && /* @__PURE__ */ jsx("div", { ref: lastOptionRef, className: "w-px" }),
271
+ isFetchingNextPage && /* @__PURE__ */ jsx("div", { className: "transition-fg bg-ui-bg-base flex items-center rounded-[4px] px-2 py-1.5", children: /* @__PURE__ */ jsx("div", { className: "bg-ui-bg-component size-full h-5 w-full animate-pulse rounded-[4px]" }) }),
272
+ !results.length && (noResultsPlaceholder && !(searchValue == null ? void 0 : searchValue.length) ? noResultsPlaceholder : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-x-2 rounded-[4px] px-2 py-1.5", children: /* @__PURE__ */ jsx(
273
+ Text,
274
+ {
275
+ size: "small",
276
+ leading: "compact",
277
+ className: "text-ui-fg-subtle",
278
+ children: "No results found"
279
+ }
280
+ ) })),
281
+ !results.length && onCreateOption && /* @__PURE__ */ jsxs(Fragment, { children: [
282
+ /* @__PURE__ */ jsx(Separator, { className: "bg-ui-border-base -mx-1" }),
283
+ /* @__PURE__ */ jsxs(
284
+ ComboboxItem,
285
+ {
286
+ value: uncontrolledSearchValue,
287
+ focusOnHover: true,
288
+ setValueOnClick: false,
289
+ className: "transition-fg bg-ui-bg-base data-[active-item=true]:bg-ui-bg-base-hover group mt-1 flex cursor-pointer items-center gap-x-2 rounded-[4px] px-2 py-1.5",
290
+ children: [
291
+ /* @__PURE__ */ jsx(PlusMini, { className: "text-ui-fg-subtle" }),
292
+ /* @__PURE__ */ jsxs(Text, { size: "small", leading: "compact", children: [
293
+ 'Create "',
294
+ searchValue,
295
+ '"'
296
+ ] })
297
+ ]
298
+ }
299
+ )
300
+ ] })
301
+ ]
302
+ }
303
+ )
304
+ ]
305
+ }
306
+ );
307
+ };
308
+ const Combobox = genericForwardRef(ComboboxImpl);
309
+ export {
310
+ Combobox
311
+ };