@wealthx/shadcn 1.4.1 → 1.5.0

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 (430) hide show
  1. package/.turbo/turbo-build.log +360 -180
  2. package/CHANGELOG.md +6 -0
  3. package/dist/chunk-2A53WPEC.mjs +182 -0
  4. package/dist/{chunk-SIVYAI3M.mjs → chunk-2LLFNGJZ.mjs} +15 -15
  5. package/dist/chunk-2QNOPXMQ.mjs +360 -0
  6. package/dist/{chunk-K5QV4TT6.mjs → chunk-2WCIORP7.mjs} +29 -4
  7. package/dist/{chunk-5NF6T2RS.mjs → chunk-3AREQTZU.mjs} +8 -8
  8. package/dist/{chunk-2EM2FRU6.mjs → chunk-3WGFIFP6.mjs} +5 -5
  9. package/dist/{chunk-K4KOD3KR.mjs → chunk-42NEC57Y.mjs} +44 -25
  10. package/dist/{chunk-FL6DZFJK.mjs → chunk-46Q4335I.mjs} +121 -39
  11. package/dist/chunk-4DO3WM7V.mjs +48 -0
  12. package/dist/chunk-5FHBC6DY.mjs +68 -0
  13. package/dist/chunk-5SAYZ4CI.mjs +40 -0
  14. package/dist/chunk-5WMFKQZ6.mjs +180 -0
  15. package/dist/chunk-623YVI5O.mjs +43 -0
  16. package/dist/{chunk-SFH2NJEJ.mjs → chunk-6OSULDEO.mjs} +3 -3
  17. package/dist/{chunk-UALR6JGV.mjs → chunk-6SR4K5T5.mjs} +1 -1
  18. package/dist/{chunk-D2NSIIXG.mjs → chunk-7KT5HPYM.mjs} +11 -11
  19. package/dist/chunk-A6ER36CW.mjs +456 -0
  20. package/dist/{chunk-QX7IFQSF.mjs → chunk-AHKHVBWR.mjs} +4 -4
  21. package/dist/chunk-AHSCWXYJ.mjs +113 -0
  22. package/dist/{chunk-7GWRPXHD.mjs → chunk-AL6GOL2Y.mjs} +1 -1
  23. package/dist/{chunk-OIKBW2QD.mjs → chunk-AUEUTZIC.mjs} +13 -13
  24. package/dist/{chunk-FYPSTTEJ.mjs → chunk-B7DD3ODQ.mjs} +1 -1
  25. package/dist/{chunk-TLAWKTSA.mjs → chunk-BD3DWDT4.mjs} +3 -3
  26. package/dist/{chunk-S2FKV4M5.mjs → chunk-BDESHD25.mjs} +4 -4
  27. package/dist/{chunk-OKTJFDPN.mjs → chunk-BFB3UH7V.mjs} +2 -2
  28. package/dist/{chunk-DGNHGNYH.mjs → chunk-C6SWS7OW.mjs} +1 -1
  29. package/dist/chunk-CDVG7SFT.mjs +271 -0
  30. package/dist/chunk-CUSHAIUL.mjs +109 -0
  31. package/dist/{chunk-QXKGOMUX.mjs → chunk-CW32WTZU.mjs} +4 -4
  32. package/dist/{chunk-SET2ANTY.mjs → chunk-D447W45Z.mjs} +3 -3
  33. package/dist/{chunk-RCAOCHWA.mjs → chunk-DFL5CV75.mjs} +18 -18
  34. package/dist/chunk-DYSVJ473.mjs +162 -0
  35. package/dist/chunk-E3PQDBYI.mjs +288 -0
  36. package/dist/chunk-EMYBNPIA.mjs +83 -0
  37. package/dist/chunk-EUYPMDQG.mjs +348 -0
  38. package/dist/{chunk-XYPW2XA5.mjs → chunk-EW72FINW.mjs} +11 -11
  39. package/dist/chunk-F24U4QQQ.mjs +234 -0
  40. package/dist/{chunk-VB5M6OZQ.mjs → chunk-F4O2YPXJ.mjs} +1 -1
  41. package/dist/chunk-FFXTQTB4.mjs +84 -0
  42. package/dist/{chunk-ZOWL2L5J.mjs → chunk-FYUSF5KO.mjs} +5 -1
  43. package/dist/{chunk-FTPBQVQ6.mjs → chunk-GNER6MCO.mjs} +1 -1
  44. package/dist/{chunk-2D3HQPFN.mjs → chunk-HF4FUBCY.mjs} +5 -5
  45. package/dist/{chunk-RSUIPKGX.mjs → chunk-HNDTLT5X.mjs} +1 -1
  46. package/dist/{chunk-N6Q5IPKT.mjs → chunk-HO6S3ECM.mjs} +46 -18
  47. package/dist/{chunk-L4NSRQ3T.mjs → chunk-HROG643K.mjs} +1 -1
  48. package/dist/chunk-I2EKKSEF.mjs +148 -0
  49. package/dist/{chunk-QTRSCVQ3.mjs → chunk-I3UDLWQ7.mjs} +1 -1
  50. package/dist/{chunk-AE7MASLF.mjs → chunk-IQGKOT7A.mjs} +9 -6
  51. package/dist/chunk-IXR4BQSQ.mjs +290 -0
  52. package/dist/{chunk-4MM7LHM5.mjs → chunk-J5NW5NCT.mjs} +1 -1
  53. package/dist/{chunk-OLKMCXAR.mjs → chunk-JTG5R5YV.mjs} +24 -24
  54. package/dist/chunk-JUBUN65Q.mjs +106 -0
  55. package/dist/chunk-K7TWMLLW.mjs +520 -0
  56. package/dist/{chunk-BOW7U26Y.mjs → chunk-K7WSRWOU.mjs} +4 -4
  57. package/dist/{chunk-NTYQWVLI.mjs → chunk-KAD26MCC.mjs} +1 -1
  58. package/dist/{chunk-KCWNDYPZ.mjs → chunk-KB7MZMED.mjs} +4 -4
  59. package/dist/chunk-KCKYGQVQ.mjs +61 -0
  60. package/dist/{chunk-VY5NEUP7.mjs → chunk-KLJLDNCA.mjs} +1 -1
  61. package/dist/chunk-LLAGF6BA.mjs +49 -0
  62. package/dist/{chunk-G27TSQLQ.mjs → chunk-M4LTX3MH.mjs} +1 -1
  63. package/dist/{chunk-YIZHS72Z.mjs → chunk-MHHA7QGO.mjs} +94 -54
  64. package/dist/{chunk-P2N2PEFY.mjs → chunk-NCUH54IZ.mjs} +4 -4
  65. package/dist/{chunk-PNRUH7JY.mjs → chunk-OECGKCVF.mjs} +5 -5
  66. package/dist/{chunk-YE67AALL.mjs → chunk-OL65UQHQ.mjs} +10 -10
  67. package/dist/{chunk-LQULK2E3.mjs → chunk-OYBIUEGE.mjs} +1 -1
  68. package/dist/{chunk-LR6LHDP3.mjs → chunk-PGR53HMH.mjs} +7 -7
  69. package/dist/chunk-PUJ42INK.mjs +141 -0
  70. package/dist/{chunk-M4VYX2PV.mjs → chunk-PV3Y7QGK.mjs} +2 -2
  71. package/dist/{chunk-UJZ4UHWI.mjs → chunk-PV7PNA6K.mjs} +4 -4
  72. package/dist/{chunk-6HIOM2HL.mjs → chunk-Q35PNFJ7.mjs} +1 -1
  73. package/dist/{chunk-JZY6TNIS.mjs → chunk-Q5SGEIJV.mjs} +27 -27
  74. package/dist/{chunk-ZFCDYW6N.mjs → chunk-QAX6HCUH.mjs} +1 -1
  75. package/dist/chunk-QHJDGB54.mjs +135 -0
  76. package/dist/chunk-QQSOZQOC.mjs +27 -0
  77. package/dist/chunk-RUX3OLVZ.mjs +59 -0
  78. package/dist/{chunk-QOJ2DQD6.mjs → chunk-S4CTM3UE.mjs} +5 -0
  79. package/dist/{chunk-ZEDMKQK2.mjs → chunk-TAX3KL66.mjs} +1 -1
  80. package/dist/chunk-TC43SMIN.mjs +133 -0
  81. package/dist/chunk-TGVXRD53.mjs +174 -0
  82. package/dist/{chunk-K5VHK7CM.mjs → chunk-TLYSVRSK.mjs} +12 -12
  83. package/dist/{chunk-YCWLFG27.mjs → chunk-TOIVHWNC.mjs} +1 -1
  84. package/dist/chunk-TXUBGKB7.mjs +160 -0
  85. package/dist/chunk-UEREFDAE.mjs +75 -0
  86. package/dist/chunk-UTCQN6XU.mjs +123 -0
  87. package/dist/{chunk-37AE3OM5.mjs → chunk-V4CUTCHS.mjs} +4 -4
  88. package/dist/{chunk-THVO2N47.mjs → chunk-VFH632TB.mjs} +9 -9
  89. package/dist/{chunk-3ERBUVHC.mjs → chunk-VJ3GC7W3.mjs} +95 -49
  90. package/dist/{chunk-V6XGXYCJ.mjs → chunk-VLELWBEW.mjs} +4 -4
  91. package/dist/{chunk-FEZKMUCF.mjs → chunk-WDTXHLYM.mjs} +1 -1
  92. package/dist/chunk-WUA546RX.mjs +129 -0
  93. package/dist/chunk-XHGISOX5.mjs +257 -0
  94. package/dist/chunk-XIY5DJXI.mjs +168 -0
  95. package/dist/{chunk-TOWTPLRC.mjs → chunk-XN37434W.mjs} +8 -8
  96. package/dist/{chunk-KLTACJ2G.mjs → chunk-XTWAJWCQ.mjs} +1 -1
  97. package/dist/chunk-Y24TXIFJ.mjs +518 -0
  98. package/dist/{chunk-DMXYRCHM.mjs → chunk-Y6UM3VTN.mjs} +4 -4
  99. package/dist/components/ui/about-you-form.js +1120 -0
  100. package/dist/components/ui/about-you-form.mjs +323 -0
  101. package/dist/components/ui/account-list-carousel.js +304 -0
  102. package/dist/components/ui/account-list-carousel.mjs +11 -0
  103. package/dist/components/ui/add-column-modal.js +1 -1
  104. package/dist/components/ui/add-column-modal.mjs +6 -6
  105. package/dist/components/ui/add-lead-modal.js +2 -2
  106. package/dist/components/ui/add-lead-modal.mjs +6 -6
  107. package/dist/components/ui/advisor-card.mjs +2 -2
  108. package/dist/components/ui/agent-evaluation-toast.js +299 -0
  109. package/dist/components/ui/agent-evaluation-toast.mjs +12 -0
  110. package/dist/components/ui/ai-assistant-drawer.mjs +5 -5
  111. package/dist/components/ui/ai-builder.js +3 -3
  112. package/dist/components/ui/ai-builder.mjs +5 -5
  113. package/dist/components/ui/ai-conversations.js +2 -2
  114. package/dist/components/ui/ai-conversations.mjs +11 -11
  115. package/dist/components/ui/alert-dialog.mjs +3 -3
  116. package/dist/components/ui/applicant-document-checklist.js +346 -0
  117. package/dist/components/ui/applicant-document-checklist.mjs +10 -0
  118. package/dist/components/ui/applicant-expenses-section.js +455 -0
  119. package/dist/components/ui/applicant-expenses-section.mjs +220 -0
  120. package/dist/components/ui/applicant-navigation-bar.js +309 -0
  121. package/dist/components/ui/applicant-navigation-bar.mjs +87 -0
  122. package/dist/components/ui/applicant-switcher.js +268 -0
  123. package/dist/components/ui/applicant-switcher.mjs +46 -0
  124. package/dist/components/ui/application-mobile-layout.js +88 -0
  125. package/dist/components/ui/application-mobile-layout.mjs +8 -0
  126. package/dist/components/ui/appointment-action-dialogs.js +1 -1
  127. package/dist/components/ui/appointment-action-dialogs.mjs +10 -10
  128. package/dist/components/ui/appointment-availability-settings.js +78 -31
  129. package/dist/components/ui/appointment-availability-settings.mjs +12 -10
  130. package/dist/components/ui/appointment-book-dialog.js +137 -58
  131. package/dist/components/ui/appointment-book-dialog.mjs +14 -14
  132. package/dist/components/ui/appointment-calendar-view.js +1 -1
  133. package/dist/components/ui/appointment-calendar-view.mjs +4 -4
  134. package/dist/components/ui/appointment-detail-sheet.js +38 -11
  135. package/dist/components/ui/appointment-detail-sheet.mjs +13 -13
  136. package/dist/components/ui/appointment-gmail-connect.mjs +2 -2
  137. package/dist/components/ui/appointment-time-slot-picker.mjs +2 -2
  138. package/dist/components/ui/appointment-upcoming-card.js +1 -1
  139. package/dist/components/ui/appointment-upcoming-card.mjs +10 -10
  140. package/dist/components/ui/asset-accordion.js +506 -0
  141. package/dist/components/ui/asset-accordion.mjs +202 -0
  142. package/dist/components/ui/assets-liabilities-side-card.js +328 -0
  143. package/dist/components/ui/assets-liabilities-side-card.mjs +127 -0
  144. package/dist/components/ui/auth-page-layout.js +3 -3
  145. package/dist/components/ui/auth-page-layout.mjs +1 -1
  146. package/dist/components/ui/backoffice-alert-history-chart.mjs +4 -4
  147. package/dist/components/ui/backoffice-alert-matching-chart.js +786 -0
  148. package/dist/components/ui/backoffice-alert-matching-chart.mjs +19 -0
  149. package/dist/components/ui/backoffice-alerts-chart.mjs +4 -4
  150. package/dist/components/ui/backoffice-connections-chart.mjs +4 -4
  151. package/dist/components/ui/backoffice-contact-history-chart.mjs +4 -4
  152. package/dist/components/ui/backoffice-contact-matching-chart.js +803 -0
  153. package/dist/components/ui/backoffice-contact-matching-chart.mjs +19 -0
  154. package/dist/components/ui/backoffice-signup-steps.js +1673 -0
  155. package/dist/components/ui/backoffice-signup-steps.mjs +36 -0
  156. package/dist/components/ui/bank-statement-document-table.js +467 -0
  157. package/dist/components/ui/bank-statement-document-table.mjs +12 -0
  158. package/dist/components/ui/bank-statement-generate-dialog.js +1517 -0
  159. package/dist/components/ui/bank-statement-generate-dialog.mjs +27 -0
  160. package/dist/components/ui/bank-statement-pdf-viewer.js +525 -0
  161. package/dist/components/ui/bank-statement-pdf-viewer.mjs +14 -0
  162. package/dist/components/ui/banking-accounts-connect.js +336 -0
  163. package/dist/components/ui/banking-accounts-connect.mjs +114 -0
  164. package/dist/components/ui/borrowing-capacity-atoms.js +382 -0
  165. package/dist/components/ui/borrowing-capacity-atoms.mjs +17 -0
  166. package/dist/components/ui/borrowing-capacity-card.js +835 -0
  167. package/dist/components/ui/borrowing-capacity-card.mjs +89 -0
  168. package/dist/components/ui/borrowing-capacity-line-chart.mjs +4 -4
  169. package/dist/components/ui/broker-info-panel.js +281 -0
  170. package/dist/components/ui/broker-info-panel.mjs +59 -0
  171. package/dist/components/ui/calculator-input-item.js +101 -0
  172. package/dist/components/ui/calculator-input-item.mjs +8 -0
  173. package/dist/components/ui/calculator-section.js +743 -0
  174. package/dist/components/ui/calculator-section.mjs +220 -0
  175. package/dist/components/ui/calendar.mjs +2 -2
  176. package/dist/components/ui/cash-balance-line-chart.mjs +5 -5
  177. package/dist/components/ui/cashflow-bar-chart.mjs +4 -4
  178. package/dist/components/ui/category-edit-dialog.js +737 -0
  179. package/dist/components/ui/category-edit-dialog.mjs +16 -0
  180. package/dist/components/ui/chat-widget.mjs +3 -3
  181. package/dist/components/ui/color-picker.mjs +4 -4
  182. package/dist/components/ui/connect-bank-step.js +511 -0
  183. package/dist/components/ui/connect-bank-step.mjs +287 -0
  184. package/dist/components/ui/contact-alert-dialog.js +1405 -0
  185. package/dist/components/ui/contact-alert-dialog.mjs +27 -0
  186. package/dist/components/ui/create-contact-modal.js +1028 -0
  187. package/dist/components/ui/create-contact-modal.mjs +21 -0
  188. package/dist/components/ui/csv-import-modal.js +583 -0
  189. package/dist/components/ui/csv-import-modal.mjs +14 -0
  190. package/dist/components/ui/currency-input.js +439 -0
  191. package/dist/components/ui/currency-input.mjs +13 -0
  192. package/dist/components/ui/dashboard-expense-categories.js +355 -0
  193. package/dist/components/ui/dashboard-expense-categories.mjs +186 -0
  194. package/dist/components/ui/dashboard-transactions-table.js +1083 -0
  195. package/dist/components/ui/dashboard-transactions-table.mjs +177 -0
  196. package/dist/components/ui/data-table.mjs +6 -6
  197. package/dist/components/ui/date-picker.mjs +6 -6
  198. package/dist/components/ui/debt-accordion.js +523 -0
  199. package/dist/components/ui/debt-accordion.mjs +219 -0
  200. package/dist/components/ui/delete-contact-component.js +479 -0
  201. package/dist/components/ui/delete-contact-component.mjs +14 -0
  202. package/dist/components/ui/dialog.js +1 -1
  203. package/dist/components/ui/dialog.mjs +3 -3
  204. package/dist/components/ui/document-checklist-template.mjs +4 -4
  205. package/dist/components/ui/drawer.mjs +3 -3
  206. package/dist/components/ui/dropdown-menu.mjs +3 -3
  207. package/dist/components/ui/dynamic-tabs.js +274 -0
  208. package/dist/components/ui/dynamic-tabs.mjs +116 -0
  209. package/dist/components/ui/editable-money-item.js +306 -0
  210. package/dist/components/ui/editable-money-item.mjs +12 -0
  211. package/dist/components/ui/expense-bar-chart.mjs +4 -4
  212. package/dist/components/ui/expense-detail-item.js +506 -0
  213. package/dist/components/ui/expense-detail-item.mjs +15 -0
  214. package/dist/components/ui/expense-work-details.js +1259 -0
  215. package/dist/components/ui/expense-work-details.mjs +175 -0
  216. package/dist/components/ui/field.mjs +2 -2
  217. package/dist/components/ui/file-preview-dialog.js +704 -0
  218. package/dist/components/ui/file-preview-dialog.mjs +17 -0
  219. package/dist/components/ui/financial-cards.mjs +2 -2
  220. package/dist/components/ui/financial-drawers.js +1 -1
  221. package/dist/components/ui/financial-drawers.mjs +5 -5
  222. package/dist/components/ui/financial-sections.mjs +4 -4
  223. package/dist/components/ui/form-primitives.mjs +2 -2
  224. package/dist/components/ui/frontend-signup-steps.js +1239 -0
  225. package/dist/components/ui/frontend-signup-steps.mjs +38 -0
  226. package/dist/components/ui/income-bar-chart.mjs +4 -4
  227. package/dist/components/ui/income-sources-card.js +269 -0
  228. package/dist/components/ui/income-sources-card.mjs +100 -0
  229. package/dist/components/ui/income-summary-component.js +361 -0
  230. package/dist/components/ui/income-summary-component.mjs +84 -0
  231. package/dist/components/ui/income-work-details.js +1663 -0
  232. package/dist/components/ui/income-work-details.mjs +28 -0
  233. package/dist/components/ui/incoming-outgoings-card.js +218 -0
  234. package/dist/components/ui/incoming-outgoings-card.mjs +82 -0
  235. package/dist/components/ui/interest-rate-input.js +442 -0
  236. package/dist/components/ui/interest-rate-input.mjs +90 -0
  237. package/dist/components/ui/interest-rate-section.js +337 -0
  238. package/dist/components/ui/interest-rate-section.mjs +84 -0
  239. package/dist/components/ui/interest-rate-used.js +202 -0
  240. package/dist/components/ui/interest-rate-used.mjs +62 -0
  241. package/dist/components/ui/kanban-column.js +338 -160
  242. package/dist/components/ui/kanban-column.mjs +13 -11
  243. package/dist/components/ui/loan-applicant-information.js +336 -0
  244. package/dist/components/ui/loan-applicant-information.mjs +59 -0
  245. package/dist/components/ui/loan-applicant-invite.js +319 -0
  246. package/dist/components/ui/loan-applicant-invite.mjs +68 -0
  247. package/dist/components/ui/loan-application-badge.js +236 -0
  248. package/dist/components/ui/loan-application-badge.mjs +10 -0
  249. package/dist/components/ui/loan-application-cards.js +356 -0
  250. package/dist/components/ui/loan-application-cards.mjs +110 -0
  251. package/dist/components/ui/loan-entry-shell.js +104 -0
  252. package/dist/components/ui/loan-entry-shell.mjs +8 -0
  253. package/dist/components/ui/loan-financials.js +410 -0
  254. package/dist/components/ui/loan-financials.mjs +76 -0
  255. package/dist/components/ui/loan-option-card.js +102 -0
  256. package/dist/components/ui/loan-option-card.mjs +41 -0
  257. package/dist/components/ui/loan-option-group.js +288 -0
  258. package/dist/components/ui/loan-option-group.mjs +10 -0
  259. package/dist/components/ui/loan-steps.js +1121 -0
  260. package/dist/components/ui/loan-steps.mjs +509 -0
  261. package/dist/components/ui/loan-wizard-shell.js +452 -0
  262. package/dist/components/ui/loan-wizard-shell.mjs +11 -0
  263. package/dist/components/ui/money-input-with-slider.js +210 -0
  264. package/dist/components/ui/money-input-with-slider.mjs +10 -0
  265. package/dist/components/ui/money-item-with-color-indicator.js +314 -0
  266. package/dist/components/ui/money-item-with-color-indicator.mjs +20 -0
  267. package/dist/components/ui/opportunity-card.js +235 -97
  268. package/dist/components/ui/opportunity-card.mjs +11 -9
  269. package/dist/components/ui/opportunity-edit-modals.js +1 -1
  270. package/dist/components/ui/opportunity-edit-modals.mjs +15 -15
  271. package/dist/components/ui/opportunity-summary-tab.js +1 -1
  272. package/dist/components/ui/opportunity-summary-tab.mjs +19 -19
  273. package/dist/components/ui/pagination.mjs +4 -4
  274. package/dist/components/ui/password-strength-tooltip.mjs +4 -4
  275. package/dist/components/ui/pipeline-board.js +358 -176
  276. package/dist/components/ui/pipeline-board.mjs +16 -14
  277. package/dist/components/ui/pipeline-chart.mjs +3 -3
  278. package/dist/components/ui/pipeline-dialogs.js +1 -1
  279. package/dist/components/ui/pipeline-dialogs.mjs +9 -9
  280. package/dist/components/ui/pipeline-primitives.js +75 -8
  281. package/dist/components/ui/pipeline-primitives.mjs +3 -2
  282. package/dist/components/ui/popover.mjs +3 -3
  283. package/dist/components/ui/property-asset-card.js +428 -0
  284. package/dist/components/ui/property-asset-card.mjs +156 -0
  285. package/dist/components/ui/property-cashflow-doughnut-chart.mjs +4 -4
  286. package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +4 -4
  287. package/dist/components/ui/property-list-carousel.js +295 -0
  288. package/dist/components/ui/property-list-carousel.mjs +11 -0
  289. package/dist/components/ui/property-mobile-estimate-line-chart.mjs +4 -4
  290. package/dist/components/ui/property-report-dialog.js +1148 -0
  291. package/dist/components/ui/property-report-dialog.mjs +25 -0
  292. package/dist/components/ui/resource-center.js +748 -0
  293. package/dist/components/ui/resource-center.mjs +24 -0
  294. package/dist/components/ui/review-alerts-dialog.js +569 -0
  295. package/dist/components/ui/review-alerts-dialog.mjs +15 -0
  296. package/dist/components/ui/savings-goal-modal.js +1148 -0
  297. package/dist/components/ui/savings-goal-modal.mjs +160 -0
  298. package/dist/components/ui/scenario-drawer.js +791 -0
  299. package/dist/components/ui/scenario-drawer.mjs +294 -0
  300. package/dist/components/ui/scenario-item.js +256 -0
  301. package/dist/components/ui/scenario-item.mjs +11 -0
  302. package/dist/components/ui/scenario-list.js +507 -0
  303. package/dist/components/ui/scenario-list.mjs +100 -0
  304. package/dist/components/ui/select.mjs +3 -3
  305. package/dist/components/ui/share-details-dialog.js +636 -0
  306. package/dist/components/ui/share-details-dialog.mjs +19 -0
  307. package/dist/components/ui/sheet.mjs +3 -3
  308. package/dist/components/ui/sidebar-nav.mjs +5 -5
  309. package/dist/components/ui/signup-form-primitives.js +770 -0
  310. package/dist/components/ui/signup-form-primitives.mjs +25 -0
  311. package/dist/components/ui/signup-shell.js +338 -0
  312. package/dist/components/ui/signup-shell.mjs +13 -0
  313. package/dist/components/ui/stage-timeline.js +103 -33
  314. package/dist/components/ui/stage-timeline.mjs +5 -4
  315. package/dist/components/ui/submission-confirmation-card.js +284 -0
  316. package/dist/components/ui/submission-confirmation-card.mjs +62 -0
  317. package/dist/components/ui/tooltip.mjs +3 -3
  318. package/dist/components/ui/top-three-product.js +374 -0
  319. package/dist/components/ui/top-three-product.mjs +129 -0
  320. package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +4 -4
  321. package/dist/components/ui/transactions-income-expense-bar-chart.mjs +5 -5
  322. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +4 -4
  323. package/dist/components/ui/transactions-summary-block.js +95 -0
  324. package/dist/components/ui/transactions-summary-block.mjs +34 -0
  325. package/dist/components/ui/two-fa-setup-form.mjs +3 -3
  326. package/dist/index.js +9430 -4573
  327. package/dist/index.mjs +404 -251
  328. package/dist/lib/colors.js +6 -0
  329. package/dist/lib/colors.mjs +3 -1
  330. package/dist/lib/theme-provider.mjs +2 -2
  331. package/dist/styles.css +1 -1
  332. package/package.json +366 -2
  333. package/src/components/index.tsx +223 -0
  334. package/src/components/ui/about-you-form.tsx +397 -0
  335. package/src/components/ui/account-list-carousel.tsx +87 -0
  336. package/src/components/ui/add-lead-modal.tsx +1 -1
  337. package/src/components/ui/agent-evaluation-toast.tsx +191 -0
  338. package/src/components/ui/ai-builder.tsx +3 -5
  339. package/src/components/ui/ai-conversations.tsx +1 -1
  340. package/src/components/ui/applicant-document-checklist.tsx +175 -0
  341. package/src/components/ui/applicant-expenses-section.tsx +260 -0
  342. package/src/components/ui/applicant-navigation-bar.tsx +104 -0
  343. package/src/components/ui/applicant-switcher.tsx +54 -0
  344. package/src/components/ui/application-mobile-layout.tsx +34 -0
  345. package/src/components/ui/appointment-availability-settings.tsx +115 -23
  346. package/src/components/ui/appointment-book-dialog.tsx +406 -259
  347. package/src/components/ui/appointment-calendar-view.tsx +4 -1
  348. package/src/components/ui/appointment-detail-sheet.tsx +59 -24
  349. package/src/components/ui/appointment-time-slot-picker.tsx +5 -1
  350. package/src/components/ui/asset-accordion.tsx +241 -0
  351. package/src/components/ui/assets-liabilities-side-card.tsx +157 -0
  352. package/src/components/ui/auth-page-layout.tsx +3 -3
  353. package/src/components/ui/backoffice-alert-matching-chart.tsx +320 -0
  354. package/src/components/ui/backoffice-contact-matching-chart.tsx +341 -0
  355. package/src/components/ui/backoffice-signup-steps.tsx +615 -0
  356. package/src/components/ui/bank-statement-document-table.tsx +222 -0
  357. package/src/components/ui/bank-statement-generate-dialog.tsx +435 -0
  358. package/src/components/ui/bank-statement-pdf-viewer.tsx +241 -0
  359. package/src/components/ui/banking-accounts-connect.tsx +187 -0
  360. package/src/components/ui/borrowing-capacity-atoms.tsx +228 -0
  361. package/src/components/ui/borrowing-capacity-card.tsx +155 -0
  362. package/src/components/ui/broker-info-panel.tsx +94 -0
  363. package/src/components/ui/calculator-input-item.tsx +49 -0
  364. package/src/components/ui/calculator-section.tsx +275 -0
  365. package/src/components/ui/category-edit-dialog.tsx +300 -0
  366. package/src/components/ui/connect-bank-step.tsx +379 -0
  367. package/src/components/ui/contact-alert-dialog.tsx +710 -0
  368. package/src/components/ui/create-contact-modal.tsx +237 -0
  369. package/src/components/ui/csv-import-modal.tsx +153 -0
  370. package/src/components/ui/currency-input.tsx +104 -0
  371. package/src/components/ui/dashboard-expense-categories.tsx +262 -0
  372. package/src/components/ui/dashboard-transactions-table.tsx +241 -0
  373. package/src/components/ui/debt-accordion.tsx +254 -0
  374. package/src/components/ui/delete-contact-component.tsx +87 -0
  375. package/src/components/ui/dialog.tsx +2 -2
  376. package/src/components/ui/dynamic-tabs.tsx +149 -0
  377. package/src/components/ui/editable-money-item.tsx +176 -0
  378. package/src/components/ui/expense-detail-item.tsx +216 -0
  379. package/src/components/ui/expense-work-details.tsx +229 -0
  380. package/src/components/ui/file-preview-dialog.tsx +292 -0
  381. package/src/components/ui/financial-drawers.tsx +1 -1
  382. package/src/components/ui/frontend-signup-steps.tsx +548 -0
  383. package/src/components/ui/income-sources-card.tsx +143 -0
  384. package/src/components/ui/income-summary-component.tsx +120 -0
  385. package/src/components/ui/income-work-details.tsx +429 -0
  386. package/src/components/ui/incoming-outgoings-card.tsx +111 -0
  387. package/src/components/ui/interest-rate-input.tsx +111 -0
  388. package/src/components/ui/interest-rate-section.tsx +158 -0
  389. package/src/components/ui/interest-rate-used.tsx +82 -0
  390. package/src/components/ui/kanban-column.tsx +53 -2
  391. package/src/components/ui/loan-applicant-information.tsx +64 -0
  392. package/src/components/ui/loan-applicant-invite.tsx +67 -0
  393. package/src/components/ui/loan-application-badge.tsx +70 -0
  394. package/src/components/ui/loan-application-cards.tsx +152 -0
  395. package/src/components/ui/loan-entry-shell.tsx +86 -0
  396. package/src/components/ui/loan-financials.tsx +77 -0
  397. package/src/components/ui/loan-option-card.tsx +62 -0
  398. package/src/components/ui/loan-option-group.tsx +106 -0
  399. package/src/components/ui/loan-steps.tsx +630 -0
  400. package/src/components/ui/loan-wizard-shell.tsx +235 -0
  401. package/src/components/ui/money-input-with-slider.tsx +77 -0
  402. package/src/components/ui/money-item-with-color-indicator.tsx +30 -0
  403. package/src/components/ui/opportunity-card.tsx +46 -18
  404. package/src/components/ui/pipeline-board.tsx +13 -0
  405. package/src/components/ui/pipeline-primitives.tsx +28 -0
  406. package/src/components/ui/property-asset-card.tsx +221 -0
  407. package/src/components/ui/property-list-carousel.tsx +73 -0
  408. package/src/components/ui/property-report-dialog.tsx +355 -0
  409. package/src/components/ui/resource-center.tsx +539 -0
  410. package/src/components/ui/review-alerts-dialog.tsx +163 -0
  411. package/src/components/ui/savings-goal-modal.tsx +169 -0
  412. package/src/components/ui/scenario-drawer.tsx +358 -0
  413. package/src/components/ui/scenario-item.tsx +141 -0
  414. package/src/components/ui/scenario-list.tsx +150 -0
  415. package/src/components/ui/share-details-dialog.tsx +238 -0
  416. package/src/components/ui/signup-form-primitives.tsx +212 -0
  417. package/src/components/ui/signup-shell.tsx +180 -0
  418. package/src/components/ui/stage-timeline.tsx +11 -0
  419. package/src/components/ui/submission-confirmation-card.tsx +68 -0
  420. package/src/components/ui/top-three-product.tsx +207 -0
  421. package/src/components/ui/transactions-summary-block.tsx +59 -0
  422. package/src/lib/colors.ts +12 -0
  423. package/src/lib/format-date.ts +2 -2
  424. package/src/styles/styles-css.ts +1 -1
  425. package/tsup.config.ts +77 -1
  426. package/dist/{chunk-5VOTTIXF.mjs → chunk-FRT3S72S.mjs} +3 -3
  427. package/dist/{chunk-7BTFGCFC.mjs → chunk-MUV4EGDW.mjs} +3 -3
  428. package/dist/{chunk-57ZXILTS.mjs → chunk-MXP2RX2V.mjs} +3 -3
  429. package/dist/{chunk-ZKWXDQDG.mjs → chunk-VCDGLN25.mjs} +3 -3
  430. package/dist/{chunk-FLL633WS.mjs → chunk-ZXEUBBHJ.mjs} +3 -3
@@ -0,0 +1,222 @@
1
+ import { Download, Trash2 } from "lucide-react";
2
+ import { cn } from "@/lib/utils";
3
+ import { Button } from "@/components/ui/button";
4
+ import { Checkbox } from "@/components/ui/checkbox";
5
+ import {
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableHead,
10
+ TableHeader,
11
+ TableRow,
12
+ } from "@/components/ui/table";
13
+
14
+ /**
15
+ * BankStatementDocumentTable — WealthX DS (L3 Organism)
16
+ *
17
+ * A table for managing bank statement documents inside the Bank Statement tab
18
+ * of `OpportunityDetailsDrawer`. Renders two instances per opportunity:
19
+ * one for the main applicant and one for the co-applicant.
20
+ *
21
+ * Features:
22
+ * - Select-all / individual row checkboxes
23
+ * - "Download All" bulk action (disabled when nothing selected)
24
+ * - Per-row view (click name), download, and delete actions
25
+ * - Loading and empty states
26
+ *
27
+ * Layer: L3 Organism
28
+ *
29
+ * Data source: bank statement documents fetched via `DocumentTypeFilter.GENERATED`
30
+ */
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Types
34
+ // ---------------------------------------------------------------------------
35
+
36
+ export interface BankStatementDocument {
37
+ id: string;
38
+ /** Display filename shown in the Name column. */
39
+ name: string;
40
+ /** Document type label, e.g. "Bank Statement" or "Property Report". */
41
+ type: string;
42
+ /** ISO date string or pre-formatted date label. */
43
+ updatedDate: string;
44
+ /** When true, download / delete action buttons are shown for this row. */
45
+ hasDownload: boolean;
46
+ /**
47
+ * Whether the underlying PDF data is ready to view/download.
48
+ * `false` or `undefined` → action buttons are shown but disabled.
49
+ * `true` → clicking the name triggers `onView`; action buttons are enabled.
50
+ */
51
+ statementReady?: boolean;
52
+ }
53
+
54
+ export interface BankStatementDocumentTableProps {
55
+ /** Section heading rendered above the table (e.g. "Main Applicant"). */
56
+ title: string;
57
+ documents: BankStatementDocument[];
58
+ /** IDs of currently selected rows. */
59
+ selectedIds: string[];
60
+ /** Toggle a single row's selection. */
61
+ onToggle: (id: string) => void;
62
+ /** Toggle all rows (select all / deselect all). */
63
+ onToggleAll: () => void;
64
+ /** Bulk download — only enabled when `selectedIds.length > 0`. */
65
+ onDownloadAll: () => void;
66
+ /** Open the PDF viewer for this document (requires `statementReady`). */
67
+ onView: (doc: BankStatementDocument) => void;
68
+ /** Download a single document (requires `statementReady`). */
69
+ onDownload: (doc: BankStatementDocument) => void;
70
+ /** Open the delete confirmation for a document (requires `statementReady`). */
71
+ onDelete: (doc: BankStatementDocument) => void;
72
+ /** Show a loading row instead of documents. */
73
+ isLoading?: boolean;
74
+ /** Disable delete buttons while a deletion is in flight. */
75
+ isDeleting?: boolean;
76
+ className?: string;
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // BankStatementDocumentTable
81
+ // ---------------------------------------------------------------------------
82
+
83
+ export function BankStatementDocumentTable({
84
+ title,
85
+ documents,
86
+ selectedIds,
87
+ onToggle,
88
+ onToggleAll,
89
+ onDownloadAll,
90
+ onView,
91
+ onDownload,
92
+ onDelete,
93
+ isLoading = false,
94
+ isDeleting = false,
95
+ className,
96
+ }: BankStatementDocumentTableProps) {
97
+ const areAllSelected =
98
+ documents.length > 0 && selectedIds.length === documents.length;
99
+ const isIndeterminate = selectedIds.length > 0 && !areAllSelected;
100
+
101
+ return (
102
+ <div
103
+ className={cn("flex flex-col gap-2", className)}
104
+ data-slot="bank-statement-document-table"
105
+ >
106
+ {/* ── Header ── */}
107
+ <div className="flex items-center justify-between">
108
+ <p className="text-body-large font-semibold">{title}</p>
109
+ <Button
110
+ variant="outline"
111
+ size="sm"
112
+ onClick={onDownloadAll}
113
+ disabled={selectedIds.length === 0}
114
+ >
115
+ Download All
116
+ </Button>
117
+ </div>
118
+
119
+ {/* ── Table ── */}
120
+ <Table>
121
+ <TableHeader>
122
+ <TableRow>
123
+ <TableHead className="w-10">
124
+ <Checkbox
125
+ checked={areAllSelected}
126
+ indeterminate={isIndeterminate}
127
+ onCheckedChange={onToggleAll}
128
+ aria-label="Select all"
129
+ disabled={isLoading || documents.length === 0}
130
+ />
131
+ </TableHead>
132
+ <TableHead>Name</TableHead>
133
+ <TableHead>Type</TableHead>
134
+ <TableHead>Date</TableHead>
135
+ <TableHead className="w-20">Action</TableHead>
136
+ </TableRow>
137
+ </TableHeader>
138
+ <TableBody>
139
+ {isLoading ? (
140
+ <TableRow>
141
+ <TableCell colSpan={5} className="py-8 text-center">
142
+ <p className="text-body-medium text-muted-foreground">
143
+ Loading documents…
144
+ </p>
145
+ </TableCell>
146
+ </TableRow>
147
+ ) : documents.length === 0 ? (
148
+ <TableRow>
149
+ <TableCell colSpan={5} className="py-8 text-center">
150
+ <p className="text-body-medium text-muted-foreground">
151
+ No documents found
152
+ </p>
153
+ </TableCell>
154
+ </TableRow>
155
+ ) : (
156
+ documents.map((doc) => (
157
+ <TableRow key={doc.id}>
158
+ <TableCell>
159
+ <Checkbox
160
+ checked={selectedIds.includes(doc.id)}
161
+ onCheckedChange={() => onToggle(doc.id)}
162
+ aria-label={`Select ${doc.name}`}
163
+ />
164
+ </TableCell>
165
+
166
+ {/* Name — clickable when download is ready */}
167
+ <TableCell>
168
+ <p
169
+ className={cn(
170
+ "text-body-medium max-w-[360px] overflow-hidden text-ellipsis whitespace-nowrap font-semibold align-bottom inline-block",
171
+ doc.hasDownload && doc.statementReady
172
+ ? "cursor-pointer text-primary hover:underline"
173
+ : "cursor-default",
174
+ )}
175
+ onClick={() => {
176
+ if (doc.hasDownload && doc.statementReady) {
177
+ onView(doc);
178
+ }
179
+ }}
180
+ >
181
+ {doc.name}
182
+ </p>
183
+ </TableCell>
184
+
185
+ <TableCell>{doc.type}</TableCell>
186
+ <TableCell>{doc.updatedDate}</TableCell>
187
+
188
+ {/* Actions */}
189
+ <TableCell>
190
+ <div className="flex gap-1">
191
+ {doc.hasDownload && (
192
+ <>
193
+ <Button
194
+ variant="ghost"
195
+ size="icon-sm"
196
+ aria-label="Download"
197
+ onClick={() => onDownload(doc)}
198
+ disabled={!doc.statementReady}
199
+ >
200
+ <Download className="size-4" />
201
+ </Button>
202
+ <Button
203
+ variant="ghost"
204
+ size="icon-sm"
205
+ aria-label="Delete"
206
+ onClick={() => onDelete(doc)}
207
+ disabled={!doc.statementReady || isDeleting}
208
+ >
209
+ <Trash2 className="size-4" />
210
+ </Button>
211
+ </>
212
+ )}
213
+ </div>
214
+ </TableCell>
215
+ </TableRow>
216
+ ))
217
+ )}
218
+ </TableBody>
219
+ </Table>
220
+ </div>
221
+ );
222
+ }
@@ -0,0 +1,435 @@
1
+ import { useEffect, useMemo, useState } from "react";
2
+ import { format, parseISO, subDays } from "date-fns";
3
+ import { cn } from "@/lib/utils";
4
+ import { Button } from "@/components/ui/button";
5
+ import { Checkbox } from "@/components/ui/checkbox";
6
+ import { DatePicker } from "@/components/ui/date-picker";
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogFooter,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ } from "@/components/ui/dialog";
14
+ import { Field, FieldLabel } from "@/components/ui/field";
15
+ import { Input } from "@/components/ui/input";
16
+ import {
17
+ Select,
18
+ SelectContent,
19
+ SelectItem,
20
+ SelectTrigger,
21
+ SelectValue,
22
+ } from "@/components/ui/select";
23
+ import { Spinner } from "@/components/ui/spinner";
24
+ import {
25
+ Table,
26
+ TableBody,
27
+ TableCell,
28
+ TableHead,
29
+ TableHeader,
30
+ TableRow,
31
+ } from "@/components/ui/table";
32
+ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
33
+
34
+ /**
35
+ * BankStatementGenerateDialog — WealthX DS (L4 Template)
36
+ *
37
+ * Dialog for generating a new bank statement PDF from connected bank accounts.
38
+ * Shown when the user clicks "Generate" in the Bank Statement tab of
39
+ * `OpportunityDetailsDrawer`.
40
+ *
41
+ * Internal state:
42
+ * - Statement name (Input)
43
+ * - Range preset: 90 / 180 / 365 days or Custom (ToggleGroup + DatePickers)
44
+ * - Applicant type: primary / secondary (Select)
45
+ * - Selected bank account IDs (Table with Checkboxes)
46
+ *
47
+ * Data handed in via props (consumer owns fetching):
48
+ * - `bankAccounts` — pre-filtered for the current `applicantType`
49
+ * - `isLoadingAccounts` — spinner while the consumer re-fetches after type change
50
+ *
51
+ * Layer: L4 Template
52
+ *
53
+ * Data source: `useAggregatedBankAccounts` in backoffice (not included here)
54
+ */
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Types
58
+ // ---------------------------------------------------------------------------
59
+
60
+ export type BankStatementRangePreset = 90 | 180 | 365 | "custom";
61
+
62
+ export interface BankStatementAccount {
63
+ id: string;
64
+ /** Display name for the account (e.g. "Everyday Savings"). */
65
+ name: string;
66
+ /** BSB / account number string. */
67
+ accountNo?: string;
68
+ /** Bank / institution name. */
69
+ institutionName?: string;
70
+ /** URL to institution logo image. */
71
+ institutionLogo?: string;
72
+ /** ISO date string of when the account was last synced. */
73
+ lastUpdated?: string;
74
+ }
75
+
76
+ export interface BankStatementGeneratePayload {
77
+ statementName: string;
78
+ rangePreset: BankStatementRangePreset;
79
+ /** ISO date string (YYYY-MM-DD). Set for all presets as well as custom. */
80
+ fromDate: string;
81
+ /** ISO date string (YYYY-MM-DD). Set for all presets as well as custom. */
82
+ toDate: string;
83
+ applicantType: "primary" | "secondary";
84
+ selectedAccountIds: string[];
85
+ }
86
+
87
+ export interface BankStatementGenerateDialogProps {
88
+ open: boolean;
89
+ onClose: () => void;
90
+ /**
91
+ * Called when the user clicks Generate (only if form is valid).
92
+ * Consumer is responsible for the actual API call.
93
+ */
94
+ onSubmit: (payload: BankStatementGeneratePayload) => void;
95
+ /**
96
+ * Called when the user changes the applicant type so the consumer can
97
+ * re-fetch / re-filter bank accounts for the new type.
98
+ */
99
+ onApplicantTypeChange?: (type: "primary" | "secondary") => void;
100
+ /**
101
+ * Bank accounts pre-filtered for the currently selected applicant type.
102
+ * Pass an empty array while loading.
103
+ */
104
+ bankAccounts: BankStatementAccount[];
105
+ /** Show "Co-Applicant" option in the applicant type Select. */
106
+ hasCoApplicant?: boolean;
107
+ /** Show a loading spinner in the accounts table while the consumer re-fetches. */
108
+ isLoadingAccounts?: boolean;
109
+ /** Show a loading indicator on the Generate button while the API call is in flight. */
110
+ isLoading?: boolean;
111
+ className?: string;
112
+ }
113
+
114
+ // ---------------------------------------------------------------------------
115
+ // Helpers
116
+ // ---------------------------------------------------------------------------
117
+
118
+ function toIsoDate(date: Date): string {
119
+ return date.toISOString().slice(0, 10);
120
+ }
121
+
122
+ function presetToDateRange(preset: number): { from: string; to: string } {
123
+ const today = new Date();
124
+ return {
125
+ from: toIsoDate(subDays(today, preset - 1)),
126
+ to: toIsoDate(today),
127
+ };
128
+ }
129
+
130
+ // ---------------------------------------------------------------------------
131
+ // BankStatementGenerateDialog
132
+ // ---------------------------------------------------------------------------
133
+
134
+ export function BankStatementGenerateDialog({
135
+ open,
136
+ onClose,
137
+ onSubmit,
138
+ onApplicantTypeChange,
139
+ bankAccounts,
140
+ hasCoApplicant = false,
141
+ isLoadingAccounts = false,
142
+ isLoading = false,
143
+ className,
144
+ }: BankStatementGenerateDialogProps) {
145
+ const [statementName, setStatementName] = useState("Bank Statement 1");
146
+ const [rangePreset, setRangePreset] = useState<BankStatementRangePreset>(90);
147
+ const [fromDate, setFromDate] = useState<string>("");
148
+ const [toDate, setToDate] = useState<string>("");
149
+ const [applicantType, setApplicantType] = useState<
150
+ "primary" | "secondary" | ""
151
+ >("");
152
+ const [selectedAccountIds, setSelectedAccountIds] = useState<string[]>([]);
153
+
154
+ // Reset form whenever the dialog opens.
155
+ useEffect(() => {
156
+ if (!open) return;
157
+ const timer = setTimeout(() => {
158
+ setStatementName("Bank Statement 1");
159
+ setApplicantType("");
160
+ setSelectedAccountIds([]);
161
+ const { from, to } = presetToDateRange(90);
162
+ setRangePreset(90);
163
+ setFromDate(from);
164
+ setToDate(to);
165
+ }, 0);
166
+ return () => clearTimeout(timer);
167
+ }, [open]);
168
+
169
+ // ── Applicant type ───────────────────────────────────────────────────────
170
+
171
+ const handleApplicantTypeChange = (type: "primary" | "secondary") => {
172
+ setApplicantType(type);
173
+ setSelectedAccountIds([]);
174
+ onApplicantTypeChange?.(type);
175
+ };
176
+
177
+ // ── Date range preset ────────────────────────────────────────────────────
178
+
179
+ const applyPreset = (preset: BankStatementRangePreset) => {
180
+ setRangePreset(preset);
181
+ if (preset !== "custom") {
182
+ const { from, to } = presetToDateRange(preset);
183
+ setFromDate(from);
184
+ setToDate(to);
185
+ }
186
+ };
187
+
188
+ // ── Account selection ────────────────────────────────────────────────────
189
+
190
+ const areAllSelected =
191
+ bankAccounts.length > 0 &&
192
+ selectedAccountIds.length === bankAccounts.length;
193
+ const isSomeSelected = selectedAccountIds.length > 0 && !areAllSelected;
194
+
195
+ const handleToggleAccount = (id: string) => {
196
+ setSelectedAccountIds((prev) =>
197
+ prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id],
198
+ );
199
+ };
200
+
201
+ const handleToggleAll = () => {
202
+ if (areAllSelected) {
203
+ setSelectedAccountIds([]);
204
+ } else {
205
+ setSelectedAccountIds(bankAccounts.map((a) => a.id));
206
+ }
207
+ };
208
+
209
+ // ── Period label for the accounts table ─────────────────────────────────
210
+
211
+ const periodLabel = useMemo(() => {
212
+ if (fromDate && toDate) {
213
+ return `${format(parseISO(fromDate), "dd MMM yyyy")} – ${format(parseISO(toDate), "dd MMM yyyy")}`;
214
+ }
215
+ return "—";
216
+ }, [fromDate, toDate]);
217
+
218
+ // ── Submit guard ─────────────────────────────────────────────────────────
219
+
220
+ const isSubmitDisabled =
221
+ !statementName.trim() ||
222
+ !applicantType ||
223
+ (rangePreset === "custom" && (!fromDate || !toDate)) ||
224
+ selectedAccountIds.length === 0;
225
+
226
+ const handleSubmit = () => {
227
+ if (isSubmitDisabled || !applicantType) return;
228
+ onSubmit({
229
+ statementName,
230
+ rangePreset,
231
+ fromDate,
232
+ toDate,
233
+ applicantType,
234
+ selectedAccountIds,
235
+ });
236
+ };
237
+
238
+ // ── Render ───────────────────────────────────────────────────────────────
239
+
240
+ return (
241
+ <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
242
+ <DialogContent
243
+ className={cn("max-w-[700px]", className)}
244
+ data-slot="bank-statement-generate-dialog"
245
+ >
246
+ <DialogHeader>
247
+ <DialogTitle>Generate Bank Statement</DialogTitle>
248
+ </DialogHeader>
249
+
250
+ <div className="flex flex-col gap-4">
251
+ {/* Statement name */}
252
+ <Field>
253
+ <FieldLabel>Name</FieldLabel>
254
+ <Input
255
+ value={statementName}
256
+ onChange={(e) => setStatementName(e.target.value)}
257
+ placeholder="Bank Statement 1"
258
+ />
259
+ </Field>
260
+
261
+ {/* Date range preset */}
262
+ <div className="flex flex-col gap-2">
263
+ <span className="text-body-small text-muted-foreground">
264
+ Statement period
265
+ </span>
266
+ <ToggleGroup
267
+ type="single"
268
+ variant="outline"
269
+ value={[String(rangePreset)]}
270
+ onValueChange={(val) => {
271
+ if (val.length === 0) return;
272
+ const raw = val[0];
273
+ if (raw === "custom") {
274
+ applyPreset("custom");
275
+ } else {
276
+ applyPreset(Number(raw) as 90 | 180 | 365);
277
+ }
278
+ }}
279
+ className="w-full"
280
+ >
281
+ <ToggleGroupItem value="90" className="flex-1">
282
+ 3 Months
283
+ </ToggleGroupItem>
284
+ <ToggleGroupItem value="180" className="flex-1">
285
+ 6 Months
286
+ </ToggleGroupItem>
287
+ <ToggleGroupItem value="365" className="flex-1">
288
+ 12 Months
289
+ </ToggleGroupItem>
290
+ <ToggleGroupItem value="custom" className="flex-1">
291
+ Custom
292
+ </ToggleGroupItem>
293
+ </ToggleGroup>
294
+ </div>
295
+
296
+ {/* Custom date pickers */}
297
+ {rangePreset === "custom" && (
298
+ <div className="flex gap-3">
299
+ <DatePicker
300
+ value={fromDate ? parseISO(fromDate) : undefined}
301
+ onChange={(date) => setFromDate(date ? toIsoDate(date) : "")}
302
+ placeholder="From Date"
303
+ className="flex-1"
304
+ />
305
+ <DatePicker
306
+ value={toDate ? parseISO(toDate) : undefined}
307
+ onChange={(date) => setToDate(date ? toIsoDate(date) : "")}
308
+ placeholder="To Date"
309
+ className="flex-1"
310
+ />
311
+ </div>
312
+ )}
313
+
314
+ {/* Applicant type */}
315
+ <Select
316
+ value={applicantType}
317
+ onValueChange={(v) =>
318
+ handleApplicantTypeChange(v as "primary" | "secondary")
319
+ }
320
+ >
321
+ <SelectTrigger className="w-full">
322
+ <SelectValue placeholder="Applicant Type" />
323
+ </SelectTrigger>
324
+ <SelectContent>
325
+ <SelectItem value="primary">Main applicant</SelectItem>
326
+ {hasCoApplicant && (
327
+ <SelectItem value="secondary">Co-applicant</SelectItem>
328
+ )}
329
+ </SelectContent>
330
+ </Select>
331
+
332
+ {/* Bank accounts table */}
333
+ {applicantType && (
334
+ <div className="mt-1">
335
+ {isLoadingAccounts && (
336
+ <div className="flex items-center justify-center p-6">
337
+ <Spinner size="lg" />
338
+ </div>
339
+ )}
340
+
341
+ {!isLoadingAccounts && bankAccounts.length === 0 && (
342
+ <p className="py-4 text-center text-body-medium text-muted-foreground">
343
+ No bank accounts found for the selected applicant
344
+ </p>
345
+ )}
346
+
347
+ {!isLoadingAccounts && bankAccounts.length > 0 && (
348
+ <Table>
349
+ <TableHeader>
350
+ <TableRow>
351
+ <TableHead className="w-10">
352
+ <Checkbox
353
+ checked={areAllSelected}
354
+ indeterminate={isSomeSelected}
355
+ onCheckedChange={handleToggleAll}
356
+ aria-label="Select all accounts"
357
+ />
358
+ </TableHead>
359
+ <TableHead>Account Name</TableHead>
360
+ <TableHead>Account Number</TableHead>
361
+ <TableHead>Period</TableHead>
362
+ <TableHead>Last Updated</TableHead>
363
+ </TableRow>
364
+ </TableHeader>
365
+ <TableBody>
366
+ {bankAccounts.map((account) => (
367
+ <TableRow key={account.id}>
368
+ <TableCell>
369
+ <Checkbox
370
+ checked={selectedAccountIds.includes(account.id)}
371
+ onCheckedChange={() =>
372
+ handleToggleAccount(account.id)
373
+ }
374
+ aria-label={`Select ${account.name}`}
375
+ />
376
+ </TableCell>
377
+ <TableCell>
378
+ <div className="flex items-center gap-2">
379
+ {account.institutionLogo && (
380
+ <img
381
+ src={account.institutionLogo}
382
+ alt={account.institutionName ?? ""}
383
+ className="size-8 rounded object-cover"
384
+ />
385
+ )}
386
+ <span className="text-body-medium font-semibold">
387
+ {account.name || account.institutionName || "—"}
388
+ </span>
389
+ </div>
390
+ </TableCell>
391
+ <TableCell>
392
+ <span className="text-body-medium">
393
+ {account.accountNo ?? "—"}
394
+ </span>
395
+ </TableCell>
396
+ <TableCell>
397
+ <span className="text-body-medium">
398
+ {periodLabel}
399
+ </span>
400
+ </TableCell>
401
+ <TableCell>
402
+ <span className="text-body-medium">
403
+ {account.lastUpdated
404
+ ? format(
405
+ parseISO(account.lastUpdated),
406
+ "dd MMM yyyy",
407
+ )
408
+ : "—"}
409
+ </span>
410
+ </TableCell>
411
+ </TableRow>
412
+ ))}
413
+ </TableBody>
414
+ </Table>
415
+ )}
416
+ </div>
417
+ )}
418
+ </div>
419
+
420
+ <DialogFooter>
421
+ <Button variant="ghost" onClick={onClose}>
422
+ Cancel
423
+ </Button>
424
+ <Button
425
+ onClick={handleSubmit}
426
+ disabled={isSubmitDisabled}
427
+ loading={isLoading}
428
+ >
429
+ Generate
430
+ </Button>
431
+ </DialogFooter>
432
+ </DialogContent>
433
+ </Dialog>
434
+ );
435
+ }