@voyant-travel/bookings-react 0.119.3

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 (602) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +87 -0
  3. package/dist/admin/booking-contract-dialog.d.ts +22 -0
  4. package/dist/admin/booking-contract-dialog.d.ts.map +1 -0
  5. package/dist/admin/booking-contract-dialog.js +161 -0
  6. package/dist/admin/booking-detail-host.d.ts +103 -0
  7. package/dist/admin/booking-detail-host.d.ts.map +1 -0
  8. package/dist/admin/booking-detail-host.js +127 -0
  9. package/dist/admin/booking-detail-skeleton.d.ts +7 -0
  10. package/dist/admin/booking-detail-skeleton.d.ts.map +1 -0
  11. package/dist/admin/booking-detail-skeleton.js +24 -0
  12. package/dist/admin/booking-documents-table.d.ts +13 -0
  13. package/dist/admin/booking-documents-table.d.ts.map +1 -0
  14. package/dist/admin/booking-documents-table.js +259 -0
  15. package/dist/admin/booking-invoice-sheet.d.ts +18 -0
  16. package/dist/admin/booking-invoice-sheet.d.ts.map +1 -0
  17. package/dist/admin/booking-invoice-sheet.js +101 -0
  18. package/dist/admin/booking-journey-host.d.ts +24 -0
  19. package/dist/admin/booking-journey-host.d.ts.map +1 -0
  20. package/dist/admin/booking-journey-host.js +278 -0
  21. package/dist/admin/bookings-host.d.ts +26 -0
  22. package/dist/admin/bookings-host.d.ts.map +1 -0
  23. package/dist/admin/bookings-host.js +18 -0
  24. package/dist/admin/bookings-list-skeleton.d.ts +10 -0
  25. package/dist/admin/bookings-list-skeleton.d.ts.map +1 -0
  26. package/dist/admin/bookings-list-skeleton.js +25 -0
  27. package/dist/admin/index.d.ts +273 -0
  28. package/dist/admin/index.d.ts.map +1 -0
  29. package/dist/admin/index.js +331 -0
  30. package/dist/admin/journey-billing-duplicate-warning.d.ts +3 -0
  31. package/dist/admin/journey-billing-duplicate-warning.d.ts.map +1 -0
  32. package/dist/admin/journey-billing-duplicate-warning.js +26 -0
  33. package/dist/admin/journey-departure-picker.d.ts +7 -0
  34. package/dist/admin/journey-departure-picker.d.ts.map +1 -0
  35. package/dist/admin/journey-departure-picker.js +100 -0
  36. package/dist/admin/journey-units-picker.d.ts +11 -0
  37. package/dist/admin/journey-units-picker.d.ts.map +1 -0
  38. package/dist/admin/journey-units-picker.js +60 -0
  39. package/dist/admin/journey-voucher-picker.d.ts +3 -0
  40. package/dist/admin/journey-voucher-picker.d.ts.map +1 -0
  41. package/dist/admin/journey-voucher-picker.js +71 -0
  42. package/dist/admin/pages/booking-compose-page.d.ts +9 -0
  43. package/dist/admin/pages/booking-compose-page.d.ts.map +1 -0
  44. package/dist/admin/pages/booking-compose-page.js +17 -0
  45. package/dist/admin/pages/booking-detail-page.d.ts +11 -0
  46. package/dist/admin/pages/booking-detail-page.d.ts.map +1 -0
  47. package/dist/admin/pages/booking-detail-page.js +14 -0
  48. package/dist/admin/pages/booking-journey-page.d.ts +12 -0
  49. package/dist/admin/pages/booking-journey-page.d.ts.map +1 -0
  50. package/dist/admin/pages/booking-journey-page.js +26 -0
  51. package/dist/admin/pages/booking-new-page.d.ts +15 -0
  52. package/dist/admin/pages/booking-new-page.d.ts.map +1 -0
  53. package/dist/admin/pages/booking-new-page.js +50 -0
  54. package/dist/admin/pages/bookings-index-page.d.ts +20 -0
  55. package/dist/admin/pages/bookings-index-page.d.ts.map +1 -0
  56. package/dist/admin/pages/bookings-index-page.js +18 -0
  57. package/dist/admin/person-bookings-widget.d.ts +13 -0
  58. package/dist/admin/person-bookings-widget.d.ts.map +1 -0
  59. package/dist/admin/person-bookings-widget.js +48 -0
  60. package/dist/admin/slots.d.ts +31 -0
  61. package/dist/admin/slots.d.ts.map +1 -0
  62. package/dist/admin/slots.js +30 -0
  63. package/dist/admin/use-booking-action-ledger-events.d.ts +15 -0
  64. package/dist/admin/use-booking-action-ledger-events.d.ts.map +1 -0
  65. package/dist/admin/use-booking-action-ledger-events.js +66 -0
  66. package/dist/client.d.ts +14 -0
  67. package/dist/client.d.ts.map +1 -0
  68. package/dist/client.js +59 -0
  69. package/dist/components/booking-activity-timeline.d.ts +32 -0
  70. package/dist/components/booking-activity-timeline.d.ts.map +1 -0
  71. package/dist/components/booking-activity-timeline.js +147 -0
  72. package/dist/components/booking-billing-dialog.d.ts +16 -0
  73. package/dist/components/booking-billing-dialog.d.ts.map +1 -0
  74. package/dist/components/booking-billing-dialog.js +315 -0
  75. package/dist/components/booking-cancellation-dialog.d.ts +18 -0
  76. package/dist/components/booking-cancellation-dialog.d.ts.map +1 -0
  77. package/dist/components/booking-cancellation-dialog.js +79 -0
  78. package/dist/components/booking-combobox.d.ts +13 -0
  79. package/dist/components/booking-combobox.d.ts.map +1 -0
  80. package/dist/components/booking-combobox.js +44 -0
  81. package/dist/components/booking-create-form-utils.d.ts +56 -0
  82. package/dist/components/booking-create-form-utils.d.ts.map +1 -0
  83. package/dist/components/booking-create-form-utils.js +216 -0
  84. package/dist/components/booking-create-page.d.ts +14 -0
  85. package/dist/components/booking-create-page.d.ts.map +1 -0
  86. package/dist/components/booking-create-page.js +11 -0
  87. package/dist/components/booking-create-preview-card.d.ts +26 -0
  88. package/dist/components/booking-create-preview-card.d.ts.map +1 -0
  89. package/dist/components/booking-create-preview-card.js +107 -0
  90. package/dist/components/booking-create-product-extras-picker.d.ts +18 -0
  91. package/dist/components/booking-create-product-extras-picker.d.ts.map +1 -0
  92. package/dist/components/booking-create-product-extras-picker.js +82 -0
  93. package/dist/components/booking-create-sheet.d.ts +34 -0
  94. package/dist/components/booking-create-sheet.d.ts.map +1 -0
  95. package/dist/components/booking-create-sheet.js +811 -0
  96. package/dist/components/booking-create-utils.d.ts +66 -0
  97. package/dist/components/booking-create-utils.d.ts.map +1 -0
  98. package/dist/components/booking-create-utils.js +185 -0
  99. package/dist/components/booking-detail-page.d.ts +126 -0
  100. package/dist/components/booking-detail-page.d.ts.map +1 -0
  101. package/dist/components/booking-detail-page.js +264 -0
  102. package/dist/components/booking-dialog.d.ts +28 -0
  103. package/dist/components/booking-dialog.d.ts.map +1 -0
  104. package/dist/components/booking-dialog.js +130 -0
  105. package/dist/components/booking-document-dialog.d.ts +8 -0
  106. package/dist/components/booking-document-dialog.d.ts.map +1 -0
  107. package/dist/components/booking-document-dialog.js +83 -0
  108. package/dist/components/booking-document-list.d.ts +5 -0
  109. package/dist/components/booking-document-list.d.ts.map +1 -0
  110. package/dist/components/booking-document-list.js +43 -0
  111. package/dist/components/booking-group-link-dialog.d.ts +10 -0
  112. package/dist/components/booking-group-link-dialog.d.ts.map +1 -0
  113. package/dist/components/booking-group-link-dialog.js +79 -0
  114. package/dist/components/booking-group-section.d.ts +27 -0
  115. package/dist/components/booking-group-section.d.ts.map +1 -0
  116. package/dist/components/booking-group-section.js +51 -0
  117. package/dist/components/booking-guarantee-dialog.d.ts +10 -0
  118. package/dist/components/booking-guarantee-dialog.d.ts.map +1 -0
  119. package/dist/components/booking-guarantee-dialog.js +123 -0
  120. package/dist/components/booking-guarantee-list.d.ts +5 -0
  121. package/dist/components/booking-guarantee-list.d.ts.map +1 -0
  122. package/dist/components/booking-guarantee-list.js +86 -0
  123. package/dist/components/booking-item-dialog.d.ts +10 -0
  124. package/dist/components/booking-item-dialog.d.ts.map +1 -0
  125. package/dist/components/booking-item-dialog.js +155 -0
  126. package/dist/components/booking-item-list.d.ts +12 -0
  127. package/dist/components/booking-item-list.d.ts.map +1 -0
  128. package/dist/components/booking-item-list.js +191 -0
  129. package/dist/components/booking-item-travelers.d.ts +6 -0
  130. package/dist/components/booking-item-travelers.d.ts.map +1 -0
  131. package/dist/components/booking-item-travelers.js +57 -0
  132. package/dist/components/booking-list-filters.d.ts +43 -0
  133. package/dist/components/booking-list-filters.d.ts.map +1 -0
  134. package/dist/components/booking-list-filters.js +192 -0
  135. package/dist/components/booking-list.d.ts +50 -0
  136. package/dist/components/booking-list.d.ts.map +1 -0
  137. package/dist/components/booking-list.js +352 -0
  138. package/dist/components/booking-note-dialog.d.ts +16 -0
  139. package/dist/components/booking-note-dialog.d.ts.map +1 -0
  140. package/dist/components/booking-note-dialog.js +41 -0
  141. package/dist/components/booking-notes.d.ts +5 -0
  142. package/dist/components/booking-notes.d.ts.map +1 -0
  143. package/dist/components/booking-notes.js +45 -0
  144. package/dist/components/booking-payment-reconciliation-banner.d.ts +5 -0
  145. package/dist/components/booking-payment-reconciliation-banner.d.ts.map +1 -0
  146. package/dist/components/booking-payment-reconciliation-banner.js +91 -0
  147. package/dist/components/booking-payment-schedule-dialog.d.ts +10 -0
  148. package/dist/components/booking-payment-schedule-dialog.d.ts.map +1 -0
  149. package/dist/components/booking-payment-schedule-dialog.js +117 -0
  150. package/dist/components/booking-payment-schedule-list.d.ts +10 -0
  151. package/dist/components/booking-payment-schedule-list.d.ts.map +1 -0
  152. package/dist/components/booking-payment-schedule-list.js +217 -0
  153. package/dist/components/booking-payments-summary.d.ts +83 -0
  154. package/dist/components/booking-payments-summary.d.ts.map +1 -0
  155. package/dist/components/booking-payments-summary.js +176 -0
  156. package/dist/components/booking-quick-view-sheet.d.ts +14 -0
  157. package/dist/components/booking-quick-view-sheet.d.ts.map +1 -0
  158. package/dist/components/booking-quick-view-sheet.js +283 -0
  159. package/dist/components/bookings-page.d.ts +19 -0
  160. package/dist/components/bookings-page.d.ts.map +1 -0
  161. package/dist/components/bookings-page.js +9 -0
  162. package/dist/components/file-dropzone.d.ts +25 -0
  163. package/dist/components/file-dropzone.d.ts.map +1 -0
  164. package/dist/components/file-dropzone.js +102 -0
  165. package/dist/components/icon-action-button.d.ts +18 -0
  166. package/dist/components/icon-action-button.d.ts.map +1 -0
  167. package/dist/components/icon-action-button.js +13 -0
  168. package/dist/components/option-units-stepper-section.d.ts +111 -0
  169. package/dist/components/option-units-stepper-section.d.ts.map +1 -0
  170. package/dist/components/option-units-stepper-section.js +276 -0
  171. package/dist/components/payment-schedule-section.d.ts +91 -0
  172. package/dist/components/payment-schedule-section.d.ts.map +1 -0
  173. package/dist/components/payment-schedule-section.js +206 -0
  174. package/dist/components/person-picker-section.d.ts +71 -0
  175. package/dist/components/person-picker-section.d.ts.map +1 -0
  176. package/dist/components/person-picker-section.js +160 -0
  177. package/dist/components/price-breakdown-section.d.ts +83 -0
  178. package/dist/components/price-breakdown-section.d.ts.map +1 -0
  179. package/dist/components/price-breakdown-section.js +278 -0
  180. package/dist/components/product-picker-section.d.ts +29 -0
  181. package/dist/components/product-picker-section.d.ts.map +1 -0
  182. package/dist/components/product-picker-section.js +74 -0
  183. package/dist/components/shared-room-section.d.ts +40 -0
  184. package/dist/components/shared-room-section.d.ts.map +1 -0
  185. package/dist/components/shared-room-section.js +99 -0
  186. package/dist/components/status-badge.d.ts +24 -0
  187. package/dist/components/status-badge.d.ts.map +1 -0
  188. package/dist/components/status-badge.js +65 -0
  189. package/dist/components/status-change-dialog.d.ts +10 -0
  190. package/dist/components/status-change-dialog.d.ts.map +1 -0
  191. package/dist/components/status-change-dialog.js +57 -0
  192. package/dist/components/supplier-status-dialog.d.ts +10 -0
  193. package/dist/components/supplier-status-dialog.d.ts.map +1 -0
  194. package/dist/components/supplier-status-dialog.js +98 -0
  195. package/dist/components/supplier-status-list.d.ts +5 -0
  196. package/dist/components/supplier-status-list.d.ts.map +1 -0
  197. package/dist/components/supplier-status-list.js +115 -0
  198. package/dist/components/traveler-category-buttons.d.ts +26 -0
  199. package/dist/components/traveler-category-buttons.d.ts.map +1 -0
  200. package/dist/components/traveler-category-buttons.js +35 -0
  201. package/dist/components/traveler-dialog.d.ts +10 -0
  202. package/dist/components/traveler-dialog.d.ts.map +1 -0
  203. package/dist/components/traveler-dialog.js +256 -0
  204. package/dist/components/traveler-list.d.ts +6 -0
  205. package/dist/components/traveler-list.d.ts.map +1 -0
  206. package/dist/components/traveler-list.js +295 -0
  207. package/dist/components/travelers-section-controls.d.ts +52 -0
  208. package/dist/components/travelers-section-controls.d.ts.map +1 -0
  209. package/dist/components/travelers-section-controls.js +206 -0
  210. package/dist/components/travelers-section.d.ts +159 -0
  211. package/dist/components/travelers-section.d.ts.map +1 -0
  212. package/dist/components/travelers-section.js +355 -0
  213. package/dist/components/voucher-picker-section.d.ts +50 -0
  214. package/dist/components/voucher-picker-section.d.ts.map +1 -0
  215. package/dist/components/voucher-picker-section.js +79 -0
  216. package/dist/extras/client.d.ts +14 -0
  217. package/dist/extras/client.d.ts.map +1 -0
  218. package/dist/extras/client.js +58 -0
  219. package/dist/extras/components/extra-catalog-card.d.ts +13 -0
  220. package/dist/extras/components/extra-catalog-card.d.ts.map +1 -0
  221. package/dist/extras/components/extra-catalog-card.js +52 -0
  222. package/dist/extras/components/product-combobox.d.ts +9 -0
  223. package/dist/extras/components/product-combobox.d.ts.map +1 -0
  224. package/dist/extras/components/product-combobox.js +46 -0
  225. package/dist/extras/components/slot-extras-manifest-panel.d.ts +6 -0
  226. package/dist/extras/components/slot-extras-manifest-panel.d.ts.map +1 -0
  227. package/dist/extras/components/slot-extras-manifest-panel.js +108 -0
  228. package/dist/extras/hooks/index.d.ts +5 -0
  229. package/dist/extras/hooks/index.d.ts.map +1 -0
  230. package/dist/extras/hooks/index.js +4 -0
  231. package/dist/extras/hooks/use-product-extra.d.ts +24 -0
  232. package/dist/extras/hooks/use-product-extra.d.ts.map +1 -0
  233. package/dist/extras/hooks/use-product-extra.js +12 -0
  234. package/dist/extras/hooks/use-product-extras.d.ts +30 -0
  235. package/dist/extras/hooks/use-product-extras.d.ts.map +1 -0
  236. package/dist/extras/hooks/use-product-extras.js +12 -0
  237. package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts +48 -0
  238. package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts.map +1 -0
  239. package/dist/extras/hooks/use-slot-extra-manifest-mutation.js +26 -0
  240. package/dist/extras/hooks/use-slot-extra-manifest.d.ts +68 -0
  241. package/dist/extras/hooks/use-slot-extra-manifest.d.ts.map +1 -0
  242. package/dist/extras/hooks/use-slot-extra-manifest.js +11 -0
  243. package/dist/extras/i18n/en.d.ts +52 -0
  244. package/dist/extras/i18n/en.d.ts.map +1 -0
  245. package/dist/extras/i18n/en.js +51 -0
  246. package/dist/extras/i18n/index.d.ts +5 -0
  247. package/dist/extras/i18n/index.d.ts.map +1 -0
  248. package/dist/extras/i18n/index.js +3 -0
  249. package/dist/extras/i18n/messages.d.ts +37 -0
  250. package/dist/extras/i18n/messages.d.ts.map +1 -0
  251. package/dist/extras/i18n/messages.js +1 -0
  252. package/dist/extras/i18n/provider.d.ts +126 -0
  253. package/dist/extras/i18n/provider.d.ts.map +1 -0
  254. package/dist/extras/i18n/provider.js +44 -0
  255. package/dist/extras/i18n/ro.d.ts +52 -0
  256. package/dist/extras/i18n/ro.d.ts.map +1 -0
  257. package/dist/extras/i18n/ro.js +51 -0
  258. package/dist/extras/index.d.ts +7 -0
  259. package/dist/extras/index.d.ts.map +1 -0
  260. package/dist/extras/index.js +6 -0
  261. package/dist/extras/provider.d.ts +2 -0
  262. package/dist/extras/provider.d.ts.map +1 -0
  263. package/dist/extras/provider.js +1 -0
  264. package/dist/extras/query-keys.d.ts +16 -0
  265. package/dist/extras/query-keys.d.ts.map +1 -0
  266. package/dist/extras/query-keys.js +8 -0
  267. package/dist/extras/query-options.d.ts +455 -0
  268. package/dist/extras/query-options.d.ts.map +1 -0
  269. package/dist/extras/query-options.js +44 -0
  270. package/dist/extras/schemas.d.ts +416 -0
  271. package/dist/extras/schemas.d.ts.map +1 -0
  272. package/dist/extras/schemas.js +89 -0
  273. package/dist/extras/ui.d.ts +4 -0
  274. package/dist/extras/ui.d.ts.map +1 -0
  275. package/dist/extras/ui.js +3 -0
  276. package/dist/extras.d.ts +10 -0
  277. package/dist/extras.d.ts.map +1 -0
  278. package/dist/extras.js +9 -0
  279. package/dist/hooks/index.d.ts +36 -0
  280. package/dist/hooks/index.d.ts.map +1 -0
  281. package/dist/hooks/index.js +35 -0
  282. package/dist/hooks/use-booking-action-ledger.d.ts +63 -0
  283. package/dist/hooks/use-booking-action-ledger.d.ts.map +1 -0
  284. package/dist/hooks/use-booking-action-ledger.js +34 -0
  285. package/dist/hooks/use-booking-activity.d.ts +17 -0
  286. package/dist/hooks/use-booking-activity.d.ts.map +1 -0
  287. package/dist/hooks/use-booking-activity.js +12 -0
  288. package/dist/hooks/use-booking-cancel-mutation.d.ts +69 -0
  289. package/dist/hooks/use-booking-cancel-mutation.d.ts.map +1 -0
  290. package/dist/hooks/use-booking-cancel-mutation.js +24 -0
  291. package/dist/hooks/use-booking-contract-generation.d.ts +31 -0
  292. package/dist/hooks/use-booking-contract-generation.d.ts.map +1 -0
  293. package/dist/hooks/use-booking-contract-generation.js +36 -0
  294. package/dist/hooks/use-booking-convert-mutation.d.ts +81 -0
  295. package/dist/hooks/use-booking-convert-mutation.d.ts.map +1 -0
  296. package/dist/hooks/use-booking-convert-mutation.js +24 -0
  297. package/dist/hooks/use-booking-create-mutation.d.ts +337 -0
  298. package/dist/hooks/use-booking-create-mutation.d.ts.map +1 -0
  299. package/dist/hooks/use-booking-create-mutation.js +43 -0
  300. package/dist/hooks/use-booking-documents.d.ts +41 -0
  301. package/dist/hooks/use-booking-documents.d.ts.map +1 -0
  302. package/dist/hooks/use-booking-documents.js +46 -0
  303. package/dist/hooks/use-booking-dual-create-mutation.d.ts +338 -0
  304. package/dist/hooks/use-booking-dual-create-mutation.d.ts.map +1 -0
  305. package/dist/hooks/use-booking-dual-create-mutation.js +45 -0
  306. package/dist/hooks/use-booking-group-for-booking.d.ts +24 -0
  307. package/dist/hooks/use-booking-group-for-booking.d.ts.map +1 -0
  308. package/dist/hooks/use-booking-group-for-booking.js +12 -0
  309. package/dist/hooks/use-booking-group-member-mutation.d.ts +27 -0
  310. package/dist/hooks/use-booking-group-member-mutation.d.ts.map +1 -0
  311. package/dist/hooks/use-booking-group-member-mutation.js +38 -0
  312. package/dist/hooks/use-booking-group-mutation.d.ts +40 -0
  313. package/dist/hooks/use-booking-group-mutation.d.ts.map +1 -0
  314. package/dist/hooks/use-booking-group-mutation.js +32 -0
  315. package/dist/hooks/use-booking-group.d.ts +85 -0
  316. package/dist/hooks/use-booking-group.d.ts.map +1 -0
  317. package/dist/hooks/use-booking-group.js +12 -0
  318. package/dist/hooks/use-booking-groups.d.ts +21 -0
  319. package/dist/hooks/use-booking-groups.d.ts.map +1 -0
  320. package/dist/hooks/use-booking-groups.js +12 -0
  321. package/dist/hooks/use-booking-item-mutation.d.ts +101 -0
  322. package/dist/hooks/use-booking-item-mutation.d.ts.map +1 -0
  323. package/dist/hooks/use-booking-item-mutation.js +42 -0
  324. package/dist/hooks/use-booking-item-travelers.d.ts +32 -0
  325. package/dist/hooks/use-booking-item-travelers.d.ts.map +1 -0
  326. package/dist/hooks/use-booking-item-travelers.js +48 -0
  327. package/dist/hooks/use-booking-items.d.ts +36 -0
  328. package/dist/hooks/use-booking-items.d.ts.map +1 -0
  329. package/dist/hooks/use-booking-items.js +12 -0
  330. package/dist/hooks/use-booking-mutation.d.ts +158 -0
  331. package/dist/hooks/use-booking-mutation.d.ts.map +1 -0
  332. package/dist/hooks/use-booking-mutation.js +39 -0
  333. package/dist/hooks/use-booking-note-mutation.d.ts +39 -0
  334. package/dist/hooks/use-booking-note-mutation.d.ts.map +1 -0
  335. package/dist/hooks/use-booking-note-mutation.js +44 -0
  336. package/dist/hooks/use-booking-notes.d.ts +15 -0
  337. package/dist/hooks/use-booking-notes.d.ts.map +1 -0
  338. package/dist/hooks/use-booking-notes.js +12 -0
  339. package/dist/hooks/use-booking-primary-product.d.ts +28 -0
  340. package/dist/hooks/use-booking-primary-product.d.ts.map +1 -0
  341. package/dist/hooks/use-booking-primary-product.js +20 -0
  342. package/dist/hooks/use-booking-status-mutation.d.ts +156 -0
  343. package/dist/hooks/use-booking-status-mutation.d.ts.map +1 -0
  344. package/dist/hooks/use-booking-status-mutation.js +54 -0
  345. package/dist/hooks/use-booking-tax-preview.d.ts +29 -0
  346. package/dist/hooks/use-booking-tax-preview.d.ts.map +1 -0
  347. package/dist/hooks/use-booking-tax-preview.js +21 -0
  348. package/dist/hooks/use-booking.d.ts +67 -0
  349. package/dist/hooks/use-booking.d.ts.map +1 -0
  350. package/dist/hooks/use-booking.js +12 -0
  351. package/dist/hooks/use-bookings.d.ts +71 -0
  352. package/dist/hooks/use-bookings.d.ts.map +1 -0
  353. package/dist/hooks/use-bookings.js +12 -0
  354. package/dist/hooks/use-pricing-preview.d.ts +61 -0
  355. package/dist/hooks/use-pricing-preview.d.ts.map +1 -0
  356. package/dist/hooks/use-pricing-preview.js +18 -0
  357. package/dist/hooks/use-public-booking-session-flow-mutation.d.ts +148 -0
  358. package/dist/hooks/use-public-booking-session-flow-mutation.d.ts.map +1 -0
  359. package/dist/hooks/use-public-booking-session-flow-mutation.js +35 -0
  360. package/dist/hooks/use-public-booking-session-state.d.ts +16 -0
  361. package/dist/hooks/use-public-booking-session-state.d.ts.map +1 -0
  362. package/dist/hooks/use-public-booking-session-state.js +12 -0
  363. package/dist/hooks/use-public-booking-session.d.ts +101 -0
  364. package/dist/hooks/use-public-booking-session.d.ts.map +1 -0
  365. package/dist/hooks/use-public-booking-session.js +12 -0
  366. package/dist/hooks/use-reveal-traveler.d.ts +54 -0
  367. package/dist/hooks/use-reveal-traveler.d.ts.map +1 -0
  368. package/dist/hooks/use-reveal-traveler.js +18 -0
  369. package/dist/hooks/use-sharing-groups.d.ts +41 -0
  370. package/dist/hooks/use-sharing-groups.d.ts.map +1 -0
  371. package/dist/hooks/use-sharing-groups.js +20 -0
  372. package/dist/hooks/use-supplier-status-mutation.d.ts +46 -0
  373. package/dist/hooks/use-supplier-status-mutation.d.ts.map +1 -0
  374. package/dist/hooks/use-supplier-status-mutation.js +39 -0
  375. package/dist/hooks/use-supplier-statuses.d.ts +20 -0
  376. package/dist/hooks/use-supplier-statuses.d.ts.map +1 -0
  377. package/dist/hooks/use-supplier-statuses.js +12 -0
  378. package/dist/hooks/use-traveler-mutation.d.ts +55 -0
  379. package/dist/hooks/use-traveler-mutation.d.ts.map +1 -0
  380. package/dist/hooks/use-traveler-mutation.js +42 -0
  381. package/dist/hooks/use-traveler-with-travel-details-mutation.d.ts +120 -0
  382. package/dist/hooks/use-traveler-with-travel-details-mutation.d.ts.map +1 -0
  383. package/dist/hooks/use-traveler-with-travel-details-mutation.js +43 -0
  384. package/dist/hooks/use-travelers.d.ts +23 -0
  385. package/dist/hooks/use-travelers.d.ts.map +1 -0
  386. package/dist/hooks/use-travelers.js +12 -0
  387. package/dist/i18n/en-base.d.ts +295 -0
  388. package/dist/i18n/en-base.d.ts.map +1 -0
  389. package/dist/i18n/en-base.js +294 -0
  390. package/dist/i18n/en-create-list.d.ts +327 -0
  391. package/dist/i18n/en-create-list.d.ts.map +1 -0
  392. package/dist/i18n/en-create-list.js +326 -0
  393. package/dist/i18n/en-journey.d.ts +229 -0
  394. package/dist/i18n/en-journey.d.ts.map +1 -0
  395. package/dist/i18n/en-journey.js +228 -0
  396. package/dist/i18n/en-operations.d.ts +382 -0
  397. package/dist/i18n/en-operations.d.ts.map +1 -0
  398. package/dist/i18n/en-operations.js +381 -0
  399. package/dist/i18n/en-sections.d.ts +360 -0
  400. package/dist/i18n/en-sections.d.ts.map +1 -0
  401. package/dist/i18n/en-sections.js +359 -0
  402. package/dist/i18n/en.d.ts +1581 -0
  403. package/dist/i18n/en.d.ts.map +1 -0
  404. package/dist/i18n/en.js +12 -0
  405. package/dist/i18n/index.d.ts +5 -0
  406. package/dist/i18n/index.d.ts.map +1 -0
  407. package/dist/i18n/index.js +3 -0
  408. package/dist/i18n/messages-base.d.ts +251 -0
  409. package/dist/i18n/messages-base.d.ts.map +1 -0
  410. package/dist/i18n/messages-base.js +1 -0
  411. package/dist/i18n/messages-create-list.d.ts +310 -0
  412. package/dist/i18n/messages-create-list.d.ts.map +1 -0
  413. package/dist/i18n/messages-create-list.js +1 -0
  414. package/dist/i18n/messages-journey.d.ts +198 -0
  415. package/dist/i18n/messages-journey.d.ts.map +1 -0
  416. package/dist/i18n/messages-journey.js +1 -0
  417. package/dist/i18n/messages-operations.d.ts +362 -0
  418. package/dist/i18n/messages-operations.d.ts.map +1 -0
  419. package/dist/i18n/messages-operations.js +1 -0
  420. package/dist/i18n/messages-sections.d.ts +312 -0
  421. package/dist/i18n/messages-sections.d.ts.map +1 -0
  422. package/dist/i18n/messages-sections.js +1 -0
  423. package/dist/i18n/messages.d.ts +7 -0
  424. package/dist/i18n/messages.d.ts.map +1 -0
  425. package/dist/i18n/messages.js +1 -0
  426. package/dist/i18n/provider.d.ts +3185 -0
  427. package/dist/i18n/provider.d.ts.map +1 -0
  428. package/dist/i18n/provider.js +45 -0
  429. package/dist/i18n/ro-base.d.ts +295 -0
  430. package/dist/i18n/ro-base.d.ts.map +1 -0
  431. package/dist/i18n/ro-base.js +294 -0
  432. package/dist/i18n/ro-create-list.d.ts +327 -0
  433. package/dist/i18n/ro-create-list.d.ts.map +1 -0
  434. package/dist/i18n/ro-create-list.js +326 -0
  435. package/dist/i18n/ro-journey.d.ts +229 -0
  436. package/dist/i18n/ro-journey.d.ts.map +1 -0
  437. package/dist/i18n/ro-journey.js +228 -0
  438. package/dist/i18n/ro-operations.d.ts +382 -0
  439. package/dist/i18n/ro-operations.d.ts.map +1 -0
  440. package/dist/i18n/ro-operations.js +381 -0
  441. package/dist/i18n/ro-sections.d.ts +360 -0
  442. package/dist/i18n/ro-sections.d.ts.map +1 -0
  443. package/dist/i18n/ro-sections.js +359 -0
  444. package/dist/i18n/ro.d.ts +1581 -0
  445. package/dist/i18n/ro.d.ts.map +1 -0
  446. package/dist/i18n/ro.js +12 -0
  447. package/dist/index.d.ts +9 -0
  448. package/dist/index.d.ts.map +1 -0
  449. package/dist/index.js +8 -0
  450. package/dist/journey/components/booking-journey-rules.d.ts +48 -0
  451. package/dist/journey/components/booking-journey-rules.d.ts.map +1 -0
  452. package/dist/journey/components/booking-journey-rules.js +235 -0
  453. package/dist/journey/components/booking-journey.d.ts +3 -0
  454. package/dist/journey/components/booking-journey.d.ts.map +1 -0
  455. package/dist/journey/components/booking-journey.js +368 -0
  456. package/dist/journey/components/configure-step-skeleton.d.ts +8 -0
  457. package/dist/journey/components/configure-step-skeleton.d.ts.map +1 -0
  458. package/dist/journey/components/configure-step-skeleton.js +11 -0
  459. package/dist/journey/components/contract-preview-dialog.d.ts +47 -0
  460. package/dist/journey/components/contract-preview-dialog.d.ts.map +1 -0
  461. package/dist/journey/components/contract-preview-dialog.js +124 -0
  462. package/dist/journey/components/journey-steps/accommodation-step.d.ts +3 -0
  463. package/dist/journey/components/journey-steps/accommodation-step.d.ts.map +1 -0
  464. package/dist/journey/components/journey-steps/accommodation-step.js +71 -0
  465. package/dist/journey/components/journey-steps/addons-step.d.ts +3 -0
  466. package/dist/journey/components/journey-steps/addons-step.d.ts.map +1 -0
  467. package/dist/journey/components/journey-steps/addons-step.js +40 -0
  468. package/dist/journey/components/journey-steps/billing-step.d.ts +8 -0
  469. package/dist/journey/components/journey-steps/billing-step.d.ts.map +1 -0
  470. package/dist/journey/components/journey-steps/billing-step.js +78 -0
  471. package/dist/journey/components/journey-steps/configure-steps.d.ts +28 -0
  472. package/dist/journey/components/journey-steps/configure-steps.d.ts.map +1 -0
  473. package/dist/journey/components/journey-steps/configure-steps.js +232 -0
  474. package/dist/journey/components/journey-steps/documents-step.d.ts +11 -0
  475. package/dist/journey/components/journey-steps/documents-step.d.ts.map +1 -0
  476. package/dist/journey/components/journey-steps/documents-step.js +36 -0
  477. package/dist/journey/components/journey-steps/payment-step.d.ts +29 -0
  478. package/dist/journey/components/journey-steps/payment-step.d.ts.map +1 -0
  479. package/dist/journey/components/journey-steps/payment-step.js +225 -0
  480. package/dist/journey/components/journey-steps/review-step.d.ts +27 -0
  481. package/dist/journey/components/journey-steps/review-step.d.ts.map +1 -0
  482. package/dist/journey/components/journey-steps/review-step.js +18 -0
  483. package/dist/journey/components/journey-steps/shared.d.ts +75 -0
  484. package/dist/journey/components/journey-steps/shared.d.ts.map +1 -0
  485. package/dist/journey/components/journey-steps/shared.js +108 -0
  486. package/dist/journey/components/journey-steps/travelers-step.d.ts +7 -0
  487. package/dist/journey/components/journey-steps/travelers-step.d.ts.map +1 -0
  488. package/dist/journey/components/journey-steps/travelers-step.js +201 -0
  489. package/dist/journey/components/journey-steps.d.ts +21 -0
  490. package/dist/journey/components/journey-steps.d.ts.map +1 -0
  491. package/dist/journey/components/journey-steps.js +20 -0
  492. package/dist/journey/components/side-panel.d.ts +17 -0
  493. package/dist/journey/components/side-panel.d.ts.map +1 -0
  494. package/dist/journey/components/side-panel.js +245 -0
  495. package/dist/journey/components/stacked-journey.d.ts +30 -0
  496. package/dist/journey/components/stacked-journey.d.ts.map +1 -0
  497. package/dist/journey/components/stacked-journey.js +50 -0
  498. package/dist/journey/components/step-header.d.ts +7 -0
  499. package/dist/journey/components/step-header.d.ts.map +1 -0
  500. package/dist/journey/components/step-header.js +12 -0
  501. package/dist/journey/index.d.ts +18 -0
  502. package/dist/journey/index.d.ts.map +1 -0
  503. package/dist/journey/index.js +17 -0
  504. package/dist/journey/lib/draft-state.d.ts +35 -0
  505. package/dist/journey/lib/draft-state.d.ts.map +1 -0
  506. package/dist/journey/lib/draft-state.js +57 -0
  507. package/dist/journey/lib/pax-band-dependencies.d.ts +27 -0
  508. package/dist/journey/lib/pax-band-dependencies.d.ts.map +1 -0
  509. package/dist/journey/lib/pax-band-dependencies.js +50 -0
  510. package/dist/journey/lib/payment-schedule.d.ts +19 -0
  511. package/dist/journey/lib/payment-schedule.d.ts.map +1 -0
  512. package/dist/journey/lib/payment-schedule.js +90 -0
  513. package/dist/journey/types.d.ts +403 -0
  514. package/dist/journey/types.d.ts.map +1 -0
  515. package/dist/journey/types.js +19 -0
  516. package/dist/provider.d.ts +2 -0
  517. package/dist/provider.d.ts.map +1 -0
  518. package/dist/provider.js +1 -0
  519. package/dist/query-keys.d.ts +74 -0
  520. package/dist/query-keys.d.ts.map +1 -0
  521. package/dist/query-keys.js +26 -0
  522. package/dist/query-options.d.ts +2534 -0
  523. package/dist/query-options.d.ts.map +1 -0
  524. package/dist/query-options.js +233 -0
  525. package/dist/requirements/client.d.ts +14 -0
  526. package/dist/requirements/client.d.ts.map +1 -0
  527. package/dist/requirements/client.js +59 -0
  528. package/dist/requirements/components/booking-requirements-contact-tab.d.ts +8 -0
  529. package/dist/requirements/components/booking-requirements-contact-tab.d.ts.map +1 -0
  530. package/dist/requirements/components/booking-requirements-contact-tab.js +8 -0
  531. package/dist/requirements/components/booking-requirements-questions-tab.d.ts +14 -0
  532. package/dist/requirements/components/booking-requirements-questions-tab.d.ts.map +1 -0
  533. package/dist/requirements/components/booking-requirements-questions-tab.js +17 -0
  534. package/dist/requirements/constants.d.ts +114 -0
  535. package/dist/requirements/constants.d.ts.map +1 -0
  536. package/dist/requirements/constants.js +45 -0
  537. package/dist/requirements/hooks/index.d.ts +6 -0
  538. package/dist/requirements/hooks/index.d.ts.map +1 -0
  539. package/dist/requirements/hooks/index.js +6 -0
  540. package/dist/requirements/hooks/use-booking-questions.d.ts +24 -0
  541. package/dist/requirements/hooks/use-booking-questions.d.ts.map +1 -0
  542. package/dist/requirements/hooks/use-booking-questions.js +9 -0
  543. package/dist/requirements/hooks/use-contact-requirements.d.ts +22 -0
  544. package/dist/requirements/hooks/use-contact-requirements.d.ts.map +1 -0
  545. package/dist/requirements/hooks/use-contact-requirements.js +9 -0
  546. package/dist/requirements/hooks/use-products.d.ts +16 -0
  547. package/dist/requirements/hooks/use-products.d.ts.map +1 -0
  548. package/dist/requirements/hooks/use-products.js +9 -0
  549. package/dist/requirements/hooks/use-question-options.d.ts +19 -0
  550. package/dist/requirements/hooks/use-question-options.d.ts.map +1 -0
  551. package/dist/requirements/hooks/use-question-options.js +9 -0
  552. package/dist/requirements/hooks/use-transport-requirements.d.ts +30 -0
  553. package/dist/requirements/hooks/use-transport-requirements.d.ts.map +1 -0
  554. package/dist/requirements/hooks/use-transport-requirements.js +9 -0
  555. package/dist/requirements/i18n/en.d.ts +94 -0
  556. package/dist/requirements/i18n/en.d.ts.map +1 -0
  557. package/dist/requirements/i18n/en.js +93 -0
  558. package/dist/requirements/i18n/index.d.ts +5 -0
  559. package/dist/requirements/i18n/index.d.ts.map +1 -0
  560. package/dist/requirements/i18n/index.js +3 -0
  561. package/dist/requirements/i18n/messages.d.ts +59 -0
  562. package/dist/requirements/i18n/messages.d.ts.map +1 -0
  563. package/dist/requirements/i18n/messages.js +1 -0
  564. package/dist/requirements/i18n/provider.d.ts +210 -0
  565. package/dist/requirements/i18n/provider.d.ts.map +1 -0
  566. package/dist/requirements/i18n/provider.js +44 -0
  567. package/dist/requirements/i18n/ro.d.ts +94 -0
  568. package/dist/requirements/i18n/ro.d.ts.map +1 -0
  569. package/dist/requirements/i18n/ro.js +93 -0
  570. package/dist/requirements/index.d.ts +9 -0
  571. package/dist/requirements/index.d.ts.map +1 -0
  572. package/dist/requirements/index.js +8 -0
  573. package/dist/requirements/provider.d.ts +2 -0
  574. package/dist/requirements/provider.d.ts.map +1 -0
  575. package/dist/requirements/provider.js +1 -0
  576. package/dist/requirements/query-keys.d.ts +33 -0
  577. package/dist/requirements/query-keys.d.ts.map +1 -0
  578. package/dist/requirements/query-keys.js +13 -0
  579. package/dist/requirements/query-options.d.ts +371 -0
  580. package/dist/requirements/query-options.d.ts.map +1 -0
  581. package/dist/requirements/query-options.js +80 -0
  582. package/dist/requirements/schemas.d.ts +320 -0
  583. package/dist/requirements/schemas.d.ts.map +1 -0
  584. package/dist/requirements/schemas.js +121 -0
  585. package/dist/requirements/ui.d.ts +4 -0
  586. package/dist/requirements/ui.d.ts.map +1 -0
  587. package/dist/requirements/ui.js +3 -0
  588. package/dist/requirements/utils.d.ts +2 -0
  589. package/dist/requirements/utils.d.ts.map +1 -0
  590. package/dist/requirements/utils.js +4 -0
  591. package/dist/schemas.d.ts +2070 -0
  592. package/dist/schemas.d.ts.map +1 -0
  593. package/dist/schemas.js +507 -0
  594. package/dist/status-presentation.d.ts +34 -0
  595. package/dist/status-presentation.d.ts.map +1 -0
  596. package/dist/status-presentation.js +38 -0
  597. package/dist/ui.d.ts +43 -0
  598. package/dist/ui.d.ts.map +1 -0
  599. package/dist/ui.js +42 -0
  600. package/package.json +256 -0
  601. package/src/requirements/styles.css +1 -0
  602. package/src/styles.css +13 -0
@@ -0,0 +1,160 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useOrganization, useOrganizations, usePeople, usePerson, } from "@voyant-travel/relationships-react";
4
+ import { OrganizationForm, PersonForm } from "@voyant-travel/relationships-react/ui";
5
+ import { Button, Label, Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle, } from "@voyant-travel/ui/components";
6
+ import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyant-travel/ui/components/combobox";
7
+ import { Building2, Pencil, User, UserPlus } from "lucide-react";
8
+ import * as React from "react";
9
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
10
+ export const emptyNewPerson = {
11
+ firstName: "",
12
+ lastName: "",
13
+ email: "",
14
+ phone: "",
15
+ };
16
+ export const emptyPersonPickerValue = {
17
+ billTo: "person",
18
+ mode: "existing",
19
+ personId: "",
20
+ newPerson: emptyNewPerson,
21
+ organizationId: null,
22
+ };
23
+ /**
24
+ * Billing target picker for booking create.
25
+ *
26
+ * State is fully controlled. The embedded create sheets use the CRM forms and
27
+ * select the newly-created person or organization after save.
28
+ */
29
+ export function PersonPickerSection({ value, onChange, enabled = true, showOrganization = true, hideTargetToggle = false, labels, }) {
30
+ const [personSearch, setPersonSearch] = React.useState("");
31
+ const [orgSearch, setOrgSearch] = React.useState("");
32
+ const cachedPeopleRef = React.useRef(new Map());
33
+ const cachedOrgsRef = React.useRef(new Map());
34
+ const [personInputValue, setPersonInputValue] = React.useState("");
35
+ const [orgInputValue, setOrgInputValue] = React.useState("");
36
+ const [personSheetOpen, setPersonSheetOpen] = React.useState(false);
37
+ const [personSheetMode, setPersonSheetMode] = React.useState("create");
38
+ const [orgSheetOpen, setOrgSheetOpen] = React.useState(false);
39
+ const [orgSheetMode, setOrgSheetMode] = React.useState("create");
40
+ const messages = useBookingsUiMessagesOrDefault();
41
+ const merged = { ...messages.personPickerSection.labels, ...labels };
42
+ const billingTarget = value.billTo ?? "person";
43
+ const { data: peopleData } = usePeople({
44
+ search: personSearch || undefined,
45
+ limit: 20,
46
+ enabled: enabled && billingTarget === "person",
47
+ });
48
+ const selectedPersonQuery = usePerson(value.personId || undefined, {
49
+ enabled: enabled && billingTarget === "person" && Boolean(value.personId),
50
+ });
51
+ const people = React.useMemo(() => {
52
+ const map = new Map(cachedPeopleRef.current);
53
+ for (const person of peopleData?.data ?? [])
54
+ map.set(person.id, person);
55
+ if (selectedPersonQuery.data)
56
+ map.set(selectedPersonQuery.data.id, selectedPersonQuery.data);
57
+ cachedPeopleRef.current = map;
58
+ return Array.from(map.values());
59
+ }, [peopleData?.data, selectedPersonQuery.data]);
60
+ const peopleMap = React.useMemo(() => new Map(people.map((person) => [person.id, person])), [people]);
61
+ const { data: orgsData } = useOrganizations({
62
+ search: orgSearch || undefined,
63
+ limit: 20,
64
+ enabled: enabled && showOrganization && billingTarget === "organization",
65
+ });
66
+ const selectedOrgQuery = useOrganization(value.organizationId || undefined, {
67
+ enabled: enabled && billingTarget === "organization" && Boolean(value.organizationId),
68
+ });
69
+ const orgs = React.useMemo(() => {
70
+ const map = new Map(cachedOrgsRef.current);
71
+ for (const org of orgsData?.data ?? [])
72
+ map.set(org.id, org);
73
+ if (selectedOrgQuery.data)
74
+ map.set(selectedOrgQuery.data.id, selectedOrgQuery.data);
75
+ cachedOrgsRef.current = map;
76
+ return Array.from(map.values());
77
+ }, [orgsData?.data, selectedOrgQuery.data]);
78
+ const orgsMap = React.useMemo(() => new Map(orgs.map((org) => [org.id, org])), [orgs]);
79
+ const setPerson = (patch) => onChange({ ...value, ...patch });
80
+ const resolvePersonLabel = React.useCallback((personId) => formatPerson(peopleMap.get(personId) ?? cachedPeopleRef.current.get(personId)), [peopleMap]);
81
+ const resolveOrgLabel = React.useCallback((organizationId) => orgsMap.get(organizationId)?.name ?? cachedOrgsRef.current.get(organizationId)?.name ?? "", [orgsMap]);
82
+ const selectedPersonLabel = value.personId ? resolvePersonLabel(value.personId) : "";
83
+ const selectedOrgLabel = value.organizationId ? resolveOrgLabel(value.organizationId) : "";
84
+ React.useEffect(() => {
85
+ if (selectedPersonLabel)
86
+ setPersonInputValue(selectedPersonLabel);
87
+ }, [selectedPersonLabel]);
88
+ React.useEffect(() => {
89
+ if (selectedOrgLabel)
90
+ setOrgInputValue(selectedOrgLabel);
91
+ }, [selectedOrgLabel]);
92
+ return (_jsxs(_Fragment, { children: [showOrganization && !hideTargetToggle ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: merged.billTo }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs(Button, { type: "button", variant: billingTarget === "person" ? "default" : "outline", onClick: () => setPerson({ billTo: "person", organizationId: null }), disabled: !enabled, children: [_jsx(User, { className: "mr-2 h-4 w-4" }), merged.billToPerson] }), _jsxs(Button, { type: "button", variant: billingTarget === "organization" ? "default" : "outline", onClick: () => setPerson({ billTo: "organization", personId: "" }), disabled: !enabled, children: [_jsx(Building2, { className: "mr-2 h-4 w-4" }), merged.billToOrganization] })] })] })) : null, billingTarget === "person" ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { children: [merged.person, " ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsxs("div", { className: "flex items-center gap-1", children: [value.personId ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7", onClick: () => {
93
+ setPersonSheetMode("edit");
94
+ setPersonSheetOpen(true);
95
+ }, disabled: !enabled || !selectedPersonQuery.data, children: [_jsx(Pencil, { className: "mr-1 h-3.5 w-3.5" }), merged.editPerson] })) : null, _jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7", onClick: () => {
96
+ setPersonSheetMode("create");
97
+ setPersonSheetOpen(true);
98
+ }, disabled: !enabled, children: [_jsx(UserPlus, { className: "mr-1 h-3.5 w-3.5" }), merged.createNewPerson] })] })] }), _jsxs(Combobox, { items: people.map((person) => person.id), value: value.personId || null, inputValue: personInputValue, autoHighlight: true, disabled: !enabled, itemToStringLabel: (id) => resolvePersonLabel(id) || id, itemToStringValue: (id) => id, onInputValueChange: (next) => {
99
+ setPersonInputValue(next);
100
+ setPersonSearch(next);
101
+ if (!next)
102
+ setPerson({ personId: "" });
103
+ }, onValueChange: (next) => {
104
+ const personId = next ?? "";
105
+ setPerson({ personId });
106
+ setPersonInputValue(personId ? resolvePersonLabel(personId) : "");
107
+ }, children: [_jsx(ComboboxInput, { placeholder: merged.personSearchPlaceholder, showClear: !!value.personId }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: merged.personEmpty }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
108
+ const person = peopleMap.get(id);
109
+ if (!person)
110
+ return null;
111
+ return (_jsx(ComboboxItem, { value: person.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: formatPersonName(person) }), person.email ? (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: person.email })) : null] }) }, person.id));
112
+ } }) })] })] })] })) : (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { children: [merged.organization, " ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsxs("div", { className: "flex items-center gap-1", children: [value.organizationId ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7", onClick: () => {
113
+ setOrgSheetMode("edit");
114
+ setOrgSheetOpen(true);
115
+ }, disabled: !enabled || !selectedOrgQuery.data, children: [_jsx(Pencil, { className: "mr-1 h-3.5 w-3.5" }), merged.editOrganization] })) : null, _jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7", onClick: () => {
116
+ setOrgSheetMode("create");
117
+ setOrgSheetOpen(true);
118
+ }, disabled: !enabled, children: [_jsx(Building2, { className: "mr-1 h-3.5 w-3.5" }), merged.createNewOrganization] })] })] }), _jsxs(Combobox, { items: orgs.map((org) => org.id), value: value.organizationId ?? null, inputValue: orgInputValue, autoHighlight: true, disabled: !enabled, itemToStringLabel: (id) => resolveOrgLabel(id) || id, itemToStringValue: (id) => id, onInputValueChange: (next) => {
119
+ setOrgInputValue(next);
120
+ setOrgSearch(next);
121
+ if (!next)
122
+ setPerson({ organizationId: null });
123
+ }, onValueChange: (next) => {
124
+ const organizationId = next ?? null;
125
+ setPerson({ organizationId });
126
+ setOrgInputValue(organizationId ? resolveOrgLabel(organizationId) : "");
127
+ }, children: [_jsx(ComboboxInput, { placeholder: merged.organizationSearchPlaceholder, showClear: !!value.organizationId }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: merged.organizationEmpty }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
128
+ const org = orgsMap.get(id);
129
+ if (!org)
130
+ return null;
131
+ return (_jsx(ComboboxItem, { value: org.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: org.name }), org.legalName ? (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: org.legalName })) : null] }) }, org.id));
132
+ } }) })] })] })] })), _jsx(Sheet, { open: personSheetOpen, onOpenChange: setPersonSheetOpen, children: _jsxs(SheetContent, { side: "right", size: "lg", children: [_jsx(SheetHeader, { children: _jsx(SheetTitle, { children: personSheetMode === "edit"
133
+ ? merged.editPersonSheetTitle
134
+ : merged.createPersonSheetTitle }) }), _jsx(SheetBody, { children: _jsx(PersonForm, { mode: personSheetMode === "edit" && selectedPersonQuery.data
135
+ ? { kind: "edit", person: selectedPersonQuery.data }
136
+ : { kind: "create" }, onCancel: () => setPersonSheetOpen(false), onSuccess: (saved) => {
137
+ setPerson({ billTo: "person", personId: saved.id, organizationId: null });
138
+ setPersonInputValue(formatPerson(saved));
139
+ setPersonSheetOpen(false);
140
+ } }) })] }) }), _jsx(Sheet, { open: orgSheetOpen, onOpenChange: setOrgSheetOpen, children: _jsxs(SheetContent, { side: "right", size: "lg", children: [_jsx(SheetHeader, { children: _jsx(SheetTitle, { children: orgSheetMode === "edit"
141
+ ? merged.editOrganizationSheetTitle
142
+ : merged.createOrganizationSheetTitle }) }), _jsx(SheetBody, { children: _jsx(OrganizationForm, { mode: orgSheetMode === "edit" && selectedOrgQuery.data
143
+ ? { kind: "edit", organization: selectedOrgQuery.data }
144
+ : { kind: "create" }, onCancel: () => setOrgSheetOpen(false), onSuccess: (saved) => {
145
+ setPerson({ billTo: "organization", personId: "", organizationId: saved.id });
146
+ setOrgInputValue(saved.name);
147
+ setOrgSheetOpen(false);
148
+ } }) })] }) })] }));
149
+ }
150
+ function formatPersonName(person) {
151
+ if (!person)
152
+ return "";
153
+ return [person.firstName, person.lastName].filter(Boolean).join(" ").trim();
154
+ }
155
+ function formatPerson(person) {
156
+ if (!person)
157
+ return "";
158
+ const name = formatPersonName(person);
159
+ return person.email ? `${name} · ${person.email}` : name;
160
+ }
@@ -0,0 +1,83 @@
1
+ export interface PriceBreakdownLine {
2
+ unitId: string;
3
+ pricingCategoryId?: string | null;
4
+ label: string;
5
+ quantity: number;
6
+ /** Per-unit price for the matched tier/row. `null` = on-request pricing. */
7
+ unitAmountCents: number | null;
8
+ /** `unitAmountCents * quantity` or null when on-request. */
9
+ totalAmountCents: number | null;
10
+ /**
11
+ * Populated when a non-default tier matched — operator-visible "N × 100 EUR
12
+ * — group rate" kind of hint. Null for the default tier / single-price row.
13
+ */
14
+ tierLabel: string | null;
15
+ isGroupRate: boolean;
16
+ }
17
+ export interface PriceBreakdownValue {
18
+ catalogAmountCents: number | null;
19
+ confirmedAmountCents: number | null;
20
+ currency: string | null;
21
+ priceOverrideReason: string;
22
+ isManualOverride: boolean;
23
+ requiresReason: boolean;
24
+ lines: PriceBreakdownLine[];
25
+ }
26
+ export interface PriceBreakdownSectionProps {
27
+ productId?: string;
28
+ optionId?: string | null;
29
+ /** Quantity per option_unit id, typically from OptionUnitsStepperSection. */
30
+ unitQuantities: Record<string, number>;
31
+ /** Display labels keyed by option_unit id. */
32
+ unitLabels?: Record<string, string>;
33
+ /** Traveler pricing quantities keyed by option_unit id and pricing_category id. */
34
+ pricingCategoryQuantities?: Record<string, Record<string, number>>;
35
+ /** Display labels keyed by pricing_category id. */
36
+ pricingCategoryLabels?: Record<string, string>;
37
+ /**
38
+ * Force a specific catalog. Defaults to the public catalog the storefront
39
+ * uses — matches what a customer would see.
40
+ */
41
+ catalogId?: string | null;
42
+ labels?: {
43
+ heading?: string;
44
+ total?: string;
45
+ onRequest?: string;
46
+ groupRate?: string;
47
+ empty?: string;
48
+ noPricing?: string;
49
+ confirmedTotal?: string;
50
+ manualTotal?: string;
51
+ useCatalogTotal?: string;
52
+ overrideReason?: string;
53
+ overrideReasonPlaceholder?: string;
54
+ overrideReasonRequired?: string;
55
+ };
56
+ onChange?: (value: PriceBreakdownValue) => void;
57
+ /**
58
+ * When true, the section drops its bordered card wrapper and the
59
+ * heading label — for embedding inside another card (e.g. the
60
+ * booking-summary panel) where the parent owns the chrome.
61
+ */
62
+ flat?: boolean;
63
+ }
64
+ interface UnitPriceLookupRow {
65
+ unitId: string;
66
+ pricingCategoryId?: string | null;
67
+ }
68
+ export declare function createUnitPriceLookup<TUnitPrice extends UnitPriceLookupRow>(unitPrices: ReadonlyArray<TUnitPrice>): (unitId: string, pricingCategoryId: string | null) => TUnitPrice | undefined;
69
+ /**
70
+ * Live price-breakdown preview for booking-create flows. Read-only — uses
71
+ * `usePricingPreview` (#237) to fetch the catalog-resolved snapshot the
72
+ * storefront also uses, then computes lines against the operator's current
73
+ * unit quantities so the operator sees the same numbers the customer would.
74
+ *
75
+ * ### Pricing mode handling
76
+ *
77
+ * - `per_unit` — multiply the matched tier's `sellAmountCents` by quantity.
78
+ * - `free` / `included` — render 0.00 without an on-request badge.
79
+ * - `on_request` / anything else — render "On request"; total excludes it.
80
+ */
81
+ export declare function PriceBreakdownSection({ productId, optionId, unitQuantities, unitLabels, pricingCategoryQuantities, pricingCategoryLabels, catalogId, labels, onChange, flat, }: PriceBreakdownSectionProps): import("react/jsx-runtime").JSX.Element | null;
82
+ export {};
83
+ //# sourceMappingURL=price-breakdown-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price-breakdown-section.d.ts","sourceRoot":"","sources":["../../src/components/price-breakdown-section.tsx"],"names":[],"mappings":"AASA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;;;OAGG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,gBAAgB,EAAE,OAAO,CAAA;IACzB,cAAc,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,kBAAkB,EAAE,CAAA;CAC5B;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,mFAAmF;IACnF,yBAAyB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClE,mDAAmD;IACnD,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,yBAAyB,CAAC,EAAE,MAAM,CAAA;QAClC,sBAAsB,CAAC,EAAE,MAAM,CAAA;KAChC,CAAA;IACD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAC/C;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAQD,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC;AAED,wBAAgB,qBAAqB,CAAC,UAAU,SAAS,kBAAkB,EACzE,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,GACpC,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,KAAK,UAAU,GAAG,SAAS,CAwB9E;AAoBD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,EACR,cAAc,EACd,UAAU,EACV,yBAAyB,EACzB,qBAAqB,EACrB,SAAS,EACT,MAAM,EACN,QAAQ,EACR,IAAY,GACb,EAAE,0BAA0B,kDA2U5B"}
@@ -0,0 +1,278 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useProduct } from "@voyant-travel/inventory-react";
4
+ import { Button, Label, Textarea } from "@voyant-travel/ui/components";
5
+ import { CurrencyInput } from "@voyant-travel/ui/components/currency-input";
6
+ import * as React from "react";
7
+ import { useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { usePricingPreview } from "../index.js";
9
+ export function createUnitPriceLookup(unitPrices) {
10
+ const defaultUnitPricesByUnit = new Map();
11
+ const unitPricesByUnitAndCategory = new Map();
12
+ for (const unitPrice of unitPrices) {
13
+ if (unitPrice.pricingCategoryId) {
14
+ unitPricesByUnitAndCategory.set(`${unitPrice.unitId}:${unitPrice.pricingCategoryId}`, unitPrice);
15
+ continue;
16
+ }
17
+ if (!defaultUnitPricesByUnit.has(unitPrice.unitId)) {
18
+ defaultUnitPricesByUnit.set(unitPrice.unitId, unitPrice);
19
+ }
20
+ }
21
+ return (unitId, pricingCategoryId) => {
22
+ if (!pricingCategoryId)
23
+ return defaultUnitPricesByUnit.get(unitId);
24
+ return (unitPricesByUnitAndCategory.get(`${unitId}:${pricingCategoryId}`) ??
25
+ defaultUnitPricesByUnit.get(unitId));
26
+ };
27
+ }
28
+ /**
29
+ * Picks the tier whose quantity range contains `qty`. Tiers are expected
30
+ * oldest-to-newest, `minQuantity`-ascending. Ties are broken by first-match —
31
+ * the server sorts by sort_order and then min_quantity, so the selection here
32
+ * mirrors the storefront engine.
33
+ */
34
+ function matchTier(tiers, qty) {
35
+ for (const tier of tiers) {
36
+ if (qty >= tier.minQuantity &&
37
+ (tier.maxQuantity === null || qty <= tier.maxQuantity) // i18n-literal-ok numeric bounds
38
+ ) {
39
+ return tier;
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Live price-breakdown preview for booking-create flows. Read-only — uses
46
+ * `usePricingPreview` (#237) to fetch the catalog-resolved snapshot the
47
+ * storefront also uses, then computes lines against the operator's current
48
+ * unit quantities so the operator sees the same numbers the customer would.
49
+ *
50
+ * ### Pricing mode handling
51
+ *
52
+ * - `per_unit` — multiply the matched tier's `sellAmountCents` by quantity.
53
+ * - `free` / `included` — render 0.00 without an on-request badge.
54
+ * - `on_request` / anything else — render "On request"; total excludes it.
55
+ */
56
+ export function PriceBreakdownSection({ productId, optionId, unitQuantities, unitLabels, pricingCategoryQuantities, pricingCategoryLabels, catalogId, labels, onChange, flat = false, }) {
57
+ const { formatCurrency, formatNumber } = useBookingsUiI18nOrDefault();
58
+ const messages = useBookingsUiMessagesOrDefault();
59
+ const merged = { ...messages.priceBreakdownSection.labels, ...labels };
60
+ const preview = usePricingPreview({
61
+ productId: productId ?? "",
62
+ optionId: optionId ?? null,
63
+ catalogId: catalogId ?? null,
64
+ enabled: Boolean(productId),
65
+ });
66
+ const productQuery = useProduct(productId, { enabled: Boolean(productId) });
67
+ const quantitiesKey = React.useMemo(() => JSON.stringify(unitQuantities), [unitQuantities]);
68
+ const [manualAmountCents, setManualAmountCents] = React.useState(null);
69
+ const [overrideReason, setOverrideReason] = React.useState("");
70
+ // biome-ignore lint/correctness/useExhaustiveDependencies: #935 reset manual confirmation when the priced selection changes
71
+ React.useEffect(() => {
72
+ setManualAmountCents(null);
73
+ setOverrideReason("");
74
+ }, [productId, optionId, catalogId, quantitiesKey]);
75
+ const snapshot = preview.data?.data;
76
+ const fallbackProduct = productQuery.data;
77
+ const fallbackUnitAmountCents = fallbackProduct?.sellAmountCents ?? null;
78
+ const currency = snapshot?.catalog.currencyCode ?? fallbackProduct?.sellCurrency ?? null;
79
+ const formatAmount = React.useCallback((cents) => currency
80
+ ? formatCurrency(cents / 100, currency)
81
+ : formatNumber(cents / 100, {
82
+ minimumFractionDigits: 2,
83
+ maximumFractionDigits: 2,
84
+ }), [currency, formatCurrency, formatNumber]);
85
+ const { lines, total } = React.useMemo(() => {
86
+ const out = [];
87
+ let runningTotal = 0;
88
+ let anyOnRequest = false;
89
+ if (!snapshot) {
90
+ if (fallbackUnitAmountCents === null)
91
+ return { lines: out, total: null };
92
+ for (const [unitId, quantity] of Object.entries(unitQuantities)) {
93
+ if (quantity <= 0)
94
+ continue;
95
+ const lineTotal = fallbackUnitAmountCents * quantity;
96
+ out.push({
97
+ unitId,
98
+ label: unitLabels?.[unitId] ?? fallbackProduct?.name ?? unitId,
99
+ quantity,
100
+ unitAmountCents: fallbackUnitAmountCents,
101
+ totalAmountCents: lineTotal,
102
+ tierLabel: null,
103
+ isGroupRate: false,
104
+ });
105
+ runningTotal += lineTotal;
106
+ }
107
+ return { lines: out, total: runningTotal };
108
+ }
109
+ // Pick the default price rule for the resolved option (snapshot already
110
+ // filters options by the caller's optionId; rules keep isDefault-first
111
+ // ordering from the server).
112
+ const rulesByOption = new Map();
113
+ for (const rule of snapshot.rules) {
114
+ const existing = rulesByOption.get(rule.optionId) ?? [];
115
+ existing.push(rule);
116
+ rulesByOption.set(rule.optionId, existing);
117
+ }
118
+ const findUnitPrice = createUnitPriceLookup(snapshot.unitPrices);
119
+ for (const [unitId, quantity] of Object.entries(unitQuantities)) {
120
+ if (quantity <= 0)
121
+ continue;
122
+ const categoryEntries = Object.entries(pricingCategoryQuantities?.[unitId] ?? {}).filter(([, categoryQuantity]) => categoryQuantity > 0);
123
+ const selections = categoryEntries.length > 0
124
+ ? categoryEntries.map(([pricingCategoryId, categoryQuantity]) => ({
125
+ pricingCategoryId,
126
+ quantity: categoryQuantity,
127
+ unitPrice: findUnitPrice(unitId, pricingCategoryId),
128
+ }))
129
+ : [
130
+ {
131
+ pricingCategoryId: null,
132
+ quantity,
133
+ unitPrice: findUnitPrice(unitId, null),
134
+ },
135
+ ];
136
+ for (const selection of selections) {
137
+ const up = selection.unitPrice;
138
+ if (!up) {
139
+ // The unit isn't priced in this catalog — show it on-request so the
140
+ // operator knows they need to quote manually.
141
+ out.push({
142
+ unitId,
143
+ pricingCategoryId: selection.pricingCategoryId,
144
+ label: unitLabels?.[unitId] ?? unitId,
145
+ quantity: selection.quantity,
146
+ unitAmountCents: null,
147
+ totalAmountCents: null,
148
+ tierLabel: null,
149
+ isGroupRate: false,
150
+ });
151
+ anyOnRequest = true;
152
+ continue;
153
+ }
154
+ const categoryLabel = selection.pricingCategoryId
155
+ ? pricingCategoryLabels?.[selection.pricingCategoryId]
156
+ : null;
157
+ const unitLabel = unitLabels?.[unitId] ?? up.unitName ?? unitId;
158
+ const label = categoryLabel ? `${unitLabel} · ${categoryLabel}` : unitLabel;
159
+ if (up.pricingMode === "on_request") {
160
+ out.push({
161
+ unitId,
162
+ pricingCategoryId: selection.pricingCategoryId,
163
+ label,
164
+ quantity: selection.quantity,
165
+ unitAmountCents: null,
166
+ totalAmountCents: null,
167
+ tierLabel: merged.onRequest,
168
+ isGroupRate: false,
169
+ });
170
+ anyOnRequest = true;
171
+ continue;
172
+ }
173
+ if (up.pricingMode === "free" || up.pricingMode === "included") {
174
+ out.push({
175
+ unitId,
176
+ pricingCategoryId: selection.pricingCategoryId,
177
+ label,
178
+ quantity: selection.quantity,
179
+ unitAmountCents: 0,
180
+ totalAmountCents: 0,
181
+ tierLabel: null,
182
+ isGroupRate: false,
183
+ });
184
+ continue;
185
+ }
186
+ // per_unit (and anything else that falls through to explicit amounts).
187
+ const matchedTier = matchTier(up.tiers, selection.quantity);
188
+ const unitAmount = matchedTier?.sellAmountCents ?? up.sellAmountCents;
189
+ if (unitAmount === null) {
190
+ out.push({
191
+ unitId,
192
+ pricingCategoryId: selection.pricingCategoryId,
193
+ label,
194
+ quantity: selection.quantity,
195
+ unitAmountCents: null,
196
+ totalAmountCents: null,
197
+ tierLabel: merged.onRequest,
198
+ isGroupRate: false,
199
+ });
200
+ anyOnRequest = true;
201
+ continue;
202
+ }
203
+ const lineTotal = unitAmount * selection.quantity;
204
+ const isGroupRate = matchedTier !== null && matchedTier.minQuantity > 1;
205
+ out.push({
206
+ unitId,
207
+ pricingCategoryId: selection.pricingCategoryId,
208
+ label,
209
+ quantity: selection.quantity,
210
+ unitAmountCents: unitAmount,
211
+ totalAmountCents: lineTotal,
212
+ tierLabel: isGroupRate ? merged.groupRate : null,
213
+ isGroupRate,
214
+ });
215
+ runningTotal += lineTotal;
216
+ }
217
+ }
218
+ return { lines: out, total: anyOnRequest ? null : runningTotal };
219
+ }, [
220
+ snapshot,
221
+ fallbackProduct?.name,
222
+ fallbackUnitAmountCents,
223
+ unitQuantities,
224
+ unitLabels,
225
+ pricingCategoryQuantities,
226
+ pricingCategoryLabels,
227
+ merged.onRequest,
228
+ merged.groupRate,
229
+ ]);
230
+ const confirmedAmountCents = manualAmountCents ?? total;
231
+ const isManualOverride = manualAmountCents != null && (total === null || manualAmountCents !== total);
232
+ const requiresReason = isManualOverride && overrideReason.trim().length === 0;
233
+ React.useEffect(() => {
234
+ onChange?.({
235
+ catalogAmountCents: total,
236
+ confirmedAmountCents,
237
+ currency,
238
+ priceOverrideReason: overrideReason,
239
+ isManualOverride,
240
+ requiresReason,
241
+ lines,
242
+ });
243
+ }, [
244
+ confirmedAmountCents,
245
+ currency,
246
+ isManualOverride,
247
+ lines,
248
+ onChange,
249
+ overrideReason,
250
+ requiresReason,
251
+ total,
252
+ ]);
253
+ const manualTotalControls = (_jsxs("div", { className: "flex flex-col gap-2 border-t pt-2", children: [_jsxs("div", { className: "grid gap-2 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-end", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.manualTotal }), _jsx(CurrencyInput, { value: manualAmountCents, onChange: setManualAmountCents, currency: currency ?? undefined,
254
+ // CurrencyInput already renders the currency symbol + code
255
+ // as addons; the placeholder must be the bare number so we
256
+ // don't end up with `€ €790.00 EUR` showing.
257
+ placeholder: total === null
258
+ ? merged.onRequest
259
+ : formatNumber(total / 100, {
260
+ minimumFractionDigits: 2,
261
+ maximumFractionDigits: 2,
262
+ }) })] }), manualAmountCents != null ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setManualAmountCents(null), children: merged.useCatalogTotal })) : null] }), isManualOverride ? (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-xs", children: merged.overrideReason }), _jsx(Textarea, { value: overrideReason, onChange: (event) => setOverrideReason(event.target.value), placeholder: merged.overrideReasonPlaceholder, rows: 2 }), requiresReason ? (_jsx("p", { className: "text-xs text-destructive", children: merged.overrideReasonRequired })) : null] })) : null] }));
263
+ // Empty states
264
+ if (!productId)
265
+ return null;
266
+ const wrapperClassName = flat
267
+ ? "flex flex-col gap-2" // i18n-literal-ok: tailwind utilities
268
+ : "flex flex-col gap-2 rounded-md border p-3"; // i18n-literal-ok: tailwind utilities
269
+ if ((preview.isError || (preview.isSuccess && !snapshot)) && fallbackUnitAmountCents === null) {
270
+ return (_jsxs("div", { className: wrapperClassName, children: [flat ? null : _jsx(Label, { children: merged.heading }), _jsx("p", { className: "text-xs text-muted-foreground", children: merged.noPricing }), manualTotalControls] }));
271
+ }
272
+ if (lines.length === 0) {
273
+ return (_jsxs("div", { className: wrapperClassName, children: [flat ? null : _jsx(Label, { children: merged.heading }), _jsx("p", { className: "text-xs text-muted-foreground", children: merged.empty }), manualTotalControls] }));
274
+ }
275
+ return (_jsxs("div", { className: wrapperClassName, children: [flat ? null : _jsx(Label, { children: merged.heading }), _jsx("div", { className: "flex flex-col gap-1.5", children: lines.map((line) => (_jsxs("div", { className: "flex items-baseline justify-between text-sm", children: [_jsxs("div", { className: "flex items-baseline gap-2", children: [_jsxs("span", { className: "tabular-nums", children: [formatNumber(line.quantity), "x"] }), _jsx("span", { children: line.label }), line.tierLabel ? (_jsxs("span", { className: "text-xs text-muted-foreground", children: ["\u00B7 ", line.tierLabel] })) : null] }), _jsx("div", { className: "tabular-nums", children: line.totalAmountCents === null
276
+ ? merged.onRequest
277
+ : formatAmount(line.totalAmountCents) })] }, line.unitId))) }), _jsxs("div", { className: "mt-1 flex items-baseline justify-between border-t pt-2 text-sm font-medium", children: [_jsx("span", { children: merged.total }), _jsx("span", { className: "tabular-nums", children: total === null ? merged.onRequest : formatAmount(total) })] }), _jsxs("div", { className: "flex items-baseline justify-between text-sm font-medium", children: [_jsx("span", { children: merged.confirmedTotal }), _jsx("span", { className: "tabular-nums", children: confirmedAmountCents === null ? merged.onRequest : formatAmount(confirmedAmountCents) })] }), manualTotalControls] }));
278
+ }
@@ -0,0 +1,29 @@
1
+ export interface ProductPickerValue {
2
+ productId: string;
3
+ /** `null` means "no specific option" — the product has options but none was picked. */
4
+ optionId: string | null;
5
+ }
6
+ export interface ProductPickerSectionProps {
7
+ value: ProductPickerValue;
8
+ onChange: (value: ProductPickerValue) => void;
9
+ /** When true, skip data fetches (dialog closed / parent gated). */
10
+ enabled?: boolean;
11
+ /** When true, hide the product picker and fix the productId (e.g., launched from a product page). */
12
+ lockProduct?: boolean;
13
+ /** When false, product options are selected downstream as quantities instead of a single global choice. */
14
+ showOptionPicker?: boolean;
15
+ labels?: {
16
+ product?: string;
17
+ productSearchPlaceholder?: string;
18
+ productSelectPlaceholder?: string;
19
+ option?: string;
20
+ optionNone?: string;
21
+ };
22
+ }
23
+ /**
24
+ * Controlled product + option picker. Splits `value` + `onChange` so apps can
25
+ * replace the whole section (e.g., with a typeahead against a custom catalog)
26
+ * without reimplementing the cascade logic, or keep this one and swap labels.
27
+ */
28
+ export declare function ProductPickerSection({ value, onChange, enabled, lockProduct, showOptionPicker, labels, }: ProductPickerSectionProps): import("react/jsx-runtime").JSX.Element;
29
+ //# sourceMappingURL=product-picker-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-picker-section.d.ts","sourceRoot":"","sources":["../../src/components/product-picker-section.tsx"],"names":[],"mappings":"AA+BA,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,uFAAuF;IACvF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,kBAAkB,CAAA;IACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC7C,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qGAAqG;IACrG,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2GAA2G;IAC3G,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,wBAAwB,CAAC,EAAE,MAAM,CAAA;QACjC,wBAAwB,CAAC,EAAE,MAAM,CAAA;QACjC,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;CACF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,QAAQ,EACR,OAAc,EACd,WAAmB,EACnB,gBAAuB,EACvB,MAAM,GACP,EAAE,yBAAyB,2CAyI3B"}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useProduct, useProductOptions, useProducts, } from "@voyant-travel/inventory-react";
4
+ import { Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@voyant-travel/ui/components";
5
+ import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyant-travel/ui/components/combobox";
6
+ import * as React from "react";
7
+ import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
8
+ import { productMatchesPickerSearch } from "./booking-create-utils.js";
9
+ const OPTION_NONE = "__none__";
10
+ /**
11
+ * Controlled product + option picker. Splits `value` + `onChange` so apps can
12
+ * replace the whole section (e.g., with a typeahead against a custom catalog)
13
+ * without reimplementing the cascade logic, or keep this one and swap labels.
14
+ */
15
+ export function ProductPickerSection({ value, onChange, enabled = true, lockProduct = false, showOptionPicker = true, labels, }) {
16
+ const [productSearch, setProductSearch] = React.useState("");
17
+ const cachedProductsRef = React.useRef(new Map());
18
+ const messages = useBookingsUiMessagesOrDefault();
19
+ const merged = { ...messages.productPickerSection.labels, ...labels };
20
+ const { data: productsData } = useProducts({
21
+ search: productSearch || undefined,
22
+ limit: 20,
23
+ enabled: enabled && !lockProduct,
24
+ });
25
+ const selectedProductQuery = useProduct(value.productId || undefined, {
26
+ enabled: enabled && Boolean(value.productId),
27
+ });
28
+ const products = React.useMemo(() => {
29
+ const map = new Map(cachedProductsRef.current);
30
+ for (const product of productsData?.data ?? [])
31
+ map.set(product.id, product);
32
+ if (selectedProductQuery.data)
33
+ map.set(selectedProductQuery.data.id, selectedProductQuery.data);
34
+ cachedProductsRef.current = map;
35
+ return Array.from(map.values());
36
+ }, [productsData?.data, selectedProductQuery.data]);
37
+ const productMap = React.useMemo(() => new Map(products.map((product) => [product.id, product])), [products]);
38
+ const resolveProductLabel = React.useCallback((productId) => productMap.get(productId)?.name ?? cachedProductsRef.current.get(productId)?.name ?? "", [productMap]);
39
+ const selectedProductLabel = value.productId ? resolveProductLabel(value.productId) : "";
40
+ const [productInputValue, setProductInputValue] = React.useState(selectedProductLabel);
41
+ React.useEffect(() => {
42
+ if (selectedProductLabel)
43
+ setProductInputValue(selectedProductLabel);
44
+ }, [selectedProductLabel]);
45
+ const { data: optionsData } = useProductOptions({
46
+ productId: value.productId || undefined,
47
+ limit: 50,
48
+ enabled: enabled && showOptionPicker && Boolean(value.productId),
49
+ });
50
+ const options = optionsData?.data ?? [];
51
+ return (_jsxs(_Fragment, { children: [!lockProduct && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs(Label, { children: [merged.product, " ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsxs(Combobox, { items: products.map((product) => product.id), value: value.productId || null, inputValue: productInputValue, autoHighlight: true, disabled: !enabled, filter: (id, query) => productMatchesPickerSearch(productMap.get(id), query), itemToStringLabel: (id) => resolveProductLabel(id) || id, itemToStringValue: (id) => id, onInputValueChange: (next) => {
52
+ setProductInputValue(next);
53
+ setProductSearch(next);
54
+ if (!next)
55
+ onChange({ productId: "", optionId: null });
56
+ }, onValueChange: (next) => {
57
+ const productId = next ?? "";
58
+ onChange({ productId, optionId: null });
59
+ setProductInputValue(productId ? resolveProductLabel(productId) : "");
60
+ }, children: [_jsx(ComboboxInput, { placeholder: merged.productSearchPlaceholder, showClear: !!value.productId }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: merged.productEmpty }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
61
+ const product = productMap.get(id);
62
+ if (!product)
63
+ return null;
64
+ return (_jsx(ComboboxItem, { value: product.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: product.name }), _jsxs("span", { className: "truncate text-xs text-muted-foreground", children: [product.sellCurrency, product.sellAmountCents != null
65
+ ? ` · ${product.sellAmountCents / 100}`
66
+ : ""] })] }) }, product.id));
67
+ } }) })] })] })] })), showOptionPicker && value.productId && options.length > 0 && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: merged.option }), _jsxs(Select, { items: [
68
+ { label: merged.optionNone, value: OPTION_NONE },
69
+ ...options.map((o) => ({ label: o.name, value: o.id })),
70
+ ], value: value.optionId ?? OPTION_NONE, onValueChange: (v) => onChange({
71
+ productId: value.productId,
72
+ optionId: v === OPTION_NONE ? null : (v ?? null),
73
+ }), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: OPTION_NONE, children: merged.optionNone }), options.map((o) => (_jsx(SelectItem, { value: o.id, children: o.name }, o.id)))] })] })] }))] }));
74
+ }