@voyant-travel/distribution-react 0.109.8

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 (312) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +82 -0
  3. package/dist/admin/index.d.ts +30 -0
  4. package/dist/admin/index.d.ts.map +1 -0
  5. package/dist/admin/index.js +65 -0
  6. package/dist/client.d.ts +14 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +59 -0
  9. package/dist/components/booking-link-detail-page.d.ts +10 -0
  10. package/dist/components/booking-link-detail-page.d.ts.map +1 -0
  11. package/dist/components/booking-link-detail-page.js +51 -0
  12. package/dist/components/channel-detail-page.d.ts +12 -0
  13. package/dist/components/channel-detail-page.d.ts.map +1 -0
  14. package/dist/components/channel-detail-page.js +41 -0
  15. package/dist/components/channel-sync-controls.d.ts +15 -0
  16. package/dist/components/channel-sync-controls.d.ts.map +1 -0
  17. package/dist/components/channel-sync-controls.js +29 -0
  18. package/dist/components/channel-sync-deliveries-drawer.d.ts +12 -0
  19. package/dist/components/channel-sync-deliveries-drawer.d.ts.map +1 -0
  20. package/dist/components/channel-sync-deliveries-drawer.js +18 -0
  21. package/dist/components/channel-sync-page-utils.d.ts +99 -0
  22. package/dist/components/channel-sync-page-utils.d.ts.map +1 -0
  23. package/dist/components/channel-sync-page-utils.js +85 -0
  24. package/dist/components/channel-sync-page.d.ts +4 -0
  25. package/dist/components/channel-sync-page.d.ts.map +1 -0
  26. package/dist/components/channel-sync-page.js +141 -0
  27. package/dist/components/channels-page.d.ts +6 -0
  28. package/dist/components/channels-page.d.ts.map +1 -0
  29. package/dist/components/channels-page.js +132 -0
  30. package/dist/components/commission-rule-detail-page.d.ts +10 -0
  31. package/dist/components/commission-rule-detail-page.d.ts.map +1 -0
  32. package/dist/components/commission-rule-detail-page.js +57 -0
  33. package/dist/components/contract-detail-page.d.ts +10 -0
  34. package/dist/components/contract-detail-page.d.ts.map +1 -0
  35. package/dist/components/contract-detail-page.js +64 -0
  36. package/dist/components/distribution-overview.d.ts +19 -0
  37. package/dist/components/distribution-overview.d.ts.map +1 -0
  38. package/dist/components/distribution-overview.js +13 -0
  39. package/dist/components/distribution-page.d.ts +26 -0
  40. package/dist/components/distribution-page.d.ts.map +1 -0
  41. package/dist/components/distribution-page.js +190 -0
  42. package/dist/components/distribution-section-header.d.ts +7 -0
  43. package/dist/components/distribution-section-header.d.ts.map +1 -0
  44. package/dist/components/distribution-section-header.js +6 -0
  45. package/dist/components/distribution-shared.d.ts +32 -0
  46. package/dist/components/distribution-shared.d.ts.map +1 -0
  47. package/dist/components/distribution-shared.js +246 -0
  48. package/dist/components/distribution-tabs-primary.d.ts +57 -0
  49. package/dist/components/distribution-tabs-primary.d.ts.map +1 -0
  50. package/dist/components/distribution-tabs-primary.js +89 -0
  51. package/dist/components/distribution-tabs-secondary.d.ts +58 -0
  52. package/dist/components/distribution-tabs-secondary.d.ts.map +1 -0
  53. package/dist/components/distribution-tabs-secondary.js +89 -0
  54. package/dist/components/mapping-detail-page.d.ts +10 -0
  55. package/dist/components/mapping-detail-page.d.ts.map +1 -0
  56. package/dist/components/mapping-detail-page.js +51 -0
  57. package/dist/components/webhook-event-detail-page.d.ts +9 -0
  58. package/dist/components/webhook-event-detail-page.d.ts.map +1 -0
  59. package/dist/components/webhook-event-detail-page.js +46 -0
  60. package/dist/constants.d.ts +103 -0
  61. package/dist/constants.d.ts.map +1 -0
  62. package/dist/constants.js +48 -0
  63. package/dist/external-refs/client.d.ts +14 -0
  64. package/dist/external-refs/client.d.ts.map +1 -0
  65. package/dist/external-refs/client.js +58 -0
  66. package/dist/external-refs/components/entity-ref-picker.d.ts +21 -0
  67. package/dist/external-refs/components/entity-ref-picker.d.ts.map +1 -0
  68. package/dist/external-refs/components/entity-ref-picker.js +38 -0
  69. package/dist/external-refs/components/external-ref-dialog.d.ts +11 -0
  70. package/dist/external-refs/components/external-ref-dialog.d.ts.map +1 -0
  71. package/dist/external-refs/components/external-ref-dialog.js +120 -0
  72. package/dist/external-refs/components/external-refs-page.d.ts +16 -0
  73. package/dist/external-refs/components/external-refs-page.d.ts.map +1 -0
  74. package/dist/external-refs/components/external-refs-page.js +109 -0
  75. package/dist/external-refs/hooks/index.d.ts +3 -0
  76. package/dist/external-refs/hooks/index.d.ts.map +1 -0
  77. package/dist/external-refs/hooks/index.js +2 -0
  78. package/dist/external-refs/hooks/use-external-ref-mutation.d.ts +57 -0
  79. package/dist/external-refs/hooks/use-external-ref-mutation.d.ts.map +1 -0
  80. package/dist/external-refs/hooks/use-external-ref-mutation.js +40 -0
  81. package/dist/external-refs/hooks/use-external-refs.d.ts +26 -0
  82. package/dist/external-refs/hooks/use-external-refs.d.ts.map +1 -0
  83. package/dist/external-refs/hooks/use-external-refs.js +12 -0
  84. package/dist/external-refs/i18n/en.d.ts +3 -0
  85. package/dist/external-refs/i18n/en.d.ts.map +1 -0
  86. package/dist/external-refs/i18n/en.js +92 -0
  87. package/dist/external-refs/i18n/index.d.ts +5 -0
  88. package/dist/external-refs/i18n/index.d.ts.map +1 -0
  89. package/dist/external-refs/i18n/index.js +3 -0
  90. package/dist/external-refs/i18n/messages.d.ts +85 -0
  91. package/dist/external-refs/i18n/messages.d.ts.map +1 -0
  92. package/dist/external-refs/i18n/messages.js +1 -0
  93. package/dist/external-refs/i18n/provider.d.ts +26 -0
  94. package/dist/external-refs/i18n/provider.d.ts.map +1 -0
  95. package/dist/external-refs/i18n/provider.js +44 -0
  96. package/dist/external-refs/i18n/ro.d.ts +3 -0
  97. package/dist/external-refs/i18n/ro.d.ts.map +1 -0
  98. package/dist/external-refs/i18n/ro.js +92 -0
  99. package/dist/external-refs/index.d.ts +7 -0
  100. package/dist/external-refs/index.d.ts.map +1 -0
  101. package/dist/external-refs/index.js +6 -0
  102. package/dist/external-refs/provider.d.ts +2 -0
  103. package/dist/external-refs/provider.d.ts.map +1 -0
  104. package/dist/external-refs/provider.js +1 -0
  105. package/dist/external-refs/query-keys.d.ts +18 -0
  106. package/dist/external-refs/query-keys.d.ts.map +1 -0
  107. package/dist/external-refs/query-keys.js +6 -0
  108. package/dist/external-refs/query-options.d.ts +159 -0
  109. package/dist/external-refs/query-options.d.ts.map +1 -0
  110. package/dist/external-refs/query-options.js +31 -0
  111. package/dist/external-refs/schemas.d.ts +82 -0
  112. package/dist/external-refs/schemas.d.ts.map +1 -0
  113. package/dist/external-refs/schemas.js +20 -0
  114. package/dist/external-refs/ui.d.ts +5 -0
  115. package/dist/external-refs/ui.d.ts.map +1 -0
  116. package/dist/external-refs/ui.js +4 -0
  117. package/dist/hooks/index.d.ts +12 -0
  118. package/dist/hooks/index.d.ts.map +1 -0
  119. package/dist/hooks/index.js +12 -0
  120. package/dist/hooks/use-booking-links.d.ts +20 -0
  121. package/dist/hooks/use-booking-links.d.ts.map +1 -0
  122. package/dist/hooks/use-booking-links.js +9 -0
  123. package/dist/hooks/use-bookings.d.ts +14 -0
  124. package/dist/hooks/use-bookings.d.ts.map +1 -0
  125. package/dist/hooks/use-bookings.js +9 -0
  126. package/dist/hooks/use-channel-mutation.d.ts +69 -0
  127. package/dist/hooks/use-channel-mutation.d.ts.map +1 -0
  128. package/dist/hooks/use-channel-mutation.js +49 -0
  129. package/dist/hooks/use-channel.d.ts +16 -0
  130. package/dist/hooks/use-channel.d.ts.map +1 -0
  131. package/dist/hooks/use-channel.js +13 -0
  132. package/dist/hooks/use-channels.d.ts +20 -0
  133. package/dist/hooks/use-channels.d.ts.map +1 -0
  134. package/dist/hooks/use-channels.js +9 -0
  135. package/dist/hooks/use-commission-rules.d.ts +23 -0
  136. package/dist/hooks/use-commission-rules.d.ts.map +1 -0
  137. package/dist/hooks/use-commission-rules.js +9 -0
  138. package/dist/hooks/use-contracts.d.ts +22 -0
  139. package/dist/hooks/use-contracts.d.ts.map +1 -0
  140. package/dist/hooks/use-contracts.js +9 -0
  141. package/dist/hooks/use-mappings.d.ts +19 -0
  142. package/dist/hooks/use-mappings.d.ts.map +1 -0
  143. package/dist/hooks/use-mappings.js +9 -0
  144. package/dist/hooks/use-products.d.ts +14 -0
  145. package/dist/hooks/use-products.d.ts.map +1 -0
  146. package/dist/hooks/use-products.js +9 -0
  147. package/dist/hooks/use-suppliers.d.ts +14 -0
  148. package/dist/hooks/use-suppliers.d.ts.map +1 -0
  149. package/dist/hooks/use-suppliers.js +9 -0
  150. package/dist/hooks/use-webhook-events.d.ts +21 -0
  151. package/dist/hooks/use-webhook-events.d.ts.map +1 -0
  152. package/dist/hooks/use-webhook-events.js +9 -0
  153. package/dist/i18n/en.d.ts +592 -0
  154. package/dist/i18n/en.d.ts.map +1 -0
  155. package/dist/i18n/en.js +561 -0
  156. package/dist/i18n/index.d.ts +5 -0
  157. package/dist/i18n/index.d.ts.map +1 -0
  158. package/dist/i18n/index.js +3 -0
  159. package/dist/i18n/messages.d.ts +409 -0
  160. package/dist/i18n/messages.d.ts.map +1 -0
  161. package/dist/i18n/messages.js +1 -0
  162. package/dist/i18n/provider.d.ts +1207 -0
  163. package/dist/i18n/provider.d.ts.map +1 -0
  164. package/dist/i18n/provider.js +44 -0
  165. package/dist/i18n/ro.d.ts +592 -0
  166. package/dist/i18n/ro.d.ts.map +1 -0
  167. package/dist/i18n/ro.js +561 -0
  168. package/dist/i18n/utils.d.ts +4 -0
  169. package/dist/i18n/utils.d.ts.map +1 -0
  170. package/dist/i18n/utils.js +8 -0
  171. package/dist/index.d.ts +9 -0
  172. package/dist/index.d.ts.map +1 -0
  173. package/dist/index.js +8 -0
  174. package/dist/provider.d.ts +2 -0
  175. package/dist/provider.d.ts.map +1 -0
  176. package/dist/provider.js +1 -0
  177. package/dist/query-keys.d.ts +61 -0
  178. package/dist/query-keys.d.ts.map +1 -0
  179. package/dist/query-keys.js +30 -0
  180. package/dist/query-options.d.ts +999 -0
  181. package/dist/query-options.d.ts.map +1 -0
  182. package/dist/query-options.js +219 -0
  183. package/dist/schemas.d.ts +615 -0
  184. package/dist/schemas.d.ts.map +1 -0
  185. package/dist/schemas.js +144 -0
  186. package/dist/suppliers/admin/index.d.ts +69 -0
  187. package/dist/suppliers/admin/index.d.ts.map +1 -0
  188. package/dist/suppliers/admin/index.js +111 -0
  189. package/dist/suppliers/admin/pages/supplier-detail-page.d.ts +9 -0
  190. package/dist/suppliers/admin/pages/supplier-detail-page.d.ts.map +1 -0
  191. package/dist/suppliers/admin/pages/supplier-detail-page.js +11 -0
  192. package/dist/suppliers/admin/slots.d.ts +19 -0
  193. package/dist/suppliers/admin/slots.d.ts.map +1 -0
  194. package/dist/suppliers/admin/slots.js +18 -0
  195. package/dist/suppliers/admin/supplier-detail-host.d.ts +30 -0
  196. package/dist/suppliers/admin/supplier-detail-host.d.ts.map +1 -0
  197. package/dist/suppliers/admin/supplier-detail-host.js +34 -0
  198. package/dist/suppliers/admin/supplier-detail-skeleton.d.ts +9 -0
  199. package/dist/suppliers/admin/supplier-detail-skeleton.d.ts.map +1 -0
  200. package/dist/suppliers/admin/supplier-detail-skeleton.js +20 -0
  201. package/dist/suppliers/admin/suppliers-host.d.ts +11 -0
  202. package/dist/suppliers/admin/suppliers-host.d.ts.map +1 -0
  203. package/dist/suppliers/admin/suppliers-host.js +17 -0
  204. package/dist/suppliers/admin/suppliers-list-skeleton.d.ts +9 -0
  205. package/dist/suppliers/admin/suppliers-list-skeleton.d.ts.map +1 -0
  206. package/dist/suppliers/admin/suppliers-list-skeleton.js +24 -0
  207. package/dist/suppliers/client.d.ts +14 -0
  208. package/dist/suppliers/client.d.ts.map +1 -0
  209. package/dist/suppliers/client.js +59 -0
  210. package/dist/suppliers/components/message-format.d.ts +2 -0
  211. package/dist/suppliers/components/message-format.d.ts.map +1 -0
  212. package/dist/suppliers/components/message-format.js +3 -0
  213. package/dist/suppliers/components/rate-dialog.d.ts +11 -0
  214. package/dist/suppliers/components/rate-dialog.d.ts.map +1 -0
  215. package/dist/suppliers/components/rate-dialog.js +93 -0
  216. package/dist/suppliers/components/service-dialog.d.ts +10 -0
  217. package/dist/suppliers/components/service-dialog.d.ts.map +1 -0
  218. package/dist/suppliers/components/service-dialog.js +69 -0
  219. package/dist/suppliers/components/supplier-combobox.d.ts +13 -0
  220. package/dist/suppliers/components/supplier-combobox.d.ts.map +1 -0
  221. package/dist/suppliers/components/supplier-combobox.js +23 -0
  222. package/dist/suppliers/components/supplier-detail-page.d.ts +17 -0
  223. package/dist/suppliers/components/supplier-detail-page.d.ts.map +1 -0
  224. package/dist/suppliers/components/supplier-detail-page.js +105 -0
  225. package/dist/suppliers/components/supplier-dialog.d.ts +9 -0
  226. package/dist/suppliers/components/supplier-dialog.d.ts.map +1 -0
  227. package/dist/suppliers/components/supplier-dialog.js +118 -0
  228. package/dist/suppliers/components/supplier-service-row.d.ts +22 -0
  229. package/dist/suppliers/components/supplier-service-row.d.ts.map +1 -0
  230. package/dist/suppliers/components/supplier-service-row.js +18 -0
  231. package/dist/suppliers/components/suppliers-page.d.ts +10 -0
  232. package/dist/suppliers/components/suppliers-page.d.ts.map +1 -0
  233. package/dist/suppliers/components/suppliers-page.js +94 -0
  234. package/dist/suppliers/constants.d.ts +69 -0
  235. package/dist/suppliers/constants.d.ts.map +1 -0
  236. package/dist/suppliers/constants.js +34 -0
  237. package/dist/suppliers/hooks/index.d.ts +10 -0
  238. package/dist/suppliers/hooks/index.d.ts.map +1 -0
  239. package/dist/suppliers/hooks/index.js +10 -0
  240. package/dist/suppliers/hooks/use-supplier-mutation.d.ts +95 -0
  241. package/dist/suppliers/hooks/use-supplier-mutation.d.ts.map +1 -0
  242. package/dist/suppliers/hooks/use-supplier-mutation.js +41 -0
  243. package/dist/suppliers/hooks/use-supplier-note-mutation.d.ts +13 -0
  244. package/dist/suppliers/hooks/use-supplier-note-mutation.d.ts.map +1 -0
  245. package/dist/suppliers/hooks/use-supplier-note-mutation.js +20 -0
  246. package/dist/suppliers/hooks/use-supplier-notes.d.ts +13 -0
  247. package/dist/suppliers/hooks/use-supplier-notes.d.ts.map +1 -0
  248. package/dist/suppliers/hooks/use-supplier-notes.js +12 -0
  249. package/dist/suppliers/hooks/use-supplier-rate-mutation.d.ts +56 -0
  250. package/dist/suppliers/hooks/use-supplier-rate-mutation.d.ts.map +1 -0
  251. package/dist/suppliers/hooks/use-supplier-rate-mutation.js +41 -0
  252. package/dist/suppliers/hooks/use-supplier-service-mutation.d.ts +45 -0
  253. package/dist/suppliers/hooks/use-supplier-service-mutation.d.ts.map +1 -0
  254. package/dist/suppliers/hooks/use-supplier-service-mutation.js +44 -0
  255. package/dist/suppliers/hooks/use-supplier-service-rates.d.ts +20 -0
  256. package/dist/suppliers/hooks/use-supplier-service-rates.d.ts.map +1 -0
  257. package/dist/suppliers/hooks/use-supplier-service-rates.js +12 -0
  258. package/dist/suppliers/hooks/use-supplier-services.d.ts +19 -0
  259. package/dist/suppliers/hooks/use-supplier-services.d.ts.map +1 -0
  260. package/dist/suppliers/hooks/use-supplier-services.js +12 -0
  261. package/dist/suppliers/hooks/use-supplier.d.ts +38 -0
  262. package/dist/suppliers/hooks/use-supplier.d.ts.map +1 -0
  263. package/dist/suppliers/hooks/use-supplier.js +9 -0
  264. package/dist/suppliers/hooks/use-suppliers.d.ts +42 -0
  265. package/dist/suppliers/hooks/use-suppliers.d.ts.map +1 -0
  266. package/dist/suppliers/hooks/use-suppliers.js +9 -0
  267. package/dist/suppliers/i18n/en.d.ts +204 -0
  268. package/dist/suppliers/i18n/en.d.ts.map +1 -0
  269. package/dist/suppliers/i18n/en.js +203 -0
  270. package/dist/suppliers/i18n/index.d.ts +5 -0
  271. package/dist/suppliers/i18n/index.d.ts.map +1 -0
  272. package/dist/suppliers/i18n/index.js +3 -0
  273. package/dist/suppliers/i18n/messages.d.ts +187 -0
  274. package/dist/suppliers/i18n/messages.d.ts.map +1 -0
  275. package/dist/suppliers/i18n/messages.js +1 -0
  276. package/dist/suppliers/i18n/provider.d.ts +430 -0
  277. package/dist/suppliers/i18n/provider.d.ts.map +1 -0
  278. package/dist/suppliers/i18n/provider.js +44 -0
  279. package/dist/suppliers/i18n/ro.d.ts +204 -0
  280. package/dist/suppliers/i18n/ro.d.ts.map +1 -0
  281. package/dist/suppliers/i18n/ro.js +203 -0
  282. package/dist/suppliers/index.d.ts +9 -0
  283. package/dist/suppliers/index.d.ts.map +1 -0
  284. package/dist/suppliers/index.js +8 -0
  285. package/dist/suppliers/provider.d.ts +2 -0
  286. package/dist/suppliers/provider.d.ts.map +1 -0
  287. package/dist/suppliers/provider.js +1 -0
  288. package/dist/suppliers/query-keys.d.ts +29 -0
  289. package/dist/suppliers/query-keys.d.ts.map +1 -0
  290. package/dist/suppliers/query-keys.js +12 -0
  291. package/dist/suppliers/query-options.d.ts +467 -0
  292. package/dist/suppliers/query-options.d.ts.map +1 -0
  293. package/dist/suppliers/query-options.js +63 -0
  294. package/dist/suppliers/schemas.d.ts +363 -0
  295. package/dist/suppliers/schemas.d.ts.map +1 -0
  296. package/dist/suppliers/schemas.js +109 -0
  297. package/dist/suppliers/ui.d.ts +9 -0
  298. package/dist/suppliers/ui.d.ts.map +1 -0
  299. package/dist/suppliers/ui.js +8 -0
  300. package/dist/suppliers/utils.d.ts +4 -0
  301. package/dist/suppliers/utils.d.ts.map +1 -0
  302. package/dist/suppliers/utils.js +10 -0
  303. package/dist/ui.d.ts +16 -0
  304. package/dist/ui.d.ts.map +1 -0
  305. package/dist/ui.js +14 -0
  306. package/dist/utils.d.ts +10 -0
  307. package/dist/utils.d.ts.map +1 -0
  308. package/dist/utils.js +44 -0
  309. package/package.json +263 -0
  310. package/src/external-refs/styles.css +11 -0
  311. package/src/styles.css +11 -0
  312. package/src/suppliers/styles.css +11 -0
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { Badge, Button, Card, CardContent, CardHeader, CardTitle, ConfirmActionButton, } from "@voyant-travel/ui/components";
4
+ import { cn } from "@voyant-travel/ui/lib/utils";
5
+ import { ArrowLeft, Link2, Loader2, Package } from "lucide-react";
6
+ import { useDistributionUiI18nOrDefault } from "../i18n/index.js";
7
+ import { distributionQueryKeys, fetchWithValidation, getChannelQueryOptions, getMappingQueryOptions, getProductQueryOptions, successEnvelope, useVoyantDistributionContext, } from "../index.js";
8
+ import { formatDistributionDateTime } from "./distribution-shared.js";
9
+ const noop = () => { };
10
+ export function MappingDetailPage({ id, className, onBack = noop, onDeleted = noop, onChannelOpen = noop, onProductOpen = noop, }) {
11
+ const i18n = useDistributionUiI18nOrDefault();
12
+ const { messages } = i18n;
13
+ const detail = messages.details.mapping;
14
+ const client = useVoyantDistributionContext();
15
+ const queryClient = useQueryClient();
16
+ const mappingQuery = useQuery({
17
+ ...getMappingQueryOptions(client, id),
18
+ select: (result) => result.data,
19
+ });
20
+ const mapping = mappingQuery.data;
21
+ const channelQuery = useQuery({
22
+ ...getChannelQueryOptions(client, mapping?.channelId),
23
+ select: (result) => result.data,
24
+ enabled: Boolean(mapping?.channelId),
25
+ });
26
+ const productQuery = useQuery({
27
+ ...getProductQueryOptions(client, mapping?.productId),
28
+ select: (result) => result.data,
29
+ enabled: Boolean(mapping?.productId),
30
+ });
31
+ const remove = useMutation({
32
+ mutationFn: () => fetchWithValidation(`/v1/distribution/product-mappings/${id}`, successEnvelope, client, {
33
+ method: "DELETE", // i18n-literal-ok HTTP method
34
+ }),
35
+ onSuccess: () => {
36
+ void queryClient.invalidateQueries({ queryKey: distributionQueryKeys.mappings() });
37
+ queryClient.removeQueries({ queryKey: distributionQueryKeys.mapping(id) });
38
+ onDeleted();
39
+ onBack();
40
+ },
41
+ });
42
+ if (mappingQuery.isPending) {
43
+ return (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }));
44
+ }
45
+ if (!mapping) {
46
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-12", children: [_jsx("p", { className: "text-muted-foreground", children: detail.notFound }), _jsx(Button, { variant: "outline", onClick: onBack, children: messages.common.backToDistribution })] }));
47
+ }
48
+ return (_jsxs("div", { "data-slot": "mapping-detail-page", className: cn("flex flex-col gap-6 p-6", className), children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: onBack, children: _jsx(ArrowLeft, { className: "h-4 w-4" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: detail.title }), _jsxs("div", { className: "mt-1 flex items-center gap-2", children: [_jsx(Badge, { variant: mapping.active ? "default" : "secondary", children: mapping.active ? messages.common.active : messages.common.inactive }), _jsx(Badge, { variant: "outline", children: mapping.externalProductId })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", onClick: () => onChannelOpen(mapping.channelId), children: [_jsx(Link2, { className: "mr-2 h-4 w-4" }), detail.openChannel] }), _jsxs(Button, { variant: "outline", onClick: () => onProductOpen(mapping.productId), children: [_jsx(Package, { className: "mr-2 h-4 w-4" }), detail.openProduct] }), _jsx(ConfirmActionButton, { buttonLabel: detail.deleteButton, confirmLabel: detail.deleteButton, title: detail.deleteConfirm, description: detail.deleteDescription, variant: "destructive", confirmVariant: "destructive", disabled: remove.isPending, onConfirm: async () => {
49
+ await remove.mutateAsync();
50
+ } })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: detail.sections.details }) }), _jsxs(CardContent, { className: "grid gap-3 text-sm md:grid-cols-2", children: [_jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.channelLabel, ":"] }), " ", _jsx("span", { children: channelQuery.data?.name ?? mapping.channelId })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.productLabel, ":"] }), " ", _jsx("span", { children: productQuery.data?.name ?? mapping.productId })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [detail.labels.externalProduct, ":"] }), " ", _jsx("span", { children: mapping.externalProductId })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [detail.labels.externalRate, ":"] }), " ", _jsx("span", { children: mapping.externalRateId ?? messages.common.none })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [detail.labels.externalCategory, ":"] }), " ", _jsx("span", { children: mapping.externalCategoryId ?? messages.common.none })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.createdLabel, ":"] }), " ", _jsx("span", { children: formatDistributionDateTime(mapping.createdAt, i18n) })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.updatedLabel, ":"] }), " ", _jsx("span", { children: formatDistributionDateTime(mapping.updatedAt, i18n) })] })] })] })] }));
51
+ }
@@ -0,0 +1,9 @@
1
+ export interface WebhookEventDetailPageProps {
2
+ id: string;
3
+ className?: string;
4
+ onBack?: () => void;
5
+ onDeleted?: () => void;
6
+ onChannelOpen?: (channelId: string) => void;
7
+ }
8
+ export declare function WebhookEventDetailPage({ id, className, onBack, onDeleted, onChannelOpen, }: WebhookEventDetailPageProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=webhook-event-detail-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-event-detail-page.d.ts","sourceRoot":"","sources":["../../src/components/webhook-event-detail-page.tsx"],"names":[],"mappings":"AAuBA,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5C;AAID,wBAAgB,sBAAsB,CAAC,EACrC,EAAE,EACF,SAAS,EACT,MAAa,EACb,SAAgB,EAChB,aAAoB,GACrB,EAAE,2BAA2B,2CA0I7B"}
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { Badge, Button, Card, CardContent, CardHeader, CardTitle, ConfirmActionButton, } from "@voyant-travel/ui/components";
4
+ import { cn } from "@voyant-travel/ui/lib/utils";
5
+ import { ArrowLeft, Link2, Loader2, Webhook } from "lucide-react";
6
+ import { useDistributionUiI18nOrDefault } from "../i18n/index.js";
7
+ import { distributionQueryKeys, fetchWithValidation, getChannelQueryOptions, getWebhookEventQueryOptions, successEnvelope, useVoyantDistributionContext, } from "../index.js";
8
+ import { formatDistributionDateTime } from "./distribution-shared.js";
9
+ const noop = () => { };
10
+ export function WebhookEventDetailPage({ id, className, onBack = noop, onDeleted = noop, onChannelOpen = noop, }) {
11
+ const i18n = useDistributionUiI18nOrDefault();
12
+ const { messages } = i18n;
13
+ const detail = messages.details.webhookEvent;
14
+ const client = useVoyantDistributionContext();
15
+ const queryClient = useQueryClient();
16
+ const eventQuery = useQuery({
17
+ ...getWebhookEventQueryOptions(client, id),
18
+ select: (result) => result.data,
19
+ });
20
+ const event = eventQuery.data;
21
+ const channelQuery = useQuery({
22
+ ...getChannelQueryOptions(client, event?.channelId),
23
+ select: (result) => result.data,
24
+ enabled: Boolean(event?.channelId),
25
+ });
26
+ const remove = useMutation({
27
+ mutationFn: () => fetchWithValidation(`/v1/distribution/webhook-events/${id}`, successEnvelope, client, {
28
+ method: "DELETE", // i18n-literal-ok HTTP method
29
+ }),
30
+ onSuccess: () => {
31
+ void queryClient.invalidateQueries({ queryKey: distributionQueryKeys.webhookEvents() });
32
+ queryClient.removeQueries({ queryKey: distributionQueryKeys.webhookEvent(id) });
33
+ onDeleted();
34
+ onBack();
35
+ },
36
+ });
37
+ if (eventQuery.isPending) {
38
+ return (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }));
39
+ }
40
+ if (!event) {
41
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-12", children: [_jsx("p", { className: "text-muted-foreground", children: detail.notFound }), _jsx(Button, { variant: "outline", onClick: onBack, children: messages.common.backToDistribution })] }));
42
+ }
43
+ return (_jsxs("div", { "data-slot": "webhook-event-detail-page", className: cn("flex flex-col gap-6 p-6", className), children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: onBack, children: _jsx(ArrowLeft, { className: "h-4 w-4" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: detail.title }), _jsxs("div", { className: "mt-1 flex items-center gap-2", children: [_jsx(Badge, { variant: "outline", children: messages.common.webhookStatusLabels[event.status] }), _jsx(Badge, { variant: "secondary", children: event.eventType })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", onClick: () => onChannelOpen(event.channelId), children: [_jsx(Link2, { className: "mr-2 h-4 w-4" }), detail.openChannel] }), _jsx(ConfirmActionButton, { buttonLabel: detail.deleteButton, confirmLabel: detail.deleteButton, title: detail.deleteConfirm, description: detail.deleteDescription, variant: "destructive", confirmVariant: "destructive", disabled: remove.isPending, onConfirm: async () => {
44
+ await remove.mutateAsync();
45
+ } })] })] }), _jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-row items-center gap-2", children: [_jsx(Webhook, { className: "h-4 w-4" }), _jsx(CardTitle, { children: detail.sections.details })] }), _jsxs(CardContent, { className: "grid gap-3 text-sm", children: [_jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.channelLabel, ":"] }), " ", _jsx("span", { children: channelQuery.data?.name ?? event.channelId })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [detail.labels.externalEvent, ":"] }), " ", _jsx("span", { children: event.externalEventId ?? messages.common.none })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [detail.labels.received, ":"] }), " ", _jsx("span", { children: formatDistributionDateTime(event.receivedAt, i18n) })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [detail.labels.processed, ":"] }), " ", _jsx("span", { children: formatDistributionDateTime(event.processedAt, i18n) })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.createdLabel, ":"] }), " ", _jsx("span", { children: formatDistributionDateTime(event.createdAt, i18n) })] }), _jsxs("div", { children: [_jsxs("span", { className: "text-muted-foreground", children: [messages.common.updatedLabel, ":"] }), " ", _jsx("span", { children: formatDistributionDateTime(event.updatedAt, i18n) })] }), event.errorMessage ? (_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-muted-foreground", children: detail.labels.error }), _jsx("div", { className: "whitespace-pre-wrap rounded-md border p-3", children: event.errorMessage })] })) : null] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: detail.sections.payload }) }), _jsx(CardContent, { className: "text-sm", children: _jsx("pre", { className: "overflow-x-auto rounded-md bg-muted p-3 text-xs", children: JSON.stringify(event.payload, null, 2) }) })] })] })] }));
46
+ }
@@ -0,0 +1,103 @@
1
+ export declare const NONE_VALUE = "__none__";
2
+ export declare const channelKindOptions: readonly [{
3
+ readonly value: "direct";
4
+ readonly label: "Direct";
5
+ }, {
6
+ readonly value: "affiliate";
7
+ readonly label: "Affiliate";
8
+ }, {
9
+ readonly value: "ota";
10
+ readonly label: "OTA";
11
+ }, {
12
+ readonly value: "reseller";
13
+ readonly label: "Reseller";
14
+ }, {
15
+ readonly value: "marketplace";
16
+ readonly label: "Marketplace";
17
+ }, {
18
+ readonly value: "api_partner";
19
+ readonly label: "API Partner";
20
+ }, {
21
+ readonly value: "connect";
22
+ readonly label: "Connect";
23
+ }];
24
+ export declare const channelStatusOptions: readonly [{
25
+ readonly value: "active";
26
+ readonly label: "Active";
27
+ }, {
28
+ readonly value: "inactive";
29
+ readonly label: "Inactive";
30
+ }, {
31
+ readonly value: "pending";
32
+ readonly label: "Pending";
33
+ }, {
34
+ readonly value: "archived";
35
+ readonly label: "Archived";
36
+ }];
37
+ export declare const contractStatusOptions: readonly [{
38
+ readonly value: "draft";
39
+ readonly label: "Draft";
40
+ }, {
41
+ readonly value: "active";
42
+ readonly label: "Active";
43
+ }, {
44
+ readonly value: "expired";
45
+ readonly label: "Expired";
46
+ }, {
47
+ readonly value: "terminated";
48
+ readonly label: "Terminated";
49
+ }];
50
+ export declare const paymentOwnerOptions: readonly [{
51
+ readonly value: "operator";
52
+ readonly label: "Operator";
53
+ }, {
54
+ readonly value: "channel";
55
+ readonly label: "Channel";
56
+ }, {
57
+ readonly value: "split";
58
+ readonly label: "Split";
59
+ }];
60
+ export declare const cancellationOwnerOptions: readonly [{
61
+ readonly value: "operator";
62
+ readonly label: "Operator";
63
+ }, {
64
+ readonly value: "channel";
65
+ readonly label: "Channel";
66
+ }, {
67
+ readonly value: "mixed";
68
+ readonly label: "Mixed";
69
+ }];
70
+ export declare const commissionScopeOptions: readonly [{
71
+ readonly value: "booking";
72
+ readonly label: "Booking";
73
+ }, {
74
+ readonly value: "product";
75
+ readonly label: "Product";
76
+ }, {
77
+ readonly value: "rate";
78
+ readonly label: "Rate";
79
+ }, {
80
+ readonly value: "category";
81
+ readonly label: "Category";
82
+ }];
83
+ export declare const commissionTypeOptions: readonly [{
84
+ readonly value: "fixed";
85
+ readonly label: "Fixed";
86
+ }, {
87
+ readonly value: "percentage";
88
+ readonly label: "Percentage";
89
+ }];
90
+ export declare const webhookStatusOptions: readonly [{
91
+ readonly value: "pending";
92
+ readonly label: "Pending";
93
+ }, {
94
+ readonly value: "processed";
95
+ readonly label: "Processed";
96
+ }, {
97
+ readonly value: "failed";
98
+ readonly label: "Failed";
99
+ }, {
100
+ readonly value: "ignored";
101
+ readonly label: "Ignored";
102
+ }];
103
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,aAAa,CAAA;AAEpC,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAQrB,CAAA;AAEV,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAKvB,CAAA;AAEV,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAKxB,CAAA;AAEV,eAAO,MAAM,mBAAmB;;;;;;;;;EAItB,CAAA;AAEV,eAAO,MAAM,wBAAwB;;;;;;;;;EAI3B,CAAA;AAEV,eAAO,MAAM,sBAAsB;;;;;;;;;;;;EAKzB,CAAA;AAEV,eAAO,MAAM,qBAAqB;;;;;;EAGxB,CAAA;AAEV,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAKvB,CAAA"}
@@ -0,0 +1,48 @@
1
+ export const NONE_VALUE = "__none__";
2
+ export const channelKindOptions = [
3
+ { value: "direct", label: "Direct" },
4
+ { value: "affiliate", label: "Affiliate" },
5
+ { value: "ota", label: "OTA" },
6
+ { value: "reseller", label: "Reseller" },
7
+ { value: "marketplace", label: "Marketplace" },
8
+ { value: "api_partner", label: "API Partner" },
9
+ { value: "connect", label: "Connect" },
10
+ ];
11
+ export const channelStatusOptions = [
12
+ { value: "active", label: "Active" },
13
+ { value: "inactive", label: "Inactive" },
14
+ { value: "pending", label: "Pending" },
15
+ { value: "archived", label: "Archived" },
16
+ ];
17
+ export const contractStatusOptions = [
18
+ { value: "draft", label: "Draft" },
19
+ { value: "active", label: "Active" },
20
+ { value: "expired", label: "Expired" },
21
+ { value: "terminated", label: "Terminated" },
22
+ ];
23
+ export const paymentOwnerOptions = [
24
+ { value: "operator", label: "Operator" },
25
+ { value: "channel", label: "Channel" },
26
+ { value: "split", label: "Split" },
27
+ ];
28
+ export const cancellationOwnerOptions = [
29
+ { value: "operator", label: "Operator" },
30
+ { value: "channel", label: "Channel" },
31
+ { value: "mixed", label: "Mixed" },
32
+ ];
33
+ export const commissionScopeOptions = [
34
+ { value: "booking", label: "Booking" },
35
+ { value: "product", label: "Product" },
36
+ { value: "rate", label: "Rate" },
37
+ { value: "category", label: "Category" },
38
+ ];
39
+ export const commissionTypeOptions = [
40
+ { value: "fixed", label: "Fixed" },
41
+ { value: "percentage", label: "Percentage" },
42
+ ];
43
+ export const webhookStatusOptions = [
44
+ { value: "pending", label: "Pending" },
45
+ { value: "processed", label: "Processed" },
46
+ { value: "failed", label: "Failed" },
47
+ { value: "ignored", label: "Ignored" },
48
+ ];
@@ -0,0 +1,14 @@
1
+ import type { z } from "zod";
2
+ export type VoyantFetcher = (url: string, init?: RequestInit) => Promise<Response>;
3
+ export declare const defaultFetcher: VoyantFetcher;
4
+ export declare class VoyantApiError extends Error {
5
+ readonly status: number;
6
+ readonly body: unknown;
7
+ constructor(message: string, status: number, body: unknown);
8
+ }
9
+ export interface FetchWithValidationOptions {
10
+ baseUrl: string;
11
+ fetcher: VoyantFetcher;
12
+ }
13
+ export declare function fetchWithValidation<TOut>(path: string, schema: z.ZodType<TOut>, options: FetchWithValidationOptions, init?: RequestInit): Promise<TOut>;
14
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/external-refs/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAElF,eAAO,MAAM,cAAc,EAAE,aACoB,CAAA;AAEjD,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;gBAEV,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO;CAM3D;AAaD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,aAAa,CAAA;CACvB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAC5C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EACvB,OAAO,EAAE,0BAA0B,EACnC,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
@@ -0,0 +1,58 @@
1
+ export const defaultFetcher = (url, init) => fetch(url, { credentials: "include", ...init });
2
+ export class VoyantApiError extends Error {
3
+ status;
4
+ body;
5
+ constructor(message, status, body) {
6
+ super(message);
7
+ this.name = "VoyantApiError";
8
+ this.status = status;
9
+ this.body = body;
10
+ }
11
+ }
12
+ function extractErrorMessage(status, statusText, body) {
13
+ if (typeof body === "object" && body !== null && "error" in body) {
14
+ const err = body.error;
15
+ if (typeof err === "string")
16
+ return err;
17
+ if (typeof err === "object" && err !== null && "message" in err) {
18
+ return String(err.message);
19
+ }
20
+ }
21
+ return `Voyant API error: ${status} ${statusText}`;
22
+ }
23
+ export async function fetchWithValidation(path, schema, options, init) {
24
+ const url = joinUrl(options.baseUrl, path);
25
+ const headers = new Headers(init?.headers);
26
+ if (init?.body !== undefined && !headers.has("Content-Type")) {
27
+ headers.set("Content-Type", "application/json");
28
+ }
29
+ const response = await options.fetcher(url, { ...init, headers });
30
+ if (!response.ok) {
31
+ const body = await safeJson(response);
32
+ throw new VoyantApiError(extractErrorMessage(response.status, response.statusText, body), response.status, body);
33
+ }
34
+ if (response.status === 204)
35
+ return schema.parse(undefined);
36
+ const body = await safeJson(response);
37
+ const parsed = schema.safeParse(body);
38
+ if (!parsed.success) {
39
+ throw new VoyantApiError(`Voyant API response failed validation: ${parsed.error.message}`, response.status, body);
40
+ }
41
+ return parsed.data;
42
+ }
43
+ async function safeJson(response) {
44
+ const text = await response.text();
45
+ if (!text)
46
+ return undefined;
47
+ try {
48
+ return JSON.parse(text);
49
+ }
50
+ catch {
51
+ return text;
52
+ }
53
+ }
54
+ function joinUrl(baseUrl, path) {
55
+ const trimmedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
56
+ const trimmedPath = path.startsWith("/") ? path : `/${path}`;
57
+ return `${trimmedBase}${trimmedPath}`;
58
+ }
@@ -0,0 +1,21 @@
1
+ type KnownEntityType = "person" | "organization" | "supplier" | "booking" | "product";
2
+ export interface EntityRefPickerMessages {
3
+ entityTypeLabel: string;
4
+ entityLabel: string;
5
+ customEntityTypeLabel: string;
6
+ typePlaceholder: string;
7
+ entityPlaceholder: string;
8
+ entityTypeLabels: Record<KnownEntityType, string>;
9
+ }
10
+ export interface EntityRefPickerProps {
11
+ entityType: string;
12
+ entityId: string;
13
+ onChange: (scope: {
14
+ entityType: string;
15
+ entityId: string;
16
+ }) => void;
17
+ messages: EntityRefPickerMessages;
18
+ }
19
+ export declare function EntityRefPicker({ entityType, entityId, onChange, messages, }: EntityRefPickerProps): import("react/jsx-runtime").JSX.Element;
20
+ export {};
21
+ //# sourceMappingURL=entity-ref-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-ref-picker.d.ts","sourceRoot":"","sources":["../../../src/external-refs/components/entity-ref-picker.tsx"],"names":[],"mappings":"AAgBA,KAAK,eAAe,GAAG,QAAQ,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAA;AAWrF,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;IACnE,QAAQ,EAAE,uBAAuB,CAAA;CAClC;AAMD,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,oBAAoB,2CA4EtB"}
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { BookingCombobox } from "@voyant-travel/bookings-react/ui";
4
+ import { ProductCombobox } from "@voyant-travel/inventory-react/ui";
5
+ import { OrganizationCombobox, PersonCombobox } from "@voyant-travel/relationships-react/ui";
6
+ import { Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyant-travel/ui/components";
7
+ import { SupplierCombobox } from "../../suppliers/ui.js";
8
+ const KNOWN_ENTITY_TYPES = [
9
+ "person",
10
+ "organization",
11
+ "supplier",
12
+ "booking",
13
+ "product",
14
+ ];
15
+ function isKnownEntityType(value) {
16
+ return KNOWN_ENTITY_TYPES.includes(value);
17
+ }
18
+ export function EntityRefPicker({ entityType, entityId, onChange, messages, }) {
19
+ const selectedType = isKnownEntityType(entityType) ? entityType : "custom";
20
+ const setEntityType = (nextType) => {
21
+ if (nextType === "custom") {
22
+ onChange({ entityType: "", entityId: "" });
23
+ return;
24
+ }
25
+ onChange({ entityType: nextType, entityId: "" });
26
+ };
27
+ const setEntityId = (nextId) => {
28
+ onChange({ entityType, entityId: nextId ?? "" });
29
+ };
30
+ const entityPicker = isKnownEntityType(entityType) ? (entityType === "person" ? (_jsx(PersonCombobox, { value: entityId || null, onChange: setEntityId })) : entityType === "organization" ? (_jsx(OrganizationCombobox, { value: entityId || null, onChange: setEntityId })) : entityType === "supplier" ? (_jsx(SupplierCombobox, { value: entityId || null, onChange: setEntityId })) : entityType === "booking" ? (_jsx(BookingCombobox, { value: entityId || null, onChange: setEntityId })) : (_jsx(ProductCombobox, { value: entityId || null, onChange: setEntityId }))) : (_jsx(Input, { value: entityId, onChange: (event) => onChange({ entityType, entityId: event.target.value }), placeholder: messages.entityPlaceholder }));
31
+ return (_jsxs("div", { className: "grid max-w-2xl grid-cols-1 gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.entityTypeLabel }), _jsxs(Select, { items: [
32
+ ...KNOWN_ENTITY_TYPES.map((type) => ({
33
+ label: messages.entityTypeLabels[type],
34
+ value: type,
35
+ })),
36
+ { label: messages.customEntityTypeLabel, value: "custom" },
37
+ ], value: selectedType, onValueChange: (value) => setEntityType(value ?? "custom"), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, { placeholder: messages.typePlaceholder }) }), _jsxs(SelectContent, { children: [KNOWN_ENTITY_TYPES.map((type) => (_jsx(SelectItem, { value: type, children: messages.entityTypeLabels[type] }, type))), _jsx(SelectItem, { value: "custom", children: messages.customEntityTypeLabel })] })] }), selectedType === "custom" ? (_jsx(Input, { value: entityType, onChange: (event) => onChange({ entityType: event.target.value, entityId }), placeholder: messages.typePlaceholder })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.entityLabel }), entityPicker] })] }));
38
+ }
@@ -0,0 +1,11 @@
1
+ import { type ExternalRefRecord } from "../index.js";
2
+ export interface ExternalRefDialogProps {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ entityType: string;
6
+ entityId: string;
7
+ externalRef?: ExternalRefRecord;
8
+ onSuccess?: (externalRef: ExternalRefRecord) => void;
9
+ }
10
+ export declare function ExternalRefDialog({ open, onOpenChange, entityType, entityId, externalRef, onSuccess, }: ExternalRefDialogProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=external-ref-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-ref-dialog.d.ts","sourceRoot":"","sources":["../../../src/external-refs/components/external-ref-dialog.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAEL,KAAK,iBAAiB,EAGvB,MAAM,aAAa,CAAA;AA+CpB,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACrD;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,GACV,EAAE,sBAAsB,2CAiMxB"}
@@ -0,0 +1,120 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Button, Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Textarea, } from "@voyant-travel/ui/components";
4
+ import { zodResolver } from "@voyant-travel/ui/lib/zod-resolver";
5
+ import { Loader2 } from "lucide-react";
6
+ import { useEffect } from "react";
7
+ import { useForm } from "react-hook-form";
8
+ import { z } from "zod/v4";
9
+ import { useExternalRefsUiI18nOrDefault } from "../i18n/provider.js";
10
+ import { useExternalRefMutation, } from "../index.js";
11
+ const REF_STATUSES = ["active", "inactive", "archived"];
12
+ function createFormSchema(messages) {
13
+ return z.object({
14
+ sourceSystem: z
15
+ .string()
16
+ .min(1, messages.externalRefDialog.validation.sourceSystemRequired)
17
+ .max(100),
18
+ objectType: z
19
+ .string()
20
+ .min(1, messages.externalRefDialog.validation.objectTypeRequired)
21
+ .max(100),
22
+ namespace: z.string().min(1).max(100),
23
+ externalId: z
24
+ .string()
25
+ .min(1, messages.externalRefDialog.validation.externalIdRequired)
26
+ .max(255),
27
+ externalParentId: z.string().optional().nullable(),
28
+ isPrimary: z.boolean(),
29
+ status: z.enum(REF_STATUSES),
30
+ metadataJson: z
31
+ .string()
32
+ .refine((value) => {
33
+ if (!value || value.trim() === "")
34
+ return true;
35
+ try {
36
+ const parsed = JSON.parse(value);
37
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed);
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }, { message: messages.externalRefDialog.validation.metadataMustBeObject })
43
+ .optional()
44
+ .nullable(),
45
+ });
46
+ }
47
+ export function ExternalRefDialog({ open, onOpenChange, entityType, entityId, externalRef, onSuccess, }) {
48
+ const isEditing = Boolean(externalRef);
49
+ const { create, update } = useExternalRefMutation();
50
+ const { messages } = useExternalRefsUiI18nOrDefault();
51
+ const m = messages.externalRefDialog;
52
+ const formSchema = createFormSchema(messages);
53
+ const form = useForm({
54
+ resolver: zodResolver(formSchema),
55
+ defaultValues: {
56
+ sourceSystem: "",
57
+ objectType: "",
58
+ namespace: "default",
59
+ externalId: "",
60
+ externalParentId: "",
61
+ isPrimary: false,
62
+ status: "active",
63
+ metadataJson: "",
64
+ },
65
+ });
66
+ useEffect(() => {
67
+ if (open && externalRef) {
68
+ form.reset({
69
+ sourceSystem: externalRef.sourceSystem,
70
+ objectType: externalRef.objectType,
71
+ namespace: externalRef.namespace,
72
+ externalId: externalRef.externalId,
73
+ externalParentId: externalRef.externalParentId ?? "",
74
+ isPrimary: externalRef.isPrimary,
75
+ status: externalRef.status,
76
+ metadataJson: externalRef.metadata ? JSON.stringify(externalRef.metadata, null, 2) : "",
77
+ });
78
+ return;
79
+ }
80
+ if (open) {
81
+ form.reset({
82
+ sourceSystem: "",
83
+ objectType: "",
84
+ namespace: "default",
85
+ externalId: "",
86
+ externalParentId: "",
87
+ isPrimary: false,
88
+ status: "active",
89
+ metadataJson: "",
90
+ });
91
+ }
92
+ }, [externalRef, form, open]);
93
+ const onSubmit = async (values) => {
94
+ const metadata = values.metadataJson && values.metadataJson.trim() !== ""
95
+ ? JSON.parse(values.metadataJson)
96
+ : null;
97
+ const payload = {
98
+ entityType,
99
+ entityId,
100
+ sourceSystem: values.sourceSystem,
101
+ objectType: values.objectType,
102
+ namespace: values.namespace,
103
+ externalId: values.externalId,
104
+ externalParentId: values.externalParentId || null,
105
+ isPrimary: values.isPrimary,
106
+ status: values.status,
107
+ metadata,
108
+ };
109
+ const saved = isEditing
110
+ ? await update.mutateAsync({ id: externalRef.id, input: payload })
111
+ : await create.mutateAsync(payload);
112
+ onOpenChange(false);
113
+ onSuccess?.(saved);
114
+ };
115
+ const isSubmitting = form.formState.isSubmitting || create.isPending || update.isPending;
116
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing ? m.titles.edit : m.titles.add }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), children: [_jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.sourceSystem }), _jsx(Input, { ...form.register("sourceSystem"), placeholder: m.placeholders.sourceSystem }), form.formState.errors.sourceSystem ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.sourceSystem.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.objectType }), _jsx(Input, { ...form.register("objectType"), placeholder: m.placeholders.objectType }), form.formState.errors.objectType ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.objectType.message })) : null] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-3", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.namespace }), _jsx(Input, { ...form.register("namespace"), placeholder: m.placeholders.namespace })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.externalId }), _jsx(Input, { ...form.register("externalId"), placeholder: m.placeholders.externalId }), form.formState.errors.externalId ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.externalId.message })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.externalParentId }), _jsx(Input, { ...form.register("externalParentId"), placeholder: m.placeholders.externalParentId })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.status }), _jsxs(Select, { items: REF_STATUSES.map((status) => ({
117
+ label: messages.common.refStatusLabels[status],
118
+ value: status,
119
+ })), value: form.watch("status"), onValueChange: (value) => form.setValue("status", value), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: REF_STATUSES.map((status) => (_jsx(SelectItem, { value: status, children: messages.common.refStatusLabels[status] }, status))) })] })] }), _jsxs("div", { className: "flex items-center gap-2 pt-6", children: [_jsx(Switch, { checked: form.watch("isPrimary"), onCheckedChange: (value) => form.setValue("isPrimary", value) }), _jsx(Label, { children: m.labels.primary })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: m.labels.metadataJson }), _jsx(Textarea, { ...form.register("metadataJson"), rows: 4, className: "font-mono text-xs", placeholder: m.placeholders.metadataJson }), form.formState.errors.metadataJson ? (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.metadataJson.message })) : null] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: m.actions.cancel }), _jsxs(Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, isEditing ? m.actions.saveChanges : m.actions.addExternalRef] })] })] })] }) }));
120
+ }
@@ -0,0 +1,16 @@
1
+ export interface ExternalRefsPageProps {
2
+ entityType?: string;
3
+ entityId?: string;
4
+ onScopeChange?: (scope: {
5
+ entityType: string;
6
+ entityId: string;
7
+ }) => void;
8
+ className?: string;
9
+ }
10
+ export declare function ExternalRefsPage({ entityType, entityId, onScopeChange, className, }?: ExternalRefsPageProps): import("react/jsx-runtime").JSX.Element;
11
+ export interface ExternalRefsTabProps {
12
+ entityType: string;
13
+ entityId: string;
14
+ }
15
+ export declare function ExternalRefsTab({ entityType, entityId }: ExternalRefsTabProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=external-refs-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-refs-page.d.ts","sourceRoot":"","sources":["../../../src/external-refs/components/external-refs-page.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,QAAQ,EACR,aAAa,EACb,SAAS,GACV,GAAE,qBAA0B,2CAiD5B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,oBAAoB,2CAkK7E"}