@voyant-travel/finance-react 0.119.5

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 (517) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +75 -0
  3. package/dist/admin/booking-invoices-widget.d.ts +19 -0
  4. package/dist/admin/booking-invoices-widget.d.ts.map +1 -0
  5. package/dist/admin/booking-invoices-widget.js +204 -0
  6. package/dist/admin/booking-payment-policy-widget.d.ts +21 -0
  7. package/dist/admin/booking-payment-policy-widget.d.ts.map +1 -0
  8. package/dist/admin/booking-payment-policy-widget.js +128 -0
  9. package/dist/admin/booking-pending-payment-sessions-widget.d.ts +24 -0
  10. package/dist/admin/booking-pending-payment-sessions-widget.d.ts.map +1 -0
  11. package/dist/admin/booking-pending-payment-sessions-widget.js +139 -0
  12. package/dist/admin/credit-note-dialog.d.ts +9 -0
  13. package/dist/admin/credit-note-dialog.d.ts.map +1 -0
  14. package/dist/admin/credit-note-dialog.js +70 -0
  15. package/dist/admin/finance-shared.d.ts +7 -0
  16. package/dist/admin/finance-shared.d.ts.map +1 -0
  17. package/dist/admin/finance-shared.js +30 -0
  18. package/dist/admin/index.d.ts +99 -0
  19. package/dist/admin/index.d.ts.map +1 -0
  20. package/dist/admin/index.js +286 -0
  21. package/dist/admin/invoice-detail-host.d.ts +19 -0
  22. package/dist/admin/invoice-detail-host.d.ts.map +1 -0
  23. package/dist/admin/invoice-detail-host.js +147 -0
  24. package/dist/admin/invoice-detail-sections.d.ts +31 -0
  25. package/dist/admin/invoice-detail-sections.d.ts.map +1 -0
  26. package/dist/admin/invoice-detail-sections.js +109 -0
  27. package/dist/admin/invoice-detail-skeleton.d.ts +11 -0
  28. package/dist/admin/invoice-detail-skeleton.d.ts.map +1 -0
  29. package/dist/admin/invoice-detail-skeleton.js +33 -0
  30. package/dist/admin/line-item-dialog.d.ts +10 -0
  31. package/dist/admin/line-item-dialog.d.ts.map +1 -0
  32. package/dist/admin/line-item-dialog.js +91 -0
  33. package/dist/admin/pages/invoice-detail.d.ts +8 -0
  34. package/dist/admin/pages/invoice-detail.d.ts.map +1 -0
  35. package/dist/admin/pages/invoice-detail.js +11 -0
  36. package/dist/admin/pages/invoices-index.d.ts +8 -0
  37. package/dist/admin/pages/invoices-index.d.ts.map +1 -0
  38. package/dist/admin/pages/invoices-index.js +14 -0
  39. package/dist/admin/pages/payment-detail.d.ts +8 -0
  40. package/dist/admin/pages/payment-detail.d.ts.map +1 -0
  41. package/dist/admin/pages/payment-detail.js +11 -0
  42. package/dist/admin/pages/payments-index.d.ts +9 -0
  43. package/dist/admin/pages/payments-index.d.ts.map +1 -0
  44. package/dist/admin/pages/payments-index.js +21 -0
  45. package/dist/admin/pages/profitability.d.ts +10 -0
  46. package/dist/admin/pages/profitability.d.ts.map +1 -0
  47. package/dist/admin/pages/profitability.js +32 -0
  48. package/dist/admin/pages/supplier-invoice-detail.d.ts +20 -0
  49. package/dist/admin/pages/supplier-invoice-detail.d.ts.map +1 -0
  50. package/dist/admin/pages/supplier-invoice-detail.js +102 -0
  51. package/dist/admin/pages/supplier-invoices-index.d.ts +9 -0
  52. package/dist/admin/pages/supplier-invoices-index.d.ts.map +1 -0
  53. package/dist/admin/pages/supplier-invoices-index.js +16 -0
  54. package/dist/admin/payment-detail-host.d.ts +12 -0
  55. package/dist/admin/payment-detail-host.d.ts.map +1 -0
  56. package/dist/admin/payment-detail-host.js +108 -0
  57. package/dist/admin/payment-detail-skeleton.d.ts +8 -0
  58. package/dist/admin/payment-detail-skeleton.d.ts.map +1 -0
  59. package/dist/admin/payment-detail-skeleton.js +15 -0
  60. package/dist/admin/payment-dialog.d.ts +9 -0
  61. package/dist/admin/payment-dialog.d.ts.map +1 -0
  62. package/dist/admin/payment-dialog.js +99 -0
  63. package/dist/admin/record-payment-dialog.d.ts +16 -0
  64. package/dist/admin/record-payment-dialog.d.ts.map +1 -0
  65. package/dist/admin/record-payment-dialog.js +219 -0
  66. package/dist/admin/supplier-payment-policy-widget.d.ts +18 -0
  67. package/dist/admin/supplier-payment-policy-widget.d.ts.map +1 -0
  68. package/dist/admin/supplier-payment-policy-widget.js +31 -0
  69. package/dist/admin/use-supplier-picker.d.ts +19 -0
  70. package/dist/admin/use-supplier-picker.d.ts.map +1 -0
  71. package/dist/admin/use-supplier-picker.js +30 -0
  72. package/dist/checkout-components/collect-payment-dialog.d.ts +45 -0
  73. package/dist/checkout-components/collect-payment-dialog.d.ts.map +1 -0
  74. package/dist/checkout-components/collect-payment-dialog.js +121 -0
  75. package/dist/checkout-components/payment-link-landing-page.d.ts +76 -0
  76. package/dist/checkout-components/payment-link-landing-page.d.ts.map +1 -0
  77. package/dist/checkout-components/payment-link-landing-page.js +173 -0
  78. package/dist/checkout-components/payment-step.d.ts +42 -0
  79. package/dist/checkout-components/payment-step.d.ts.map +1 -0
  80. package/dist/checkout-components/payment-step.js +113 -0
  81. package/dist/checkout-hooks/index.d.ts +5 -0
  82. package/dist/checkout-hooks/index.d.ts.map +1 -0
  83. package/dist/checkout-hooks/index.js +4 -0
  84. package/dist/checkout-hooks/use-checkout-payment-link-config.d.ts +20 -0
  85. package/dist/checkout-hooks/use-checkout-payment-link-config.d.ts.map +1 -0
  86. package/dist/checkout-hooks/use-checkout-payment-link-config.js +26 -0
  87. package/dist/checkout-hooks/use-collect-payment.d.ts +227 -0
  88. package/dist/checkout-hooks/use-collect-payment.d.ts.map +1 -0
  89. package/dist/checkout-hooks/use-collect-payment.js +80 -0
  90. package/dist/checkout-hooks/use-initiate-checkout-collection.d.ts +308 -0
  91. package/dist/checkout-hooks/use-initiate-checkout-collection.d.ts.map +1 -0
  92. package/dist/checkout-hooks/use-initiate-checkout-collection.js +35 -0
  93. package/dist/checkout-hooks/use-preview-checkout-collection.d.ts +65 -0
  94. package/dist/checkout-hooks/use-preview-checkout-collection.d.ts.map +1 -0
  95. package/dist/checkout-hooks/use-preview-checkout-collection.js +27 -0
  96. package/dist/checkout-i18n/en.d.ts +3 -0
  97. package/dist/checkout-i18n/en.d.ts.map +1 -0
  98. package/dist/checkout-i18n/en.js +127 -0
  99. package/dist/checkout-i18n/index.d.ts +5 -0
  100. package/dist/checkout-i18n/index.d.ts.map +1 -0
  101. package/dist/checkout-i18n/index.js +3 -0
  102. package/dist/checkout-i18n/messages.d.ts +121 -0
  103. package/dist/checkout-i18n/messages.d.ts.map +1 -0
  104. package/dist/checkout-i18n/messages.js +1 -0
  105. package/dist/checkout-i18n/provider.d.ts +26 -0
  106. package/dist/checkout-i18n/provider.d.ts.map +1 -0
  107. package/dist/checkout-i18n/provider.js +41 -0
  108. package/dist/checkout-i18n/ro.d.ts +3 -0
  109. package/dist/checkout-i18n/ro.d.ts.map +1 -0
  110. package/dist/checkout-i18n/ro.js +127 -0
  111. package/dist/checkout-types.d.ts +53 -0
  112. package/dist/checkout-types.d.ts.map +1 -0
  113. package/dist/checkout-types.js +1 -0
  114. package/dist/checkout-ui.d.ts +7 -0
  115. package/dist/checkout-ui.d.ts.map +1 -0
  116. package/dist/checkout-ui.js +4 -0
  117. package/dist/checkout.d.ts +5 -0
  118. package/dist/checkout.d.ts.map +1 -0
  119. package/dist/checkout.js +3 -0
  120. package/dist/client.d.ts +16 -0
  121. package/dist/client.d.ts.map +1 -0
  122. package/dist/client.js +79 -0
  123. package/dist/components/accountant-portal/body.d.ts +8 -0
  124. package/dist/components/accountant-portal/body.d.ts.map +1 -0
  125. package/dist/components/accountant-portal/body.js +114 -0
  126. package/dist/components/accountant-portal/widgets.d.ts +13 -0
  127. package/dist/components/accountant-portal/widgets.d.ts.map +1 -0
  128. package/dist/components/accountant-portal/widgets.js +27 -0
  129. package/dist/components/accountant-portal.d.ts +10 -0
  130. package/dist/components/accountant-portal.d.ts.map +1 -0
  131. package/dist/components/accountant-portal.js +22 -0
  132. package/dist/components/accountant-share-dialog.d.ts +6 -0
  133. package/dist/components/accountant-share-dialog.d.ts.map +1 -0
  134. package/dist/components/accountant-share-dialog.js +53 -0
  135. package/dist/components/async-combobox.d.ts +33 -0
  136. package/dist/components/async-combobox.d.ts.map +1 -0
  137. package/dist/components/async-combobox.js +100 -0
  138. package/dist/components/booking-invoice-dialog.d.ts +63 -0
  139. package/dist/components/booking-invoice-dialog.d.ts.map +1 -0
  140. package/dist/components/booking-invoice-dialog.js +383 -0
  141. package/dist/components/cost-categories-page.d.ts +5 -0
  142. package/dist/components/cost-categories-page.d.ts.map +1 -0
  143. package/dist/components/cost-categories-page.js +30 -0
  144. package/dist/components/invoice-action-ledger-card.d.ts +15 -0
  145. package/dist/components/invoice-action-ledger-card.d.ts.map +1 -0
  146. package/dist/components/invoice-action-ledger-card.js +76 -0
  147. package/dist/components/invoice-bulk-actions.d.ts +10 -0
  148. package/dist/components/invoice-bulk-actions.d.ts.map +1 -0
  149. package/dist/components/invoice-bulk-actions.js +19 -0
  150. package/dist/components/invoice-detail-page/cards.d.ts +44 -0
  151. package/dist/components/invoice-detail-page/cards.d.ts.map +1 -0
  152. package/dist/components/invoice-detail-page/cards.js +43 -0
  153. package/dist/components/invoice-detail-page/header.d.ts +15 -0
  154. package/dist/components/invoice-detail-page/header.d.ts.map +1 -0
  155. package/dist/components/invoice-detail-page/header.js +30 -0
  156. package/dist/components/invoice-detail-page/notes-dialogs.d.ts +28 -0
  157. package/dist/components/invoice-detail-page/notes-dialogs.d.ts.map +1 -0
  158. package/dist/components/invoice-detail-page/notes-dialogs.js +104 -0
  159. package/dist/components/invoice-detail-page/primitives.d.ts +47 -0
  160. package/dist/components/invoice-detail-page/primitives.d.ts.map +1 -0
  161. package/dist/components/invoice-detail-page/primitives.js +76 -0
  162. package/dist/components/invoice-detail-page-with-action-ledger.d.ts +7 -0
  163. package/dist/components/invoice-detail-page-with-action-ledger.d.ts.map +1 -0
  164. package/dist/components/invoice-detail-page-with-action-ledger.js +11 -0
  165. package/dist/components/invoice-detail-page.d.ts +46 -0
  166. package/dist/components/invoice-detail-page.d.ts.map +1 -0
  167. package/dist/components/invoice-detail-page.js +134 -0
  168. package/dist/components/invoice-dialog.d.ts +9 -0
  169. package/dist/components/invoice-dialog.d.ts.map +1 -0
  170. package/dist/components/invoice-dialog.js +145 -0
  171. package/dist/components/invoice-number-series-dialog.d.ts +9 -0
  172. package/dist/components/invoice-number-series-dialog.d.ts.map +1 -0
  173. package/dist/components/invoice-number-series-dialog.js +134 -0
  174. package/dist/components/invoice-number-series-format.d.ts +3 -0
  175. package/dist/components/invoice-number-series-format.d.ts.map +1 -0
  176. package/dist/components/invoice-number-series-format.js +4 -0
  177. package/dist/components/invoice-number-series-page.d.ts +5 -0
  178. package/dist/components/invoice-number-series-page.d.ts.map +1 -0
  179. package/dist/components/invoice-number-series-page.js +55 -0
  180. package/dist/components/invoice-table-parts.d.ts +25 -0
  181. package/dist/components/invoice-table-parts.d.ts.map +1 -0
  182. package/dist/components/invoice-table-parts.js +32 -0
  183. package/dist/components/invoices-page-skeleton.d.ts +5 -0
  184. package/dist/components/invoices-page-skeleton.d.ts.map +1 -0
  185. package/dist/components/invoices-page-skeleton.js +13 -0
  186. package/dist/components/invoices-page.d.ts +6 -0
  187. package/dist/components/invoices-page.d.ts.map +1 -0
  188. package/dist/components/invoices-page.js +145 -0
  189. package/dist/components/payment-detail-page.d.ts +47 -0
  190. package/dist/components/payment-detail-page.d.ts.map +1 -0
  191. package/dist/components/payment-detail-page.js +90 -0
  192. package/dist/components/payment-policy-form.d.ts +49 -0
  193. package/dist/components/payment-policy-form.d.ts.map +1 -0
  194. package/dist/components/payment-policy-form.js +82 -0
  195. package/dist/components/payments-page/controls.d.ts +23 -0
  196. package/dist/components/payments-page/controls.d.ts.map +1 -0
  197. package/dist/components/payments-page/controls.js +20 -0
  198. package/dist/components/payments-page-skeleton.d.ts +5 -0
  199. package/dist/components/payments-page-skeleton.d.ts.map +1 -0
  200. package/dist/components/payments-page-skeleton.js +13 -0
  201. package/dist/components/payments-page.d.ts +20 -0
  202. package/dist/components/payments-page.d.ts.map +1 -0
  203. package/dist/components/payments-page.js +143 -0
  204. package/dist/components/profitability-page/sections.d.ts +24 -0
  205. package/dist/components/profitability-page/sections.d.ts.map +1 -0
  206. package/dist/components/profitability-page/sections.js +43 -0
  207. package/dist/components/profitability-page.d.ts +13 -0
  208. package/dist/components/profitability-page.d.ts.map +1 -0
  209. package/dist/components/profitability-page.js +175 -0
  210. package/dist/components/record-booking-payment-dialog/shared.d.ts +54 -0
  211. package/dist/components/record-booking-payment-dialog/shared.d.ts.map +1 -0
  212. package/dist/components/record-booking-payment-dialog/shared.js +47 -0
  213. package/dist/components/record-booking-payment-dialog.d.ts +4 -0
  214. package/dist/components/record-booking-payment-dialog.d.ts.map +1 -0
  215. package/dist/components/record-booking-payment-dialog.js +256 -0
  216. package/dist/components/supplier-invoice-detail-page/dialogs.d.ts +34 -0
  217. package/dist/components/supplier-invoice-detail-page/dialogs.d.ts.map +1 -0
  218. package/dist/components/supplier-invoice-detail-page/dialogs.js +119 -0
  219. package/dist/components/supplier-invoice-detail-page/shared.d.ts +64 -0
  220. package/dist/components/supplier-invoice-detail-page/shared.d.ts.map +1 -0
  221. package/dist/components/supplier-invoice-detail-page/shared.js +70 -0
  222. package/dist/components/supplier-invoice-detail-page.d.ts +4 -0
  223. package/dist/components/supplier-invoice-detail-page.d.ts.map +1 -0
  224. package/dist/components/supplier-invoice-detail-page.js +101 -0
  225. package/dist/components/supplier-invoice-form-dialog.d.ts +45 -0
  226. package/dist/components/supplier-invoice-form-dialog.d.ts.map +1 -0
  227. package/dist/components/supplier-invoice-form-dialog.js +102 -0
  228. package/dist/components/supplier-invoices-page.d.ts +14 -0
  229. package/dist/components/supplier-invoices-page.d.ts.map +1 -0
  230. package/dist/components/supplier-invoices-page.js +69 -0
  231. package/dist/components/supplier-payment-dialog.d.ts +7 -0
  232. package/dist/components/supplier-payment-dialog.d.ts.map +1 -0
  233. package/dist/components/supplier-payment-dialog.js +103 -0
  234. package/dist/components/taxes-page/policy-profile-sheet.d.ts +8 -0
  235. package/dist/components/taxes-page/policy-profile-sheet.d.ts.map +1 -0
  236. package/dist/components/taxes-page/policy-profile-sheet.js +52 -0
  237. package/dist/components/taxes-page/policy-rule-sheet.d.ts +10 -0
  238. package/dist/components/taxes-page/policy-rule-sheet.d.ts.map +1 -0
  239. package/dist/components/taxes-page/policy-rule-sheet.js +137 -0
  240. package/dist/components/taxes-page/shared.d.ts +128 -0
  241. package/dist/components/taxes-page/shared.d.ts.map +1 -0
  242. package/dist/components/taxes-page/shared.js +288 -0
  243. package/dist/components/taxes-page/sheets.d.ts +4 -0
  244. package/dist/components/taxes-page/sheets.d.ts.map +1 -0
  245. package/dist/components/taxes-page/sheets.js +3 -0
  246. package/dist/components/taxes-page/tax-sheet.d.ts +9 -0
  247. package/dist/components/taxes-page/tax-sheet.d.ts.map +1 -0
  248. package/dist/components/taxes-page/tax-sheet.js +108 -0
  249. package/dist/components/taxes-page.d.ts +4 -0
  250. package/dist/components/taxes-page.d.ts.map +1 -0
  251. package/dist/components/taxes-page.js +165 -0
  252. package/dist/hooks/index.d.ts +53 -0
  253. package/dist/hooks/index.d.ts.map +1 -0
  254. package/dist/hooks/index.js +52 -0
  255. package/dist/hooks/use-accountant-share-mutation.d.ts +20 -0
  256. package/dist/hooks/use-accountant-share-mutation.d.ts.map +1 -0
  257. package/dist/hooks/use-accountant-share-mutation.js +27 -0
  258. package/dist/hooks/use-accountant-shares.d.ts +13 -0
  259. package/dist/hooks/use-accountant-shares.d.ts.map +1 -0
  260. package/dist/hooks/use-accountant-shares.js +8 -0
  261. package/dist/hooks/use-admin-booking-payments.d.ts +30 -0
  262. package/dist/hooks/use-admin-booking-payments.d.ts.map +1 -0
  263. package/dist/hooks/use-admin-booking-payments.js +18 -0
  264. package/dist/hooks/use-all-payments.d.ts +35 -0
  265. package/dist/hooks/use-all-payments.d.ts.map +1 -0
  266. package/dist/hooks/use-all-payments.js +12 -0
  267. package/dist/hooks/use-booking-guarantees.d.ts +82 -0
  268. package/dist/hooks/use-booking-guarantees.d.ts.map +1 -0
  269. package/dist/hooks/use-booking-guarantees.js +46 -0
  270. package/dist/hooks/use-booking-payment-schedule-regenerate-mutation.d.ts +44 -0
  271. package/dist/hooks/use-booking-payment-schedule-regenerate-mutation.d.ts.map +1 -0
  272. package/dist/hooks/use-booking-payment-schedule-regenerate-mutation.js +27 -0
  273. package/dist/hooks/use-booking-payment-schedules.d.ts +63 -0
  274. package/dist/hooks/use-booking-payment-schedules.d.ts.map +1 -0
  275. package/dist/hooks/use-booking-payment-schedules.js +47 -0
  276. package/dist/hooks/use-cost-categories.d.ts +14 -0
  277. package/dist/hooks/use-cost-categories.d.ts.map +1 -0
  278. package/dist/hooks/use-cost-categories.js +9 -0
  279. package/dist/hooks/use-cost-category-mutation.d.ts +31 -0
  280. package/dist/hooks/use-cost-category-mutation.d.ts.map +1 -0
  281. package/dist/hooks/use-cost-category-mutation.js +27 -0
  282. package/dist/hooks/use-departure-profitability.d.ts +56 -0
  283. package/dist/hooks/use-departure-profitability.d.ts.map +1 -0
  284. package/dist/hooks/use-departure-profitability.js +12 -0
  285. package/dist/hooks/use-finance-action-ledger.d.ts +94 -0
  286. package/dist/hooks/use-finance-action-ledger.d.ts.map +1 -0
  287. package/dist/hooks/use-finance-action-ledger.js +20 -0
  288. package/dist/hooks/use-invoice-attachment-mutation.d.ts +43 -0
  289. package/dist/hooks/use-invoice-attachment-mutation.d.ts.map +1 -0
  290. package/dist/hooks/use-invoice-attachment-mutation.js +39 -0
  291. package/dist/hooks/use-invoice-attachments.d.ts +18 -0
  292. package/dist/hooks/use-invoice-attachments.d.ts.map +1 -0
  293. package/dist/hooks/use-invoice-attachments.js +12 -0
  294. package/dist/hooks/use-invoice-bulk-status-mutation.d.ts +51 -0
  295. package/dist/hooks/use-invoice-bulk-status-mutation.d.ts.map +1 -0
  296. package/dist/hooks/use-invoice-bulk-status-mutation.js +66 -0
  297. package/dist/hooks/use-invoice-credit-note-mutation.d.ts +38 -0
  298. package/dist/hooks/use-invoice-credit-note-mutation.d.ts.map +1 -0
  299. package/dist/hooks/use-invoice-credit-note-mutation.js +35 -0
  300. package/dist/hooks/use-invoice-credit-notes.d.ts +17 -0
  301. package/dist/hooks/use-invoice-credit-notes.d.ts.map +1 -0
  302. package/dist/hooks/use-invoice-credit-notes.js +12 -0
  303. package/dist/hooks/use-invoice-fx-rate.d.ts +19 -0
  304. package/dist/hooks/use-invoice-fx-rate.d.ts.map +1 -0
  305. package/dist/hooks/use-invoice-fx-rate.js +13 -0
  306. package/dist/hooks/use-invoice-line-item-mutation.d.ts +40 -0
  307. package/dist/hooks/use-invoice-line-item-mutation.d.ts.map +1 -0
  308. package/dist/hooks/use-invoice-line-item-mutation.js +42 -0
  309. package/dist/hooks/use-invoice-line-items.d.ts +17 -0
  310. package/dist/hooks/use-invoice-line-items.d.ts.map +1 -0
  311. package/dist/hooks/use-invoice-line-items.js +12 -0
  312. package/dist/hooks/use-invoice-mutation.d.ts +225 -0
  313. package/dist/hooks/use-invoice-mutation.d.ts.map +1 -0
  314. package/dist/hooks/use-invoice-mutation.js +121 -0
  315. package/dist/hooks/use-invoice-note-mutation.d.ts +11 -0
  316. package/dist/hooks/use-invoice-note-mutation.d.ts.map +1 -0
  317. package/dist/hooks/use-invoice-note-mutation.js +23 -0
  318. package/dist/hooks/use-invoice-notes.d.ts +13 -0
  319. package/dist/hooks/use-invoice-notes.d.ts.map +1 -0
  320. package/dist/hooks/use-invoice-notes.js +12 -0
  321. package/dist/hooks/use-invoice-number-series-mutation.d.ts +62 -0
  322. package/dist/hooks/use-invoice-number-series-mutation.d.ts.map +1 -0
  323. package/dist/hooks/use-invoice-number-series-mutation.js +39 -0
  324. package/dist/hooks/use-invoice-number-series.d.ts +28 -0
  325. package/dist/hooks/use-invoice-number-series.d.ts.map +1 -0
  326. package/dist/hooks/use-invoice-number-series.js +12 -0
  327. package/dist/hooks/use-invoice-payment-mutation.d.ts +29 -0
  328. package/dist/hooks/use-invoice-payment-mutation.d.ts.map +1 -0
  329. package/dist/hooks/use-invoice-payment-mutation.js +35 -0
  330. package/dist/hooks/use-invoice-payments.d.ts +21 -0
  331. package/dist/hooks/use-invoice-payments.d.ts.map +1 -0
  332. package/dist/hooks/use-invoice-payments.js +12 -0
  333. package/dist/hooks/use-invoice.d.ts +32 -0
  334. package/dist/hooks/use-invoice.d.ts.map +1 -0
  335. package/dist/hooks/use-invoice.js +12 -0
  336. package/dist/hooks/use-invoices.d.ts +36 -0
  337. package/dist/hooks/use-invoices.d.ts.map +1 -0
  338. package/dist/hooks/use-invoices.js +12 -0
  339. package/dist/hooks/use-payment-mutation.d.ts +57 -0
  340. package/dist/hooks/use-payment-mutation.d.ts.map +1 -0
  341. package/dist/hooks/use-payment-mutation.js +59 -0
  342. package/dist/hooks/use-payment-session-mutation.d.ts +205 -0
  343. package/dist/hooks/use-payment-session-mutation.d.ts.map +1 -0
  344. package/dist/hooks/use-payment-session-mutation.js +38 -0
  345. package/dist/hooks/use-payment-sessions.d.ts +97 -0
  346. package/dist/hooks/use-payment-sessions.d.ts.map +1 -0
  347. package/dist/hooks/use-payment-sessions.js +17 -0
  348. package/dist/hooks/use-payment.d.ts +31 -0
  349. package/dist/hooks/use-payment.d.ts.map +1 -0
  350. package/dist/hooks/use-payment.js +12 -0
  351. package/dist/hooks/use-product-profitability.d.ts +52 -0
  352. package/dist/hooks/use-product-profitability.d.ts.map +1 -0
  353. package/dist/hooks/use-product-profitability.js +12 -0
  354. package/dist/hooks/use-public-booking-documents.d.ts +29 -0
  355. package/dist/hooks/use-public-booking-documents.d.ts.map +1 -0
  356. package/dist/hooks/use-public-booking-documents.js +12 -0
  357. package/dist/hooks/use-public-booking-payment-options.d.ts +47 -0
  358. package/dist/hooks/use-public-booking-payment-options.d.ts.map +1 -0
  359. package/dist/hooks/use-public-booking-payment-options.js +12 -0
  360. package/dist/hooks/use-public-booking-payments.d.ts +24 -0
  361. package/dist/hooks/use-public-booking-payments.d.ts.map +1 -0
  362. package/dist/hooks/use-public-booking-payments.js +12 -0
  363. package/dist/hooks/use-public-finance-document-by-reference.d.ts +27 -0
  364. package/dist/hooks/use-public-finance-document-by-reference.d.ts.map +1 -0
  365. package/dist/hooks/use-public-finance-document-by-reference.js +12 -0
  366. package/dist/hooks/use-public-payment-session-mutation.d.ts +82 -0
  367. package/dist/hooks/use-public-payment-session-mutation.d.ts.map +1 -0
  368. package/dist/hooks/use-public-payment-session-mutation.js +33 -0
  369. package/dist/hooks/use-public-payment-session.d.ts +73 -0
  370. package/dist/hooks/use-public-payment-session.d.ts.map +1 -0
  371. package/dist/hooks/use-public-payment-session.js +12 -0
  372. package/dist/hooks/use-public-voucher-validation-mutation.d.ts +23 -0
  373. package/dist/hooks/use-public-voucher-validation-mutation.d.ts.map +1 -0
  374. package/dist/hooks/use-public-voucher-validation-mutation.js +17 -0
  375. package/dist/hooks/use-supplier-invoice-attachments.d.ts +17 -0
  376. package/dist/hooks/use-supplier-invoice-attachments.d.ts.map +1 -0
  377. package/dist/hooks/use-supplier-invoice-attachments.js +12 -0
  378. package/dist/hooks/use-supplier-invoice-mutation.d.ts +353 -0
  379. package/dist/hooks/use-supplier-invoice-mutation.d.ts.map +1 -0
  380. package/dist/hooks/use-supplier-invoice-mutation.js +81 -0
  381. package/dist/hooks/use-supplier-invoice-payments.d.ts +26 -0
  382. package/dist/hooks/use-supplier-invoice-payments.d.ts.map +1 -0
  383. package/dist/hooks/use-supplier-invoice-payments.js +12 -0
  384. package/dist/hooks/use-supplier-invoice.d.ts +65 -0
  385. package/dist/hooks/use-supplier-invoice.d.ts.map +1 -0
  386. package/dist/hooks/use-supplier-invoice.js +12 -0
  387. package/dist/hooks/use-supplier-invoices.d.ts +36 -0
  388. package/dist/hooks/use-supplier-invoices.d.ts.map +1 -0
  389. package/dist/hooks/use-supplier-invoices.js +12 -0
  390. package/dist/hooks/use-supplier-payment-mutation.d.ts +55 -0
  391. package/dist/hooks/use-supplier-payment-mutation.d.ts.map +1 -0
  392. package/dist/hooks/use-supplier-payment-mutation.js +35 -0
  393. package/dist/hooks/use-supplier-payments.d.ts +27 -0
  394. package/dist/hooks/use-supplier-payments.d.ts.map +1 -0
  395. package/dist/hooks/use-supplier-payments.js +12 -0
  396. package/dist/hooks/use-traveler-profitability.d.ts +24 -0
  397. package/dist/hooks/use-traveler-profitability.d.ts.map +1 -0
  398. package/dist/hooks/use-traveler-profitability.js +11 -0
  399. package/dist/hooks/use-voucher-mutation.d.ts +105 -0
  400. package/dist/hooks/use-voucher-mutation.d.ts.map +1 -0
  401. package/dist/hooks/use-voucher-mutation.js +50 -0
  402. package/dist/hooks/use-voucher.d.ts +38 -0
  403. package/dist/hooks/use-voucher.d.ts.map +1 -0
  404. package/dist/hooks/use-voucher.js +17 -0
  405. package/dist/hooks/use-vouchers.d.ts +34 -0
  406. package/dist/hooks/use-vouchers.d.ts.map +1 -0
  407. package/dist/hooks/use-vouchers.js +18 -0
  408. package/dist/i18n/en/invoices.d.ts +278 -0
  409. package/dist/i18n/en/invoices.d.ts.map +1 -0
  410. package/dist/i18n/en/invoices.js +277 -0
  411. package/dist/i18n/en/numberingAndPayments.d.ts +387 -0
  412. package/dist/i18n/en/numberingAndPayments.d.ts.map +1 -0
  413. package/dist/i18n/en/numberingAndPayments.js +386 -0
  414. package/dist/i18n/en/profitability.d.ts +147 -0
  415. package/dist/i18n/en/profitability.d.ts.map +1 -0
  416. package/dist/i18n/en/profitability.js +146 -0
  417. package/dist/i18n/en/suppliers.d.ts +187 -0
  418. package/dist/i18n/en/suppliers.d.ts.map +1 -0
  419. package/dist/i18n/en/suppliers.js +186 -0
  420. package/dist/i18n/en.d.ts +998 -0
  421. package/dist/i18n/en.d.ts.map +1 -0
  422. package/dist/i18n/en.js +22 -0
  423. package/dist/i18n/index.d.ts +5 -0
  424. package/dist/i18n/index.d.ts.map +1 -0
  425. package/dist/i18n/index.js +3 -0
  426. package/dist/i18n/messages/core.d.ts +18 -0
  427. package/dist/i18n/messages/core.d.ts.map +1 -0
  428. package/dist/i18n/messages/core.js +30 -0
  429. package/dist/i18n/messages/invoices.d.ts +252 -0
  430. package/dist/i18n/messages/invoices.d.ts.map +1 -0
  431. package/dist/i18n/messages/invoices.js +1 -0
  432. package/dist/i18n/messages/numberingAndPayments.d.ts +277 -0
  433. package/dist/i18n/messages/numberingAndPayments.d.ts.map +1 -0
  434. package/dist/i18n/messages/numberingAndPayments.js +1 -0
  435. package/dist/i18n/messages/profitability.d.ts +151 -0
  436. package/dist/i18n/messages/profitability.d.ts.map +1 -0
  437. package/dist/i18n/messages/profitability.js +1 -0
  438. package/dist/i18n/messages/suppliers.d.ts +167 -0
  439. package/dist/i18n/messages/suppliers.d.ts.map +1 -0
  440. package/dist/i18n/messages/suppliers.js +1 -0
  441. package/dist/i18n/messages.d.ts +29 -0
  442. package/dist/i18n/messages.d.ts.map +1 -0
  443. package/dist/i18n/messages.js +1 -0
  444. package/dist/i18n/provider.d.ts +2018 -0
  445. package/dist/i18n/provider.d.ts.map +1 -0
  446. package/dist/i18n/provider.js +44 -0
  447. package/dist/i18n/ro/invoices.d.ts +278 -0
  448. package/dist/i18n/ro/invoices.d.ts.map +1 -0
  449. package/dist/i18n/ro/invoices.js +277 -0
  450. package/dist/i18n/ro/numberingAndPayments.d.ts +387 -0
  451. package/dist/i18n/ro/numberingAndPayments.d.ts.map +1 -0
  452. package/dist/i18n/ro/numberingAndPayments.js +386 -0
  453. package/dist/i18n/ro/profitability.d.ts +147 -0
  454. package/dist/i18n/ro/profitability.d.ts.map +1 -0
  455. package/dist/i18n/ro/profitability.js +146 -0
  456. package/dist/i18n/ro/suppliers.d.ts +187 -0
  457. package/dist/i18n/ro/suppliers.d.ts.map +1 -0
  458. package/dist/i18n/ro/suppliers.js +186 -0
  459. package/dist/i18n/ro.d.ts +998 -0
  460. package/dist/i18n/ro.d.ts.map +1 -0
  461. package/dist/i18n/ro.js +22 -0
  462. package/dist/index.d.ts +11 -0
  463. package/dist/index.d.ts.map +1 -0
  464. package/dist/index.js +9 -0
  465. package/dist/operations.d.ts +484 -0
  466. package/dist/operations.d.ts.map +1 -0
  467. package/dist/operations.js +52 -0
  468. package/dist/provider.d.ts +2 -0
  469. package/dist/provider.d.ts.map +1 -0
  470. package/dist/provider.js +1 -0
  471. package/dist/query-keys.d.ts +195 -0
  472. package/dist/query-keys.d.ts.map +1 -0
  473. package/dist/query-keys.js +49 -0
  474. package/dist/query-options/public-reporting.d.ts +2129 -0
  475. package/dist/query-options/public-reporting.d.ts.map +1 -0
  476. package/dist/query-options/public-reporting.js +193 -0
  477. package/dist/query-options-action-ledger.d.ts +382 -0
  478. package/dist/query-options-action-ledger.d.ts.map +1 -0
  479. package/dist/query-options-action-ledger.js +36 -0
  480. package/dist/query-options.d.ts +2057 -0
  481. package/dist/query-options.d.ts.map +1 -0
  482. package/dist/query-options.js +328 -0
  483. package/dist/schemas/accountant.d.ts +168 -0
  484. package/dist/schemas/accountant.d.ts.map +1 -0
  485. package/dist/schemas/accountant.js +53 -0
  486. package/dist/schemas/action-ledger.d.ts +206 -0
  487. package/dist/schemas/action-ledger.d.ts.map +1 -0
  488. package/dist/schemas/action-ledger.js +83 -0
  489. package/dist/schemas/common.d.ts +17 -0
  490. package/dist/schemas/common.d.ts.map +1 -0
  491. package/dist/schemas/common.js +10 -0
  492. package/dist/schemas/invoice.d.ts +1451 -0
  493. package/dist/schemas/invoice.d.ts.map +1 -0
  494. package/dist/schemas/invoice.js +438 -0
  495. package/dist/schemas/profitability.d.ts +333 -0
  496. package/dist/schemas/profitability.d.ts.map +1 -0
  497. package/dist/schemas/profitability.js +84 -0
  498. package/dist/schemas/public.d.ts +481 -0
  499. package/dist/schemas/public.d.ts.map +1 -0
  500. package/dist/schemas/public.js +9 -0
  501. package/dist/schemas/responses.d.ts +632 -0
  502. package/dist/schemas/responses.d.ts.map +1 -0
  503. package/dist/schemas/responses.js +27 -0
  504. package/dist/schemas/supplier.d.ts +226 -0
  505. package/dist/schemas/supplier.d.ts.map +1 -0
  506. package/dist/schemas/supplier.js +103 -0
  507. package/dist/schemas/vouchers.d.ts +283 -0
  508. package/dist/schemas/vouchers.d.ts.map +1 -0
  509. package/dist/schemas/vouchers.js +49 -0
  510. package/dist/schemas.d.ts +10 -0
  511. package/dist/schemas.d.ts.map +1 -0
  512. package/dist/schemas.js +9 -0
  513. package/dist/ui.d.ts +27 -0
  514. package/dist/ui.d.ts.map +1 -0
  515. package/dist/ui.js +26 -0
  516. package/package.json +181 -0
  517. package/src/styles.css +12 -0
@@ -0,0 +1,63 @@
1
+ import { type BookingPaymentScheduleRecord, type InvoiceRecord } from "../index.js";
2
+ export type InvoiceTypeChoice = "invoice" | "proforma";
3
+ export interface BookingInvoiceDialogUpload {
4
+ storageKey: string;
5
+ mimeType: string;
6
+ fileSize: number;
7
+ }
8
+ export interface BookingInvoiceDueDateResolverInput {
9
+ issueDate: string;
10
+ dueDate: string;
11
+ invoiceType: InvoiceTypeChoice;
12
+ booking: {
13
+ id: string;
14
+ currency: string;
15
+ amountCents: number | null;
16
+ };
17
+ bookingPaymentSchedule: BookingPaymentScheduleRecord;
18
+ }
19
+ export type BookingInvoiceDueDateResolver = (input: BookingInvoiceDueDateResolverInput) => string;
20
+ export interface BookingInvoiceDialogProps {
21
+ open: boolean;
22
+ onOpenChange: (open: boolean) => void;
23
+ bookingId: string;
24
+ /** Pre-fill the currency from the booking's sell currency. */
25
+ defaultCurrency?: string;
26
+ /** Pre-fill subtotal/total from the booking's sell amount (in cents). */
27
+ defaultAmountCents?: number | null;
28
+ /**
29
+ * Upload a file's bytes to durable storage and return its location so
30
+ * the dialog can attach it to the newly-created invoice. When omitted,
31
+ * the attachments dropzone is hidden — the SmartBill-off branch can
32
+ * still create the invoice, it just won't surface uploads. The
33
+ * template owns the upload endpoint (e.g. `/api/v1/uploads`) so the
34
+ * dialog stays transport-agnostic.
35
+ */
36
+ uploadFile?: (file: File) => Promise<BookingInvoiceDialogUpload>;
37
+ /**
38
+ * Tax % to pre-fill on the schedule-derived line item. The operator
39
+ * template resolves this from the booking's primary product (e.g. via
40
+ * `useBookingTaxPreview`) so the dialog mirrors the rate the server
41
+ * would apply server-side at issuance. Defaults to 0 when omitted.
42
+ */
43
+ defaultScheduleTaxRatePercent?: number;
44
+ /**
45
+ * Resolve the legal document due date when an invoice/proforma is
46
+ * derived from a payment schedule. Defaults to the schedule due date
47
+ * for backwards compatibility.
48
+ */
49
+ resolveScheduleDueDate?: BookingInvoiceDueDateResolver;
50
+ onSuccess?: (invoice: InvoiceRecord) => void;
51
+ }
52
+ /**
53
+ * Modal invoice creator scoped to a single booking. Operators can pick
54
+ * between a free-form ("custom") invoice and one derived from an
55
+ * unpaid payment schedule (amounts + due date are locked to the
56
+ * schedule). Toggles control whether the new invoice is pushed to
57
+ * SmartBill on issue, whether a fully-paid `payments` row is created
58
+ * alongside it, and (when sync is off) lets the operator attach
59
+ * supporting documents.
60
+ */
61
+ export declare function BookingInvoiceDialog({ open, onOpenChange, bookingId, defaultCurrency, // i18n-literal-ok domain default currency
62
+ defaultAmountCents, uploadFile, defaultScheduleTaxRatePercent, resolveScheduleDueDate, onSuccess, }: BookingInvoiceDialogProps): import("react/jsx-runtime").JSX.Element;
63
+ //# sourceMappingURL=booking-invoice-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"booking-invoice-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-invoice-dialog.tsx"],"names":[],"mappings":"AA0BA,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,aAAa,EAKnB,MAAM,aAAa,CAAA;AAEpB,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,CAAA;AAWtD,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,kCAAkC;IACjD,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,iBAAiB,CAAA;IAC9B,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAA;QACV,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAC3B,CAAA;IACD,sBAAsB,EAAE,4BAA4B,CAAA;CACrD;AAED,MAAM,MAAM,6BAA6B,GAAG,CAAC,KAAK,EAAE,kCAAkC,KAAK,MAAM,CAAA;AAEjG,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;IAChE;;;;;OAKG;IACH,6BAA6B,CAAC,EAAE,MAAM,CAAA;IACtC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,6BAA6B,CAAA;IACtD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;CAC7C;AAgED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,eAAuB,EAAE,0CAA0C;AACnE,kBAAyB,EACzB,UAAU,EACV,6BAAiC,EACjC,sBAAsB,EACtB,SAAS,GACV,EAAE,yBAAyB,2CAgsB3B"}
@@ -0,0 +1,383 @@
1
+ // agent-quality: file-size exception -- owner: finance-react; existing UI surface stays co-located until a dedicated split preserves behavior and tests.
2
+ "use client";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, Textarea, } from "@voyant-travel/ui/components";
5
+ import { CurrencyCombobox } from "@voyant-travel/ui/components/currency-combobox";
6
+ import { CurrencyInput } from "@voyant-travel/ui/components/currency-input";
7
+ import { DatePicker } from "@voyant-travel/ui/components/date-picker";
8
+ import { Loader2, Paperclip, Plus, X } from "lucide-react";
9
+ import { useCallback, useEffect, useMemo, useState } from "react";
10
+ import { useFinanceUiMessagesOrDefault } from "../i18n/index.js";
11
+ import { useBookingPaymentSchedules, useInvoiceMutation, useVoyantFinanceContext, } from "../index.js";
12
+ function generateInvoiceNumber() {
13
+ const now = new Date();
14
+ const y = now.getFullYear();
15
+ const seq = String(Math.floor(Math.random() * 9000) + 1000);
16
+ return `INV-${y}-${seq}`; // i18n-literal-ok auto-generated id
17
+ }
18
+ function formatScheduleDate(iso, locale) {
19
+ try {
20
+ return new Date(iso).toLocaleDateString(locale, { dateStyle: "medium" });
21
+ }
22
+ catch {
23
+ return iso;
24
+ }
25
+ }
26
+ function formatMoney(cents, currency) {
27
+ try {
28
+ return new Intl.NumberFormat(undefined, { style: "currency", currency }).format(cents / 100);
29
+ }
30
+ catch {
31
+ return `${(cents / 100).toFixed(2)} ${currency}`;
32
+ }
33
+ }
34
+ // Persisted as the invoice's line-item description, which ships with the
35
+ // PDF document itself. Voyant defaults to English at the data layer here;
36
+ // templates that need a Romanian/etc. PDF supply their own description
37
+ // resolver via the upcoming hook surface.
38
+ const SCHEDULE_DESCRIPTION_FALLBACK = {
39
+ // i18n-literal-ok domain default for invoice line items
40
+ deposit: "Deposit",
41
+ // i18n-literal-ok domain default for invoice line items
42
+ installment: "Installment",
43
+ // i18n-literal-ok domain default for invoice line items
44
+ balance: "Balance",
45
+ // i18n-literal-ok domain default for invoice line items
46
+ hold: "Hold",
47
+ // i18n-literal-ok domain default for invoice line items
48
+ other: "Payment",
49
+ };
50
+ function scheduleDescription(scheduleType) {
51
+ // i18n-literal-ok matches SCHEDULE_DESCRIPTION_FALLBACK above
52
+ if (!scheduleType)
53
+ return SCHEDULE_DESCRIPTION_FALLBACK.other ?? "Payment";
54
+ return SCHEDULE_DESCRIPTION_FALLBACK[scheduleType] ?? scheduleType;
55
+ }
56
+ // CurrencyInput requires `onChange` even when disabled; this placeholder
57
+ // keeps the read-only totals row from needing per-call wrappers.
58
+ const noopCurrencyChange = (_value) => { };
59
+ const PAYMENT_METHODS = [
60
+ "bank_transfer",
61
+ "credit_card",
62
+ "debit_card",
63
+ "cash",
64
+ "cheque",
65
+ "wallet",
66
+ "direct_bill",
67
+ "voucher",
68
+ "other",
69
+ ];
70
+ /**
71
+ * Modal invoice creator scoped to a single booking. Operators can pick
72
+ * between a free-form ("custom") invoice and one derived from an
73
+ * unpaid payment schedule (amounts + due date are locked to the
74
+ * schedule). Toggles control whether the new invoice is pushed to
75
+ * SmartBill on issue, whether a fully-paid `payments` row is created
76
+ * alongside it, and (when sync is off) lets the operator attach
77
+ * supporting documents.
78
+ */
79
+ export function BookingInvoiceDialog({ open, onOpenChange, bookingId, defaultCurrency = "EUR", // i18n-literal-ok domain default currency
80
+ defaultAmountCents = null, uploadFile, defaultScheduleTaxRatePercent = 0, resolveScheduleDueDate, onSuccess, }) {
81
+ const { createFromBooking } = useInvoiceMutation();
82
+ const { baseUrl, fetcher } = useVoyantFinanceContext();
83
+ const messages = useFinanceUiMessagesOrDefault();
84
+ const dialog = messages.invoiceDialog;
85
+ const [invoiceType, setInvoiceType] = useState("invoice");
86
+ const [source, setSource] = useState("schedule");
87
+ const [scheduleId, setScheduleId] = useState(null);
88
+ const [invoiceNumber, setInvoiceNumber] = useState("");
89
+ const [currency, setCurrency] = useState(defaultCurrency);
90
+ const [subtotalCents, setSubtotalCents] = useState(defaultAmountCents ?? 0);
91
+ const [taxCents, setTaxCents] = useState(0);
92
+ const [totalCents, setTotalCents] = useState(defaultAmountCents ?? 0);
93
+ const [issueDate, setIssueDate] = useState("");
94
+ const [dueDate, setDueDate] = useState("");
95
+ const [notes, setNotes] = useState("");
96
+ const [lineItems, setLineItems] = useState([]);
97
+ const [syncToSmartbill, setSyncToSmartbill] = useState(true);
98
+ const [markAsPaid, setMarkAsPaid] = useState(false);
99
+ const [markAsPaidMethod, setMarkAsPaidMethod] = useState("bank_transfer");
100
+ const [markAsPaidDate, setMarkAsPaidDate] = useState("");
101
+ const [attachments, setAttachments] = useState([]);
102
+ const [submitting, setSubmitting] = useState(false);
103
+ const [error, setError] = useState(null);
104
+ // ---- prefill / reset on open ---------------------------------------------
105
+ useEffect(() => {
106
+ if (!open)
107
+ return;
108
+ const today = new Date().toISOString().split("T")[0] ?? "";
109
+ setInvoiceType("invoice");
110
+ setSource("schedule");
111
+ setScheduleId(null);
112
+ setInvoiceNumber(generateInvoiceNumber());
113
+ setCurrency(defaultCurrency);
114
+ setSubtotalCents(defaultAmountCents ?? 0);
115
+ setTaxCents(0);
116
+ setTotalCents(defaultAmountCents ?? 0);
117
+ setIssueDate(today);
118
+ setDueDate("");
119
+ setNotes("");
120
+ setLineItems([]);
121
+ setSyncToSmartbill(true);
122
+ setMarkAsPaid(false);
123
+ setMarkAsPaidMethod("bank_transfer");
124
+ setMarkAsPaidDate(today);
125
+ setAttachments([]);
126
+ setSubmitting(false);
127
+ setError(null);
128
+ }, [open, defaultCurrency, defaultAmountCents]);
129
+ // ---- schedules -----------------------------------------------------------
130
+ const schedulesQuery = useBookingPaymentSchedules(bookingId, { enabled: open });
131
+ const unpaidSchedules = useMemo(() => (schedulesQuery.data?.data ?? []).filter((s) => s.status === "pending" || s.status === "due"), [schedulesQuery.data]);
132
+ // When the operator picks a schedule, lock the financial fields to it.
133
+ // `useMemo` keeps the lookup cheap on every render.
134
+ const selectedSchedule = useMemo(() => (scheduleId ? (unpaidSchedules.find((s) => s.id === scheduleId) ?? null) : null), [scheduleId, unpaidSchedules]);
135
+ useEffect(() => {
136
+ if (source !== "schedule") {
137
+ // Leaving the schedule branch — wipe the auto-prefilled line items
138
+ // so the operator's blank "Custom" slate stays blank.
139
+ setLineItems([]);
140
+ return;
141
+ }
142
+ if (!selectedSchedule) {
143
+ setLineItems([]);
144
+ return;
145
+ }
146
+ setCurrency(selectedSchedule.currency);
147
+ // The schedule amount is the gross (customer-facing) sum, so the
148
+ // line item's net unit price is `amount / (1 + tax%)`. Without this
149
+ // back-out the line would compute as `amount + amount * tax%`,
150
+ // making the invoice exceed what the customer is actually paying.
151
+ const taxFactor = 1 + Math.max(0, defaultScheduleTaxRatePercent) / 100;
152
+ const netUnitAmount = taxFactor > 0
153
+ ? Math.round(selectedSchedule.amountCents / taxFactor)
154
+ : selectedSchedule.amountCents;
155
+ setLineItems([
156
+ {
157
+ id: `schedule_${selectedSchedule.id}`,
158
+ description: scheduleDescription(selectedSchedule.scheduleType),
159
+ quantity: 1,
160
+ unitAmountCents: netUnitAmount,
161
+ taxRatePercent: defaultScheduleTaxRatePercent,
162
+ },
163
+ ]);
164
+ }, [source, selectedSchedule, defaultScheduleTaxRatePercent]);
165
+ useEffect(() => {
166
+ if (source !== "schedule" || !selectedSchedule)
167
+ return;
168
+ setDueDate(resolveScheduleDueDate?.({
169
+ issueDate,
170
+ dueDate: selectedSchedule.dueDate,
171
+ invoiceType,
172
+ booking: {
173
+ id: bookingId,
174
+ currency: defaultCurrency,
175
+ amountCents: defaultAmountCents,
176
+ },
177
+ bookingPaymentSchedule: selectedSchedule,
178
+ }) ?? selectedSchedule.dueDate);
179
+ }, [
180
+ source,
181
+ selectedSchedule,
182
+ resolveScheduleDueDate,
183
+ issueDate,
184
+ invoiceType,
185
+ bookingId,
186
+ defaultCurrency,
187
+ defaultAmountCents,
188
+ ]);
189
+ // ---- line item totals ----------------------------------------------------
190
+ // When the operator entered explicit line items, the global Subtotal/Tax/
191
+ // Total fields become a read-only summary of the sum across rows.
192
+ const lineItemTotals = useMemo(() => {
193
+ let subtotal = 0;
194
+ let tax = 0;
195
+ for (const line of lineItems) {
196
+ const lineSubtotal = Math.max(0, Math.round(line.quantity * line.unitAmountCents));
197
+ const lineTax = Math.max(0, Math.round((lineSubtotal * line.taxRatePercent) / 100));
198
+ subtotal += lineSubtotal;
199
+ tax += lineTax;
200
+ }
201
+ return { subtotalCents: subtotal, taxCents: tax, totalCents: subtotal + tax };
202
+ }, [lineItems]);
203
+ // Subtotal/Tax/Total are always derived from the line items, so reflect
204
+ // the latest computation on every render (including the empty → 0 case).
205
+ useEffect(() => {
206
+ setSubtotalCents(lineItemTotals.subtotalCents);
207
+ setTaxCents(lineItemTotals.taxCents);
208
+ setTotalCents(lineItemTotals.totalCents);
209
+ }, [lineItemTotals]);
210
+ const scheduleLocked = source === "schedule" && selectedSchedule != null;
211
+ const linesDriveTotals = source === "custom" && lineItems.length > 0;
212
+ // ---- submit --------------------------------------------------------------
213
+ const submit = useCallback(async () => {
214
+ if (submitting)
215
+ return;
216
+ setError(null);
217
+ if (source === "schedule" && !selectedSchedule) {
218
+ setError(dialog.schedulePlaceholder);
219
+ return;
220
+ }
221
+ if (!issueDate) {
222
+ setError(dialog.validation.issueDateRequired);
223
+ return;
224
+ }
225
+ if (!dueDate) {
226
+ setError(dialog.validation.dueDateRequired);
227
+ return;
228
+ }
229
+ if (linesDriveTotals) {
230
+ const invalid = lineItems.find((line) => !line.description.trim() || line.quantity < 1);
231
+ if (invalid) {
232
+ setError(dialog.validation.lineItemInvalid);
233
+ return;
234
+ }
235
+ }
236
+ setSubmitting(true);
237
+ try {
238
+ // Subtotal/Tax/Total are intentionally omitted — the server
239
+ // computes them from `lineItems` (custom mode) or from the linked
240
+ // schedule (schedule mode). Sending the locally-derived numbers
241
+ // can drift by 1 cent due to rounding and trips the strict
242
+ // "Invoice tax does not match line items" cross-check.
243
+ const created = await createFromBooking.mutateAsync({
244
+ bookingId,
245
+ bookingPaymentScheduleId: selectedSchedule?.id,
246
+ invoiceNumber,
247
+ issueDate,
248
+ dueDate,
249
+ currency,
250
+ notes: notes || null,
251
+ invoiceType,
252
+ skipExternalSync: !syncToSmartbill,
253
+ lineItems: linesDriveTotals
254
+ ? lineItems.map((line) => ({
255
+ description: line.description.trim(),
256
+ quantity: line.quantity,
257
+ unitAmountCents: line.unitAmountCents,
258
+ taxRateBps: line.taxRatePercent > 0 ? Math.round(line.taxRatePercent * 100) : undefined,
259
+ }))
260
+ : undefined,
261
+ });
262
+ // Fully-paid sibling payment row. Use the totals returned by the
263
+ // server (which may differ from the locally-derived ones by a cent
264
+ // due to schedule tax back-out / rounding) — paying the local
265
+ // figure can leave the invoice short and break the one-click
266
+ // "Mark as paid" expectation (incl. proforma conversion triggers).
267
+ if (markAsPaid && created.totalCents > 0) {
268
+ const paymentDate = markAsPaidDate || new Date().toISOString().split("T")[0] || issueDate;
269
+ await fetcher(`${baseUrl}/v1/admin/finance/invoices/${created.id}/payments`, {
270
+ method: "POST",
271
+ headers: { "Content-Type": "application/json" },
272
+ body: JSON.stringify({
273
+ amountCents: created.totalCents,
274
+ currency: created.currency,
275
+ paymentMethod: markAsPaidMethod,
276
+ status: "completed",
277
+ paymentDate,
278
+ }),
279
+ });
280
+ }
281
+ // Attachments: upload bytes via the template-supplied uploader,
282
+ // then register each as an `invoice_attachment` row pointing at
283
+ // the storage key returned by the upload.
284
+ if (uploadFile && attachments.length > 0) {
285
+ for (const file of attachments) {
286
+ const uploaded = await uploadFile(file);
287
+ await fetcher(`${baseUrl}/v1/admin/finance/invoices/${created.id}/attachments`, {
288
+ method: "POST",
289
+ headers: { "Content-Type": "application/json" },
290
+ body: JSON.stringify({
291
+ kind: "supporting_document",
292
+ name: file.name,
293
+ mimeType: uploaded.mimeType || file.type || null,
294
+ fileSize: uploaded.fileSize ?? file.size,
295
+ storageKey: uploaded.storageKey,
296
+ }),
297
+ });
298
+ }
299
+ }
300
+ onSuccess?.(created);
301
+ onOpenChange(false);
302
+ }
303
+ catch (err) {
304
+ setError(err instanceof Error ? err.message : String(err));
305
+ }
306
+ finally {
307
+ setSubmitting(false);
308
+ }
309
+ }, [
310
+ submitting,
311
+ source,
312
+ selectedSchedule,
313
+ issueDate,
314
+ dueDate,
315
+ createFromBooking,
316
+ bookingId,
317
+ invoiceNumber,
318
+ currency,
319
+ notes,
320
+ invoiceType,
321
+ syncToSmartbill,
322
+ markAsPaid,
323
+ markAsPaidMethod,
324
+ markAsPaidDate,
325
+ attachments,
326
+ uploadFile,
327
+ baseUrl,
328
+ fetcher,
329
+ onSuccess,
330
+ onOpenChange,
331
+ linesDriveTotals,
332
+ lineItems,
333
+ dialog,
334
+ ]);
335
+ // ---- render --------------------------------------------------------------
336
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "w-full! max-w-3xl! gap-0 p-0", children: [_jsxs(DialogHeader, { className: "shrink-0 border-b px-6 py-4", children: [_jsx(DialogTitle, { children: dialog.titles.create }), _jsx(DialogDescription, { children: messages.invoicesPage.description })] }), _jsx("div", { className: "max-h-[70vh] overflow-y-auto", children: _jsxs("div", { className: "flex flex-col gap-4 px-6 py-5", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.type }), _jsx(SegmentedChoice, { value: invoiceType, onChange: setInvoiceType, options: [
337
+ { value: "invoice", label: dialog.typeLabels.invoice },
338
+ { value: "proforma", label: dialog.typeLabels.proforma },
339
+ ] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.source }), _jsx(SegmentedChoice, { value: source, onChange: (next) => {
340
+ setSource(next);
341
+ if (next === "custom")
342
+ setScheduleId(null);
343
+ }, options: [
344
+ { value: "schedule", label: dialog.sourceLabels.schedule },
345
+ { value: "custom", label: dialog.sourceLabels.custom },
346
+ ] })] }), _jsxs("div", { className: "flex items-center justify-between gap-3 rounded-md border bg-muted/20 px-4 py-3", children: [_jsx(Label, { className: "cursor-pointer", onClick: () => setSyncToSmartbill((v) => !v), children: dialog.fields.syncToSmartbill }), _jsx(Switch, { checked: syncToSmartbill, onCheckedChange: setSyncToSmartbill })] }), source === "schedule" ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.schedule }), _jsxs(Select, { value: scheduleId ?? undefined, onValueChange: (v) => setScheduleId(v ?? null), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, { placeholder: dialog.schedulePlaceholder }) }), _jsx(SelectContent, { children: unpaidSchedules.length === 0 ? (_jsx("div", { className: "px-3 py-2 text-sm text-muted-foreground", children: dialog.scheduleEmpty })) : (unpaidSchedules.map((s) => (_jsxs(SelectItem, { value: s.id, children: [formatScheduleDate(s.dueDate, undefined), " \u00B7", " ", formatMoney(s.amountCents, s.currency)] }, s.id)))) })] }), scheduleLocked ? (_jsx("p", { className: "text-xs text-muted-foreground", children: dialog.scheduleLockedHint })) : null] })) : null, _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.invoiceNumber }), _jsx(Input, { value: invoiceNumber, onChange: (e) => setInvoiceNumber(e.target.value), placeholder: dialog.placeholders.invoiceNumber, disabled: syncToSmartbill }), syncToSmartbill ? (_jsx("p", { className: "text-xs text-muted-foreground", children: dialog.invoiceNumberAutoHint })) : null] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.currency }), _jsx(CurrencyCombobox, { value: currency, onChange: (next) => setCurrency(next ?? defaultCurrency), disabled: scheduleLocked })] })] }), source === "custom" || lineItems.length > 0 ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { children: dialog.lineItems.sectionTitle }), source === "custom" ? (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setLineItems((prev) => [
347
+ ...prev,
348
+ {
349
+ id: `tmp_${Date.now()}_${prev.length}`,
350
+ description: "",
351
+ quantity: 1,
352
+ unitAmountCents: 0,
353
+ taxRatePercent: 0,
354
+ },
355
+ ]), children: [_jsx(Plus, { className: "mr-1 h-3.5 w-3.5" }), dialog.lineItems.addRow] })) : null] }), lineItems.length === 0 ? (_jsx("p", { className: "text-xs text-muted-foreground", children: dialog.lineItems.empty })) : (_jsx("div", { className: "flex flex-col gap-2", children: lineItems.map((line, idx) => {
356
+ const lineSubtotal = Math.max(0, Math.round(line.quantity * line.unitAmountCents));
357
+ const lineTotal = lineSubtotal +
358
+ Math.max(0, Math.round((lineSubtotal * line.taxRatePercent) / 100));
359
+ return (_jsxs("div", { className: "grid grid-cols-[1fr_3rem_7rem_4rem_6rem_2rem] items-end gap-2 rounded-md border bg-background p-2", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [idx === 0 ? (_jsx(Label, { className: "text-xs", children: dialog.lineItems.description })) : null, _jsx(Input, { value: line.description, onChange: (e) => setLineItems((prev) => prev.map((row, i) => i === idx ? { ...row, description: e.target.value } : row)), disabled: scheduleLocked })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [idx === 0 ? (_jsx(Label, { className: "text-xs", children: dialog.lineItems.quantity })) : null, _jsx(Input, { type: "number", min: 1, value: line.quantity, onChange: (e) => setLineItems((prev) => prev.map((row, i) => i === idx
360
+ ? {
361
+ ...row,
362
+ quantity: Math.max(1, Number(e.target.value) || 1),
363
+ }
364
+ : row)), disabled: scheduleLocked })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [idx === 0 ? (_jsx(Label, { className: "text-xs", children: dialog.lineItems.unitPrice })) : null, _jsx(CurrencyInput, { value: line.unitAmountCents, onChange: (next) => setLineItems((prev) => prev.map((row, i) => i === idx ? { ...row, unitAmountCents: next ?? 0 } : row)), currency: currency, disabled: scheduleLocked })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [idx === 0 ? (_jsx(Label, { className: "text-xs", children: dialog.lineItems.taxPercent })) : null, _jsx(Input, { type: "number", min: 0, max: 100, step: 0.01, value: line.taxRatePercent, onChange: (e) => setLineItems((prev) => prev.map((row, i) => i === idx
365
+ ? {
366
+ ...row,
367
+ taxRatePercent: Math.max(0, Math.min(100, Number(e.target.value) || 0)),
368
+ }
369
+ : row)), disabled: scheduleLocked })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [idx === 0 ? (_jsx(Label, { className: "text-xs", children: dialog.lineItems.lineTotal })) : null, _jsx("div", { className: "px-2 py-1.5 text-right font-mono text-sm", children: formatMoney(lineTotal, currency) })] }), scheduleLocked ? (_jsx("div", {})) : (_jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": dialog.lineItems.remove, onClick: () => setLineItems((prev) => prev.filter((_, i) => i !== idx)), children: _jsx(X, { className: "h-3.5 w-3.5" }) }))] }, line.id));
370
+ }) }))] })) : null, _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.subtotalCents }), _jsx(CurrencyInput, { value: subtotalCents, onChange: noopCurrencyChange, currency: currency, disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.taxCents }), _jsx(CurrencyInput, { value: taxCents, onChange: noopCurrencyChange, currency: currency, disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.totalCents }), _jsx(CurrencyInput, { value: totalCents, onChange: noopCurrencyChange, currency: currency, disabled: true })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.issueDate }), _jsx(DatePicker, { value: issueDate || null, onChange: (next) => setIssueDate(next ?? ""), placeholder: dialog.placeholders.issueDate, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.dueDate }), _jsx(DatePicker, { value: dueDate || null, onChange: (next) => setDueDate(next ?? ""), placeholder: dialog.placeholders.dueDate, className: "w-full", disabled: scheduleLocked })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.notes }), _jsx(Textarea, { value: notes, onChange: (e) => setNotes(e.target.value), placeholder: dialog.placeholders.notes })] }), _jsxs("div", { className: "flex flex-col gap-3 rounded-md border bg-muted/20 px-4 py-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(Label, { className: "cursor-pointer", onClick: () => setMarkAsPaid((v) => !v), children: dialog.fields.markAsPaid }), _jsx(Switch, { checked: markAsPaid, onCheckedChange: setMarkAsPaid })] }), markAsPaid ? (_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.markAsPaidMethod }), _jsxs(Select, { value: markAsPaidMethod, onValueChange: (v) => setMarkAsPaidMethod((v ?? "bank_transfer")), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: PAYMENT_METHODS.map((method) => (_jsx(SelectItem, { value: method, children: messages.common.paymentMethodLabels[method] }, method))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.markAsPaidDate }), _jsx(DatePicker, { value: markAsPaidDate || null, onChange: (next) => setMarkAsPaidDate(next ?? ""), placeholder: dialog.placeholders.issueDate, className: "w-full" })] })] })) : null] }), !syncToSmartbill && uploadFile ? (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: dialog.fields.attachments }), _jsx("p", { className: "text-xs text-muted-foreground", children: dialog.attachmentsHint }), _jsx("input", { type: "file", multiple: true, onChange: (e) => {
371
+ const files = Array.from(e.target.files ?? []);
372
+ if (files.length > 0)
373
+ setAttachments((prev) => [...prev, ...files]);
374
+ e.target.value = "";
375
+ }, className: "block w-full text-sm file:mr-3 file:rounded-md file:border file:bg-muted file:px-3 file:py-1.5 file:text-sm file:font-medium hover:file:bg-muted/70" }), attachments.length > 0 ? (_jsx("ul", { className: "flex flex-col gap-1", children: attachments.map((file, idx) => (_jsxs("li", { className: "flex items-center justify-between gap-2 rounded-md border bg-background px-3 py-1.5 text-sm", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx(Paperclip, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "truncate", children: file.name })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => setAttachments((prev) => prev.filter((_, i) => i !== idx)), children: _jsx(X, { className: "h-3.5 w-3.5" }) })] }, `${file.name}-${idx}`))) })) : null] })) : null, error ? _jsx("p", { className: "text-sm text-destructive", children: error }) : null] }) }), _jsxs("div", { className: "flex shrink-0 items-center justify-end gap-2 border-t px-6 py-4", children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: submitting, children: messages.common.cancel }), _jsxs(Button, { type: "button", disabled: submitting, onClick: () => void submit(), children: [submitting ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, dialog.actions.create] })] })] }) }));
376
+ }
377
+ function SegmentedChoice({ value, onChange, options, }) {
378
+ return (_jsx("div", { className: "flex w-full rounded-md border bg-background p-0.5", children: options.map((opt) => {
379
+ const active = opt.value === value;
380
+ return (_jsx("button", { type: "button", onClick: () => onChange(opt.value), className: "flex-1 rounded-sm px-3 py-1.5 text-sm font-medium transition-colors " +
381
+ (active ? "bg-muted text-foreground" : "text-muted-foreground hover:text-foreground"), children: opt.label }, opt.value));
382
+ }) }));
383
+ }
@@ -0,0 +1,5 @@
1
+ export interface CostCategoriesPageProps {
2
+ className?: string;
3
+ }
4
+ export declare function CostCategoriesPage({ className }?: CostCategoriesPageProps): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=cost-categories-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-categories-page.d.ts","sourceRoot":"","sources":["../../src/components/cost-categories-page.tsx"],"names":[],"mappings":"AAiBA,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAE,uBAA4B,2CA8F7E"}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Badge, Button, Checkbox, Input, Label } from "@voyant-travel/ui/components";
4
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@voyant-travel/ui/components/table";
5
+ import { cn } from "@voyant-travel/ui/lib/utils";
6
+ import { Plus } from "lucide-react";
7
+ import { useState } from "react";
8
+ import { useFinanceUiMessagesOrDefault } from "../i18n/index.js";
9
+ import { useCostCategories, useCostCategoryMutation } from "../index.js";
10
+ export function CostCategoriesPage({ className } = {}) {
11
+ const t = useFinanceUiMessagesOrDefault().costCategories;
12
+ const [showArchived, setShowArchived] = useState(false);
13
+ const [name, setName] = useState("");
14
+ const categories = useCostCategories({ includeArchived: showArchived });
15
+ const { create, update } = useCostCategoryMutation();
16
+ const rows = categories.data?.data ?? [];
17
+ const add = () => {
18
+ const trimmed = name.trim();
19
+ if (!trimmed)
20
+ return;
21
+ create.mutate({ name: trimmed }, { onSuccess: () => setName("") });
22
+ };
23
+ return (_jsxs("div", { className: cn("flex flex-col gap-6 p-6", className), children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: t.title }), _jsx("p", { className: "text-sm text-muted-foreground", children: t.description })] }), _jsxs("div", { className: "flex max-w-md items-end gap-2", children: [_jsx(Input, { placeholder: t.namePlaceholder, value: name, onChange: (e) => setName(e.target.value), onKeyDown: (e) => {
24
+ if (e.key === "Enter")
25
+ add();
26
+ } }), _jsxs(Button, { onClick: add, disabled: create.isPending || !name.trim(), children: [_jsx(Plus, { className: "size-4" }), create.isPending ? t.adding : t.add] })] }), _jsxs(Label, { className: "flex items-center gap-2 text-sm font-normal text-muted-foreground", children: [_jsx(Checkbox, { checked: showArchived, onCheckedChange: (checked) => setShowArchived(checked === true) }), t.showArchived] }), _jsx("div", { className: "max-w-2xl rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t.namePlaceholder }), _jsx(TableHead, { className: "w-32 text-right" })] }) }), _jsx(TableBody, { children: rows.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 2, className: "text-center text-muted-foreground", children: t.empty }) })) : (rows.map((category) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { className: "font-medium", children: [category.name, category.archived ? (_jsx(Badge, { variant: "outline", className: "ml-2", children: t.archivedBadge })) : null] }), _jsx(TableCell, { className: "text-right", children: _jsx(Button, { variant: "ghost", size: "sm", disabled: update.isPending, onClick: () => update.mutate({
27
+ id: category.id,
28
+ input: { archived: !category.archived },
29
+ }), children: category.archived ? t.restore : t.archive }) })] }, category.id)))) })] }) })] }));
30
+ }
@@ -0,0 +1,15 @@
1
+ export interface InvoiceActionLedgerCardProps {
2
+ invoiceId: string;
3
+ limit?: number;
4
+ className?: string;
5
+ }
6
+ export declare function InvoiceActionLedgerCard({ invoiceId, limit, className, }: InvoiceActionLedgerCardProps): import("react/jsx-runtime").JSX.Element;
7
+ export interface PaymentSessionActionLedgerCardProps {
8
+ paymentSessionId: string;
9
+ limit?: number;
10
+ className?: string;
11
+ }
12
+ export declare function PaymentSessionActionLedgerCard({ paymentSessionId, limit, className, }: PaymentSessionActionLedgerCardProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare const actionLedgerStatusVariant: Record<string, "default" | "secondary" | "outline" | "destructive">;
14
+ export declare const actionLedgerRiskVariant: Record<string, "default" | "secondary" | "outline" | "destructive">;
15
+ //# sourceMappingURL=invoice-action-ledger-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-action-ledger-card.d.ts","sourceRoot":"","sources":["../../src/components/invoice-action-ledger-card.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,KAAU,EACV,SAAS,GACV,EAAE,4BAA4B,2CAoB9B;AAED,MAAM,WAAW,mCAAmC;IAClD,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,8BAA8B,CAAC,EAC7C,gBAAgB,EAChB,KAAU,EACV,SAAS,GACV,EAAE,mCAAmC,2CAoBrC;AA4JD,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAC5C,MAAM,EACN,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAapD,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAC1C,MAAM,EACN,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAMpD,CAAA"}
@@ -0,0 +1,76 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Badge, Button } from "@voyant-travel/ui/components";
4
+ import { cn } from "@voyant-travel/ui/lib/utils";
5
+ import { Activity, Loader2 } from "lucide-react";
6
+ import { useEffect, useState } from "react";
7
+ import { useFinanceUiI18nOrDefault, useFinanceUiMessagesOrDefault } from "../i18n/index.js";
8
+ import { useInvoiceActionLedger, usePaymentSessionActionLedger } from "../index.js";
9
+ export function InvoiceActionLedgerCard({ invoiceId, limit = 20, className, }) {
10
+ const messages = useFinanceUiMessagesOrDefault();
11
+ const detail = messages.invoiceDetailPage;
12
+ const [cursor, setCursor] = useState(null);
13
+ const actionLedgerQuery = useInvoiceActionLedger(invoiceId, { cursor, limit });
14
+ return (_jsx(FinanceActionLedgerCard, { dataSlot: "invoice-action-ledger-card", title: detail.titles.actionLedger, loadOlderLabel: detail.actions.loadOlderActionLedger, emptyLabel: detail.states.noActionLedger, loadFailedLabel: detail.states.actionLedgerLoadFailed, className: className, cursor: cursor, setCursor: setCursor, query: actionLedgerQuery }));
15
+ }
16
+ export function PaymentSessionActionLedgerCard({ paymentSessionId, limit = 20, className, }) {
17
+ const messages = useFinanceUiMessagesOrDefault();
18
+ const detail = messages.invoiceDetailPage;
19
+ const [cursor, setCursor] = useState(null);
20
+ const actionLedgerQuery = usePaymentSessionActionLedger(paymentSessionId, { cursor, limit });
21
+ return (_jsx(FinanceActionLedgerCard, { dataSlot: "payment-session-action-ledger-card", title: detail.titles.actionLedger, loadOlderLabel: detail.actions.loadOlderActionLedger, emptyLabel: detail.states.noActionLedger, loadFailedLabel: detail.states.actionLedgerLoadFailed, className: className, cursor: cursor, setCursor: setCursor, query: actionLedgerQuery }));
22
+ }
23
+ function FinanceActionLedgerCard({ dataSlot, title, loadOlderLabel, emptyLabel, loadFailedLabel, className, cursor, setCursor, query, }) {
24
+ const { formatDateTime } = useFinanceUiI18nOrDefault();
25
+ const [pages, setPages] = useState([]);
26
+ useEffect(() => {
27
+ const page = query.data;
28
+ if (!page)
29
+ return;
30
+ setPages((currentPages) => {
31
+ if (currentPages.some((currentPage) => currentPage.data[0]?.id === page.data[0]?.id)) {
32
+ return currentPages;
33
+ }
34
+ return cursor ? [...currentPages, page] : [page];
35
+ });
36
+ }, [query.data, cursor]);
37
+ const entries = pages.flatMap((page) => page.data);
38
+ const nextCursor = pages.at(-1)?.pageInfo.nextCursor ?? null;
39
+ return (_jsx(ActionLedgerSection, { dataSlot: dataSlot, title: title, className: className, children: query.isPending && entries.length === 0 ? (_jsx(ActionLedgerLoadingRow, {})) : query.isError && entries.length === 0 ? (_jsx(ActionLedgerEmptyRow, { children: loadFailedLabel })) : entries.length === 0 ? (_jsx(ActionLedgerEmptyRow, { children: emptyLabel })) : (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsx("ul", { className: "divide-y rounded-md border bg-background", children: entries.map((entry) => (_jsx(InvoiceActionLedgerEntryItem, { entry: entry, timestamp: formatDateTime(entry.occurredAt) }, entry.id))) }), nextCursor ? (_jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "self-start", disabled: query.isFetching, onClick: () => setCursor(nextCursor), children: [query.isFetching ? (_jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": "true" })) : null, loadOlderLabel] })) : null] })) }));
40
+ }
41
+ function InvoiceActionLedgerEntryItem({ entry, timestamp, }) {
42
+ return (_jsxs("li", { className: "flex items-start gap-3 p-3", children: [_jsx(Activity, { className: "mt-0.5 size-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("p", { className: "truncate font-medium text-sm", children: formatActionLedgerName(entry.actionName) }), _jsx(Badge, { variant: actionLedgerStatusVariant[entry.status] ?? "secondary", children: entry.status.replace(/_/g, " ") }), _jsx(Badge, { variant: actionLedgerRiskVariant[entry.evaluatedRisk] ?? "outline", children: entry.evaluatedRisk })] }), _jsxs("p", { className: "mt-1 text-muted-foreground text-xs", children: [entry.principalType, ":", entry.principalId, " - ", timestamp] }), entry.mutationSummary ? (_jsx("p", { className: "mt-1 truncate text-muted-foreground text-xs", children: entry.mutationSummary })) : null, _jsxs("p", { className: "mt-1 truncate font-mono text-muted-foreground text-xs", children: [entry.targetType, ":", entry.targetId] })] })] }));
43
+ }
44
+ function ActionLedgerSection({ dataSlot, title, children, className, }) {
45
+ return (_jsxs("section", { "data-slot": dataSlot, className: cn("rounded-md border bg-background", className), children: [_jsx("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b px-4 py-3", children: _jsx("h2", { className: "font-semibold text-sm", children: title }) }), _jsx("div", { className: "p-4", children: children })] }));
46
+ }
47
+ function ActionLedgerEmptyRow({ children }) {
48
+ return _jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: children });
49
+ }
50
+ function ActionLedgerLoadingRow() {
51
+ return (_jsx("div", { className: "flex justify-center py-6", children: _jsx(Loader2, { className: "size-5 animate-spin text-muted-foreground" }) }));
52
+ }
53
+ function formatActionLedgerName(actionName) {
54
+ const withoutDomain = actionName.replace(/^finance\./, "");
55
+ const label = withoutDomain.replace(/[._-]/g, " ");
56
+ return label.charAt(0).toUpperCase() + label.slice(1);
57
+ }
58
+ export const actionLedgerStatusVariant = {
59
+ requested: "outline",
60
+ awaiting_approval: "secondary",
61
+ approved: "secondary",
62
+ denied: "destructive",
63
+ succeeded: "default",
64
+ failed: "destructive",
65
+ reversed: "secondary",
66
+ compensated: "secondary",
67
+ expired: "secondary",
68
+ cancelled: "secondary",
69
+ superseded: "secondary",
70
+ };
71
+ export const actionLedgerRiskVariant = {
72
+ low: "outline",
73
+ medium: "secondary",
74
+ high: "destructive",
75
+ critical: "destructive",
76
+ };
@@ -0,0 +1,10 @@
1
+ import type { InvoiceBulkStatusResult } from "../index.js";
2
+ export interface InvoiceBulkActionsProps {
3
+ selectedCount: number;
4
+ result: InvoiceBulkStatusResult | null;
5
+ pending: boolean;
6
+ onClear: () => void;
7
+ onMarkPaid: () => unknown;
8
+ }
9
+ export declare function InvoiceBulkActions({ selectedCount, result, pending, onClear, onMarkPaid, }: InvoiceBulkActionsProps): import("react/jsx-runtime").JSX.Element;
10
+ //# sourceMappingURL=invoice-bulk-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoice-bulk-actions.d.ts","sourceRoot":"","sources":["../../src/components/invoice-bulk-actions.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE1D,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAAA;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,OAAO,CAAA;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,aAAa,EACb,MAAM,EACN,OAAO,EACP,OAAO,EACP,UAAU,GACX,EAAE,uBAAuB,2CAkDzB"}