@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.
- package/.turbo/turbo-build.log +360 -180
- package/CHANGELOG.md +6 -0
- package/dist/chunk-2A53WPEC.mjs +182 -0
- package/dist/{chunk-SIVYAI3M.mjs → chunk-2LLFNGJZ.mjs} +15 -15
- package/dist/chunk-2QNOPXMQ.mjs +360 -0
- package/dist/{chunk-K5QV4TT6.mjs → chunk-2WCIORP7.mjs} +29 -4
- package/dist/{chunk-5NF6T2RS.mjs → chunk-3AREQTZU.mjs} +8 -8
- package/dist/{chunk-2EM2FRU6.mjs → chunk-3WGFIFP6.mjs} +5 -5
- package/dist/{chunk-K4KOD3KR.mjs → chunk-42NEC57Y.mjs} +44 -25
- package/dist/{chunk-FL6DZFJK.mjs → chunk-46Q4335I.mjs} +121 -39
- package/dist/chunk-4DO3WM7V.mjs +48 -0
- package/dist/chunk-5FHBC6DY.mjs +68 -0
- package/dist/chunk-5SAYZ4CI.mjs +40 -0
- package/dist/chunk-5WMFKQZ6.mjs +180 -0
- package/dist/chunk-623YVI5O.mjs +43 -0
- package/dist/{chunk-SFH2NJEJ.mjs → chunk-6OSULDEO.mjs} +3 -3
- package/dist/{chunk-UALR6JGV.mjs → chunk-6SR4K5T5.mjs} +1 -1
- package/dist/{chunk-D2NSIIXG.mjs → chunk-7KT5HPYM.mjs} +11 -11
- package/dist/chunk-A6ER36CW.mjs +456 -0
- package/dist/{chunk-QX7IFQSF.mjs → chunk-AHKHVBWR.mjs} +4 -4
- package/dist/chunk-AHSCWXYJ.mjs +113 -0
- package/dist/{chunk-7GWRPXHD.mjs → chunk-AL6GOL2Y.mjs} +1 -1
- package/dist/{chunk-OIKBW2QD.mjs → chunk-AUEUTZIC.mjs} +13 -13
- package/dist/{chunk-FYPSTTEJ.mjs → chunk-B7DD3ODQ.mjs} +1 -1
- package/dist/{chunk-TLAWKTSA.mjs → chunk-BD3DWDT4.mjs} +3 -3
- package/dist/{chunk-S2FKV4M5.mjs → chunk-BDESHD25.mjs} +4 -4
- package/dist/{chunk-OKTJFDPN.mjs → chunk-BFB3UH7V.mjs} +2 -2
- package/dist/{chunk-DGNHGNYH.mjs → chunk-C6SWS7OW.mjs} +1 -1
- package/dist/chunk-CDVG7SFT.mjs +271 -0
- package/dist/chunk-CUSHAIUL.mjs +109 -0
- package/dist/{chunk-QXKGOMUX.mjs → chunk-CW32WTZU.mjs} +4 -4
- package/dist/{chunk-SET2ANTY.mjs → chunk-D447W45Z.mjs} +3 -3
- package/dist/{chunk-RCAOCHWA.mjs → chunk-DFL5CV75.mjs} +18 -18
- package/dist/chunk-DYSVJ473.mjs +162 -0
- package/dist/chunk-E3PQDBYI.mjs +288 -0
- package/dist/chunk-EMYBNPIA.mjs +83 -0
- package/dist/chunk-EUYPMDQG.mjs +348 -0
- package/dist/{chunk-XYPW2XA5.mjs → chunk-EW72FINW.mjs} +11 -11
- package/dist/chunk-F24U4QQQ.mjs +234 -0
- package/dist/{chunk-VB5M6OZQ.mjs → chunk-F4O2YPXJ.mjs} +1 -1
- package/dist/chunk-FFXTQTB4.mjs +84 -0
- package/dist/{chunk-ZOWL2L5J.mjs → chunk-FYUSF5KO.mjs} +5 -1
- package/dist/{chunk-FTPBQVQ6.mjs → chunk-GNER6MCO.mjs} +1 -1
- package/dist/{chunk-2D3HQPFN.mjs → chunk-HF4FUBCY.mjs} +5 -5
- package/dist/{chunk-RSUIPKGX.mjs → chunk-HNDTLT5X.mjs} +1 -1
- package/dist/{chunk-N6Q5IPKT.mjs → chunk-HO6S3ECM.mjs} +46 -18
- package/dist/{chunk-L4NSRQ3T.mjs → chunk-HROG643K.mjs} +1 -1
- package/dist/chunk-I2EKKSEF.mjs +148 -0
- package/dist/{chunk-QTRSCVQ3.mjs → chunk-I3UDLWQ7.mjs} +1 -1
- package/dist/{chunk-AE7MASLF.mjs → chunk-IQGKOT7A.mjs} +9 -6
- package/dist/chunk-IXR4BQSQ.mjs +290 -0
- package/dist/{chunk-4MM7LHM5.mjs → chunk-J5NW5NCT.mjs} +1 -1
- package/dist/{chunk-OLKMCXAR.mjs → chunk-JTG5R5YV.mjs} +24 -24
- package/dist/chunk-JUBUN65Q.mjs +106 -0
- package/dist/chunk-K7TWMLLW.mjs +520 -0
- package/dist/{chunk-BOW7U26Y.mjs → chunk-K7WSRWOU.mjs} +4 -4
- package/dist/{chunk-NTYQWVLI.mjs → chunk-KAD26MCC.mjs} +1 -1
- package/dist/{chunk-KCWNDYPZ.mjs → chunk-KB7MZMED.mjs} +4 -4
- package/dist/chunk-KCKYGQVQ.mjs +61 -0
- package/dist/{chunk-VY5NEUP7.mjs → chunk-KLJLDNCA.mjs} +1 -1
- package/dist/chunk-LLAGF6BA.mjs +49 -0
- package/dist/{chunk-G27TSQLQ.mjs → chunk-M4LTX3MH.mjs} +1 -1
- package/dist/{chunk-YIZHS72Z.mjs → chunk-MHHA7QGO.mjs} +94 -54
- package/dist/{chunk-P2N2PEFY.mjs → chunk-NCUH54IZ.mjs} +4 -4
- package/dist/{chunk-PNRUH7JY.mjs → chunk-OECGKCVF.mjs} +5 -5
- package/dist/{chunk-YE67AALL.mjs → chunk-OL65UQHQ.mjs} +10 -10
- package/dist/{chunk-LQULK2E3.mjs → chunk-OYBIUEGE.mjs} +1 -1
- package/dist/{chunk-LR6LHDP3.mjs → chunk-PGR53HMH.mjs} +7 -7
- package/dist/chunk-PUJ42INK.mjs +141 -0
- package/dist/{chunk-M4VYX2PV.mjs → chunk-PV3Y7QGK.mjs} +2 -2
- package/dist/{chunk-UJZ4UHWI.mjs → chunk-PV7PNA6K.mjs} +4 -4
- package/dist/{chunk-6HIOM2HL.mjs → chunk-Q35PNFJ7.mjs} +1 -1
- package/dist/{chunk-JZY6TNIS.mjs → chunk-Q5SGEIJV.mjs} +27 -27
- package/dist/{chunk-ZFCDYW6N.mjs → chunk-QAX6HCUH.mjs} +1 -1
- package/dist/chunk-QHJDGB54.mjs +135 -0
- package/dist/chunk-QQSOZQOC.mjs +27 -0
- package/dist/chunk-RUX3OLVZ.mjs +59 -0
- package/dist/{chunk-QOJ2DQD6.mjs → chunk-S4CTM3UE.mjs} +5 -0
- package/dist/{chunk-ZEDMKQK2.mjs → chunk-TAX3KL66.mjs} +1 -1
- package/dist/chunk-TC43SMIN.mjs +133 -0
- package/dist/chunk-TGVXRD53.mjs +174 -0
- package/dist/{chunk-K5VHK7CM.mjs → chunk-TLYSVRSK.mjs} +12 -12
- package/dist/{chunk-YCWLFG27.mjs → chunk-TOIVHWNC.mjs} +1 -1
- package/dist/chunk-TXUBGKB7.mjs +160 -0
- package/dist/chunk-UEREFDAE.mjs +75 -0
- package/dist/chunk-UTCQN6XU.mjs +123 -0
- package/dist/{chunk-37AE3OM5.mjs → chunk-V4CUTCHS.mjs} +4 -4
- package/dist/{chunk-THVO2N47.mjs → chunk-VFH632TB.mjs} +9 -9
- package/dist/{chunk-3ERBUVHC.mjs → chunk-VJ3GC7W3.mjs} +95 -49
- package/dist/{chunk-V6XGXYCJ.mjs → chunk-VLELWBEW.mjs} +4 -4
- package/dist/{chunk-FEZKMUCF.mjs → chunk-WDTXHLYM.mjs} +1 -1
- package/dist/chunk-WUA546RX.mjs +129 -0
- package/dist/chunk-XHGISOX5.mjs +257 -0
- package/dist/chunk-XIY5DJXI.mjs +168 -0
- package/dist/{chunk-TOWTPLRC.mjs → chunk-XN37434W.mjs} +8 -8
- package/dist/{chunk-KLTACJ2G.mjs → chunk-XTWAJWCQ.mjs} +1 -1
- package/dist/chunk-Y24TXIFJ.mjs +518 -0
- package/dist/{chunk-DMXYRCHM.mjs → chunk-Y6UM3VTN.mjs} +4 -4
- package/dist/components/ui/about-you-form.js +1120 -0
- package/dist/components/ui/about-you-form.mjs +323 -0
- package/dist/components/ui/account-list-carousel.js +304 -0
- package/dist/components/ui/account-list-carousel.mjs +11 -0
- package/dist/components/ui/add-column-modal.js +1 -1
- package/dist/components/ui/add-column-modal.mjs +6 -6
- package/dist/components/ui/add-lead-modal.js +2 -2
- package/dist/components/ui/add-lead-modal.mjs +6 -6
- package/dist/components/ui/advisor-card.mjs +2 -2
- package/dist/components/ui/agent-evaluation-toast.js +299 -0
- package/dist/components/ui/agent-evaluation-toast.mjs +12 -0
- package/dist/components/ui/ai-assistant-drawer.mjs +5 -5
- package/dist/components/ui/ai-builder.js +3 -3
- package/dist/components/ui/ai-builder.mjs +5 -5
- package/dist/components/ui/ai-conversations.js +2 -2
- package/dist/components/ui/ai-conversations.mjs +11 -11
- package/dist/components/ui/alert-dialog.mjs +3 -3
- package/dist/components/ui/applicant-document-checklist.js +346 -0
- package/dist/components/ui/applicant-document-checklist.mjs +10 -0
- package/dist/components/ui/applicant-expenses-section.js +455 -0
- package/dist/components/ui/applicant-expenses-section.mjs +220 -0
- package/dist/components/ui/applicant-navigation-bar.js +309 -0
- package/dist/components/ui/applicant-navigation-bar.mjs +87 -0
- package/dist/components/ui/applicant-switcher.js +268 -0
- package/dist/components/ui/applicant-switcher.mjs +46 -0
- package/dist/components/ui/application-mobile-layout.js +88 -0
- package/dist/components/ui/application-mobile-layout.mjs +8 -0
- package/dist/components/ui/appointment-action-dialogs.js +1 -1
- package/dist/components/ui/appointment-action-dialogs.mjs +10 -10
- package/dist/components/ui/appointment-availability-settings.js +78 -31
- package/dist/components/ui/appointment-availability-settings.mjs +12 -10
- package/dist/components/ui/appointment-book-dialog.js +137 -58
- package/dist/components/ui/appointment-book-dialog.mjs +14 -14
- package/dist/components/ui/appointment-calendar-view.js +1 -1
- package/dist/components/ui/appointment-calendar-view.mjs +4 -4
- package/dist/components/ui/appointment-detail-sheet.js +38 -11
- package/dist/components/ui/appointment-detail-sheet.mjs +13 -13
- package/dist/components/ui/appointment-gmail-connect.mjs +2 -2
- package/dist/components/ui/appointment-time-slot-picker.mjs +2 -2
- package/dist/components/ui/appointment-upcoming-card.js +1 -1
- package/dist/components/ui/appointment-upcoming-card.mjs +10 -10
- package/dist/components/ui/asset-accordion.js +506 -0
- package/dist/components/ui/asset-accordion.mjs +202 -0
- package/dist/components/ui/assets-liabilities-side-card.js +328 -0
- package/dist/components/ui/assets-liabilities-side-card.mjs +127 -0
- package/dist/components/ui/auth-page-layout.js +3 -3
- package/dist/components/ui/auth-page-layout.mjs +1 -1
- package/dist/components/ui/backoffice-alert-history-chart.mjs +4 -4
- package/dist/components/ui/backoffice-alert-matching-chart.js +786 -0
- package/dist/components/ui/backoffice-alert-matching-chart.mjs +19 -0
- package/dist/components/ui/backoffice-alerts-chart.mjs +4 -4
- package/dist/components/ui/backoffice-connections-chart.mjs +4 -4
- package/dist/components/ui/backoffice-contact-history-chart.mjs +4 -4
- package/dist/components/ui/backoffice-contact-matching-chart.js +803 -0
- package/dist/components/ui/backoffice-contact-matching-chart.mjs +19 -0
- package/dist/components/ui/backoffice-signup-steps.js +1673 -0
- package/dist/components/ui/backoffice-signup-steps.mjs +36 -0
- package/dist/components/ui/bank-statement-document-table.js +467 -0
- package/dist/components/ui/bank-statement-document-table.mjs +12 -0
- package/dist/components/ui/bank-statement-generate-dialog.js +1517 -0
- package/dist/components/ui/bank-statement-generate-dialog.mjs +27 -0
- package/dist/components/ui/bank-statement-pdf-viewer.js +525 -0
- package/dist/components/ui/bank-statement-pdf-viewer.mjs +14 -0
- package/dist/components/ui/banking-accounts-connect.js +336 -0
- package/dist/components/ui/banking-accounts-connect.mjs +114 -0
- package/dist/components/ui/borrowing-capacity-atoms.js +382 -0
- package/dist/components/ui/borrowing-capacity-atoms.mjs +17 -0
- package/dist/components/ui/borrowing-capacity-card.js +835 -0
- package/dist/components/ui/borrowing-capacity-card.mjs +89 -0
- package/dist/components/ui/borrowing-capacity-line-chart.mjs +4 -4
- package/dist/components/ui/broker-info-panel.js +281 -0
- package/dist/components/ui/broker-info-panel.mjs +59 -0
- package/dist/components/ui/calculator-input-item.js +101 -0
- package/dist/components/ui/calculator-input-item.mjs +8 -0
- package/dist/components/ui/calculator-section.js +743 -0
- package/dist/components/ui/calculator-section.mjs +220 -0
- package/dist/components/ui/calendar.mjs +2 -2
- package/dist/components/ui/cash-balance-line-chart.mjs +5 -5
- package/dist/components/ui/cashflow-bar-chart.mjs +4 -4
- package/dist/components/ui/category-edit-dialog.js +737 -0
- package/dist/components/ui/category-edit-dialog.mjs +16 -0
- package/dist/components/ui/chat-widget.mjs +3 -3
- package/dist/components/ui/color-picker.mjs +4 -4
- package/dist/components/ui/connect-bank-step.js +511 -0
- package/dist/components/ui/connect-bank-step.mjs +287 -0
- package/dist/components/ui/contact-alert-dialog.js +1405 -0
- package/dist/components/ui/contact-alert-dialog.mjs +27 -0
- package/dist/components/ui/create-contact-modal.js +1028 -0
- package/dist/components/ui/create-contact-modal.mjs +21 -0
- package/dist/components/ui/csv-import-modal.js +583 -0
- package/dist/components/ui/csv-import-modal.mjs +14 -0
- package/dist/components/ui/currency-input.js +439 -0
- package/dist/components/ui/currency-input.mjs +13 -0
- package/dist/components/ui/dashboard-expense-categories.js +355 -0
- package/dist/components/ui/dashboard-expense-categories.mjs +186 -0
- package/dist/components/ui/dashboard-transactions-table.js +1083 -0
- package/dist/components/ui/dashboard-transactions-table.mjs +177 -0
- package/dist/components/ui/data-table.mjs +6 -6
- package/dist/components/ui/date-picker.mjs +6 -6
- package/dist/components/ui/debt-accordion.js +523 -0
- package/dist/components/ui/debt-accordion.mjs +219 -0
- package/dist/components/ui/delete-contact-component.js +479 -0
- package/dist/components/ui/delete-contact-component.mjs +14 -0
- package/dist/components/ui/dialog.js +1 -1
- package/dist/components/ui/dialog.mjs +3 -3
- package/dist/components/ui/document-checklist-template.mjs +4 -4
- package/dist/components/ui/drawer.mjs +3 -3
- package/dist/components/ui/dropdown-menu.mjs +3 -3
- package/dist/components/ui/dynamic-tabs.js +274 -0
- package/dist/components/ui/dynamic-tabs.mjs +116 -0
- package/dist/components/ui/editable-money-item.js +306 -0
- package/dist/components/ui/editable-money-item.mjs +12 -0
- package/dist/components/ui/expense-bar-chart.mjs +4 -4
- package/dist/components/ui/expense-detail-item.js +506 -0
- package/dist/components/ui/expense-detail-item.mjs +15 -0
- package/dist/components/ui/expense-work-details.js +1259 -0
- package/dist/components/ui/expense-work-details.mjs +175 -0
- package/dist/components/ui/field.mjs +2 -2
- package/dist/components/ui/file-preview-dialog.js +704 -0
- package/dist/components/ui/file-preview-dialog.mjs +17 -0
- package/dist/components/ui/financial-cards.mjs +2 -2
- package/dist/components/ui/financial-drawers.js +1 -1
- package/dist/components/ui/financial-drawers.mjs +5 -5
- package/dist/components/ui/financial-sections.mjs +4 -4
- package/dist/components/ui/form-primitives.mjs +2 -2
- package/dist/components/ui/frontend-signup-steps.js +1239 -0
- package/dist/components/ui/frontend-signup-steps.mjs +38 -0
- package/dist/components/ui/income-bar-chart.mjs +4 -4
- package/dist/components/ui/income-sources-card.js +269 -0
- package/dist/components/ui/income-sources-card.mjs +100 -0
- package/dist/components/ui/income-summary-component.js +361 -0
- package/dist/components/ui/income-summary-component.mjs +84 -0
- package/dist/components/ui/income-work-details.js +1663 -0
- package/dist/components/ui/income-work-details.mjs +28 -0
- package/dist/components/ui/incoming-outgoings-card.js +218 -0
- package/dist/components/ui/incoming-outgoings-card.mjs +82 -0
- package/dist/components/ui/interest-rate-input.js +442 -0
- package/dist/components/ui/interest-rate-input.mjs +90 -0
- package/dist/components/ui/interest-rate-section.js +337 -0
- package/dist/components/ui/interest-rate-section.mjs +84 -0
- package/dist/components/ui/interest-rate-used.js +202 -0
- package/dist/components/ui/interest-rate-used.mjs +62 -0
- package/dist/components/ui/kanban-column.js +338 -160
- package/dist/components/ui/kanban-column.mjs +13 -11
- package/dist/components/ui/loan-applicant-information.js +336 -0
- package/dist/components/ui/loan-applicant-information.mjs +59 -0
- package/dist/components/ui/loan-applicant-invite.js +319 -0
- package/dist/components/ui/loan-applicant-invite.mjs +68 -0
- package/dist/components/ui/loan-application-badge.js +236 -0
- package/dist/components/ui/loan-application-badge.mjs +10 -0
- package/dist/components/ui/loan-application-cards.js +356 -0
- package/dist/components/ui/loan-application-cards.mjs +110 -0
- package/dist/components/ui/loan-entry-shell.js +104 -0
- package/dist/components/ui/loan-entry-shell.mjs +8 -0
- package/dist/components/ui/loan-financials.js +410 -0
- package/dist/components/ui/loan-financials.mjs +76 -0
- package/dist/components/ui/loan-option-card.js +102 -0
- package/dist/components/ui/loan-option-card.mjs +41 -0
- package/dist/components/ui/loan-option-group.js +288 -0
- package/dist/components/ui/loan-option-group.mjs +10 -0
- package/dist/components/ui/loan-steps.js +1121 -0
- package/dist/components/ui/loan-steps.mjs +509 -0
- package/dist/components/ui/loan-wizard-shell.js +452 -0
- package/dist/components/ui/loan-wizard-shell.mjs +11 -0
- package/dist/components/ui/money-input-with-slider.js +210 -0
- package/dist/components/ui/money-input-with-slider.mjs +10 -0
- package/dist/components/ui/money-item-with-color-indicator.js +314 -0
- package/dist/components/ui/money-item-with-color-indicator.mjs +20 -0
- package/dist/components/ui/opportunity-card.js +235 -97
- package/dist/components/ui/opportunity-card.mjs +11 -9
- package/dist/components/ui/opportunity-edit-modals.js +1 -1
- package/dist/components/ui/opportunity-edit-modals.mjs +15 -15
- package/dist/components/ui/opportunity-summary-tab.js +1 -1
- package/dist/components/ui/opportunity-summary-tab.mjs +19 -19
- package/dist/components/ui/pagination.mjs +4 -4
- package/dist/components/ui/password-strength-tooltip.mjs +4 -4
- package/dist/components/ui/pipeline-board.js +358 -176
- package/dist/components/ui/pipeline-board.mjs +16 -14
- package/dist/components/ui/pipeline-chart.mjs +3 -3
- package/dist/components/ui/pipeline-dialogs.js +1 -1
- package/dist/components/ui/pipeline-dialogs.mjs +9 -9
- package/dist/components/ui/pipeline-primitives.js +75 -8
- package/dist/components/ui/pipeline-primitives.mjs +3 -2
- package/dist/components/ui/popover.mjs +3 -3
- package/dist/components/ui/property-asset-card.js +428 -0
- package/dist/components/ui/property-asset-card.mjs +156 -0
- package/dist/components/ui/property-cashflow-doughnut-chart.mjs +4 -4
- package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +4 -4
- package/dist/components/ui/property-list-carousel.js +295 -0
- package/dist/components/ui/property-list-carousel.mjs +11 -0
- package/dist/components/ui/property-mobile-estimate-line-chart.mjs +4 -4
- package/dist/components/ui/property-report-dialog.js +1148 -0
- package/dist/components/ui/property-report-dialog.mjs +25 -0
- package/dist/components/ui/resource-center.js +748 -0
- package/dist/components/ui/resource-center.mjs +24 -0
- package/dist/components/ui/review-alerts-dialog.js +569 -0
- package/dist/components/ui/review-alerts-dialog.mjs +15 -0
- package/dist/components/ui/savings-goal-modal.js +1148 -0
- package/dist/components/ui/savings-goal-modal.mjs +160 -0
- package/dist/components/ui/scenario-drawer.js +791 -0
- package/dist/components/ui/scenario-drawer.mjs +294 -0
- package/dist/components/ui/scenario-item.js +256 -0
- package/dist/components/ui/scenario-item.mjs +11 -0
- package/dist/components/ui/scenario-list.js +507 -0
- package/dist/components/ui/scenario-list.mjs +100 -0
- package/dist/components/ui/select.mjs +3 -3
- package/dist/components/ui/share-details-dialog.js +636 -0
- package/dist/components/ui/share-details-dialog.mjs +19 -0
- package/dist/components/ui/sheet.mjs +3 -3
- package/dist/components/ui/sidebar-nav.mjs +5 -5
- package/dist/components/ui/signup-form-primitives.js +770 -0
- package/dist/components/ui/signup-form-primitives.mjs +25 -0
- package/dist/components/ui/signup-shell.js +338 -0
- package/dist/components/ui/signup-shell.mjs +13 -0
- package/dist/components/ui/stage-timeline.js +103 -33
- package/dist/components/ui/stage-timeline.mjs +5 -4
- package/dist/components/ui/submission-confirmation-card.js +284 -0
- package/dist/components/ui/submission-confirmation-card.mjs +62 -0
- package/dist/components/ui/tooltip.mjs +3 -3
- package/dist/components/ui/top-three-product.js +374 -0
- package/dist/components/ui/top-three-product.mjs +129 -0
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +4 -4
- package/dist/components/ui/transactions-income-expense-bar-chart.mjs +5 -5
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +4 -4
- package/dist/components/ui/transactions-summary-block.js +95 -0
- package/dist/components/ui/transactions-summary-block.mjs +34 -0
- package/dist/components/ui/two-fa-setup-form.mjs +3 -3
- package/dist/index.js +9430 -4573
- package/dist/index.mjs +404 -251
- package/dist/lib/colors.js +6 -0
- package/dist/lib/colors.mjs +3 -1
- package/dist/lib/theme-provider.mjs +2 -2
- package/dist/styles.css +1 -1
- package/package.json +366 -2
- package/src/components/index.tsx +223 -0
- package/src/components/ui/about-you-form.tsx +397 -0
- package/src/components/ui/account-list-carousel.tsx +87 -0
- package/src/components/ui/add-lead-modal.tsx +1 -1
- package/src/components/ui/agent-evaluation-toast.tsx +191 -0
- package/src/components/ui/ai-builder.tsx +3 -5
- package/src/components/ui/ai-conversations.tsx +1 -1
- package/src/components/ui/applicant-document-checklist.tsx +175 -0
- package/src/components/ui/applicant-expenses-section.tsx +260 -0
- package/src/components/ui/applicant-navigation-bar.tsx +104 -0
- package/src/components/ui/applicant-switcher.tsx +54 -0
- package/src/components/ui/application-mobile-layout.tsx +34 -0
- package/src/components/ui/appointment-availability-settings.tsx +115 -23
- package/src/components/ui/appointment-book-dialog.tsx +406 -259
- package/src/components/ui/appointment-calendar-view.tsx +4 -1
- package/src/components/ui/appointment-detail-sheet.tsx +59 -24
- package/src/components/ui/appointment-time-slot-picker.tsx +5 -1
- package/src/components/ui/asset-accordion.tsx +241 -0
- package/src/components/ui/assets-liabilities-side-card.tsx +157 -0
- package/src/components/ui/auth-page-layout.tsx +3 -3
- package/src/components/ui/backoffice-alert-matching-chart.tsx +320 -0
- package/src/components/ui/backoffice-contact-matching-chart.tsx +341 -0
- package/src/components/ui/backoffice-signup-steps.tsx +615 -0
- package/src/components/ui/bank-statement-document-table.tsx +222 -0
- package/src/components/ui/bank-statement-generate-dialog.tsx +435 -0
- package/src/components/ui/bank-statement-pdf-viewer.tsx +241 -0
- package/src/components/ui/banking-accounts-connect.tsx +187 -0
- package/src/components/ui/borrowing-capacity-atoms.tsx +228 -0
- package/src/components/ui/borrowing-capacity-card.tsx +155 -0
- package/src/components/ui/broker-info-panel.tsx +94 -0
- package/src/components/ui/calculator-input-item.tsx +49 -0
- package/src/components/ui/calculator-section.tsx +275 -0
- package/src/components/ui/category-edit-dialog.tsx +300 -0
- package/src/components/ui/connect-bank-step.tsx +379 -0
- package/src/components/ui/contact-alert-dialog.tsx +710 -0
- package/src/components/ui/create-contact-modal.tsx +237 -0
- package/src/components/ui/csv-import-modal.tsx +153 -0
- package/src/components/ui/currency-input.tsx +104 -0
- package/src/components/ui/dashboard-expense-categories.tsx +262 -0
- package/src/components/ui/dashboard-transactions-table.tsx +241 -0
- package/src/components/ui/debt-accordion.tsx +254 -0
- package/src/components/ui/delete-contact-component.tsx +87 -0
- package/src/components/ui/dialog.tsx +2 -2
- package/src/components/ui/dynamic-tabs.tsx +149 -0
- package/src/components/ui/editable-money-item.tsx +176 -0
- package/src/components/ui/expense-detail-item.tsx +216 -0
- package/src/components/ui/expense-work-details.tsx +229 -0
- package/src/components/ui/file-preview-dialog.tsx +292 -0
- package/src/components/ui/financial-drawers.tsx +1 -1
- package/src/components/ui/frontend-signup-steps.tsx +548 -0
- package/src/components/ui/income-sources-card.tsx +143 -0
- package/src/components/ui/income-summary-component.tsx +120 -0
- package/src/components/ui/income-work-details.tsx +429 -0
- package/src/components/ui/incoming-outgoings-card.tsx +111 -0
- package/src/components/ui/interest-rate-input.tsx +111 -0
- package/src/components/ui/interest-rate-section.tsx +158 -0
- package/src/components/ui/interest-rate-used.tsx +82 -0
- package/src/components/ui/kanban-column.tsx +53 -2
- package/src/components/ui/loan-applicant-information.tsx +64 -0
- package/src/components/ui/loan-applicant-invite.tsx +67 -0
- package/src/components/ui/loan-application-badge.tsx +70 -0
- package/src/components/ui/loan-application-cards.tsx +152 -0
- package/src/components/ui/loan-entry-shell.tsx +86 -0
- package/src/components/ui/loan-financials.tsx +77 -0
- package/src/components/ui/loan-option-card.tsx +62 -0
- package/src/components/ui/loan-option-group.tsx +106 -0
- package/src/components/ui/loan-steps.tsx +630 -0
- package/src/components/ui/loan-wizard-shell.tsx +235 -0
- package/src/components/ui/money-input-with-slider.tsx +77 -0
- package/src/components/ui/money-item-with-color-indicator.tsx +30 -0
- package/src/components/ui/opportunity-card.tsx +46 -18
- package/src/components/ui/pipeline-board.tsx +13 -0
- package/src/components/ui/pipeline-primitives.tsx +28 -0
- package/src/components/ui/property-asset-card.tsx +221 -0
- package/src/components/ui/property-list-carousel.tsx +73 -0
- package/src/components/ui/property-report-dialog.tsx +355 -0
- package/src/components/ui/resource-center.tsx +539 -0
- package/src/components/ui/review-alerts-dialog.tsx +163 -0
- package/src/components/ui/savings-goal-modal.tsx +169 -0
- package/src/components/ui/scenario-drawer.tsx +358 -0
- package/src/components/ui/scenario-item.tsx +141 -0
- package/src/components/ui/scenario-list.tsx +150 -0
- package/src/components/ui/share-details-dialog.tsx +238 -0
- package/src/components/ui/signup-form-primitives.tsx +212 -0
- package/src/components/ui/signup-shell.tsx +180 -0
- package/src/components/ui/stage-timeline.tsx +11 -0
- package/src/components/ui/submission-confirmation-card.tsx +68 -0
- package/src/components/ui/top-three-product.tsx +207 -0
- package/src/components/ui/transactions-summary-block.tsx +59 -0
- package/src/lib/colors.ts +12 -0
- package/src/lib/format-date.ts +2 -2
- package/src/styles/styles-css.ts +1 -1
- package/tsup.config.ts +77 -1
- package/dist/{chunk-5VOTTIXF.mjs → chunk-FRT3S72S.mjs} +3 -3
- package/dist/{chunk-7BTFGCFC.mjs → chunk-MUV4EGDW.mjs} +3 -3
- package/dist/{chunk-57ZXILTS.mjs → chunk-MXP2RX2V.mjs} +3 -3
- package/dist/{chunk-ZKWXDQDG.mjs → chunk-VCDGLN25.mjs} +3 -3
- package/dist/{chunk-FLL633WS.mjs → chunk-ZXEUBBHJ.mjs} +3 -3
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { ChevronLeft, ChevronRight, Download, X } from "lucide-react";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
|
6
|
+
import { Spinner } from "@/components/ui/spinner";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* BankStatementPDFViewer — WealthX DS (L4 Template)
|
|
10
|
+
*
|
|
11
|
+
* Full-viewport dialog for viewing a bank statement PDF.
|
|
12
|
+
* Supports paging through multiple accounts using prev / next navigation.
|
|
13
|
+
*
|
|
14
|
+
* PDF rendering:
|
|
15
|
+
* - Embeds the blob via `URL.createObjectURL(pdfBlob) + "#toolbar=0"` in an
|
|
16
|
+
* `<iframe>` so the browser's native PDF plugin renders it without toolbar.
|
|
17
|
+
* - Object URL is revoked automatically when the blob changes.
|
|
18
|
+
*
|
|
19
|
+
* Typical usage in the Bank Statement tab:
|
|
20
|
+
* 1. User clicks a document name in `BankStatementDocumentTable`.
|
|
21
|
+
* 2. Consumer fetches the PDF blob for each linked account.
|
|
22
|
+
* 3. `BankStatementPDFViewer` is mounted with `open={true}`.
|
|
23
|
+
* 4. User pages through accounts with ‹ / ›; download icon triggers a direct
|
|
24
|
+
* browser download of the current blob.
|
|
25
|
+
*
|
|
26
|
+
* Layer: L4 Template
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Types
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
export interface BankStatementViewerAccount {
|
|
34
|
+
id: string;
|
|
35
|
+
/** Account display name (e.g. "Everyday Savings"). */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** Institution name fallback (e.g. "CommBank"). */
|
|
38
|
+
institutionName?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface BankStatementPDFViewerProps {
|
|
42
|
+
open: boolean;
|
|
43
|
+
onClose: () => void;
|
|
44
|
+
/** Raw PDF blob for the currently viewed document. `null` shows an empty state. */
|
|
45
|
+
pdfBlob: Blob | null;
|
|
46
|
+
/** Filename used for the browser download, e.g. "CommBank_James_90days.pdf". */
|
|
47
|
+
pdfFilename?: string;
|
|
48
|
+
/** All accounts linked to this statement (for prev/next navigation). */
|
|
49
|
+
accounts: BankStatementViewerAccount[];
|
|
50
|
+
/** Zero-based index of the currently viewed account. */
|
|
51
|
+
currentAccountIndex: number;
|
|
52
|
+
/** Called when the user clicks ‹ / › to navigate between accounts. */
|
|
53
|
+
onAccountChange: (index: number) => void;
|
|
54
|
+
className?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// BankStatementPDFViewer
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
export function BankStatementPDFViewer({
|
|
62
|
+
open,
|
|
63
|
+
onClose,
|
|
64
|
+
pdfBlob,
|
|
65
|
+
pdfFilename,
|
|
66
|
+
accounts,
|
|
67
|
+
currentAccountIndex,
|
|
68
|
+
onAccountChange,
|
|
69
|
+
className,
|
|
70
|
+
}: BankStatementPDFViewerProps) {
|
|
71
|
+
const [loading, setLoading] = useState(true);
|
|
72
|
+
const [error, setError] = useState<string | null>(null);
|
|
73
|
+
const previousUrlRef = useRef<string | null>(null);
|
|
74
|
+
|
|
75
|
+
// Create an object URL from the blob (memoised; revoked when blob changes)
|
|
76
|
+
const pdfUrl = useMemo(() => {
|
|
77
|
+
if (!pdfBlob) return null;
|
|
78
|
+
return `${URL.createObjectURL(pdfBlob)}#toolbar=0`;
|
|
79
|
+
}, [pdfBlob]);
|
|
80
|
+
|
|
81
|
+
// Revoke the previous URL when the blob changes to avoid memory leaks
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
return () => {
|
|
84
|
+
if (pdfUrl) {
|
|
85
|
+
// Strip the #toolbar=0 fragment before revoking
|
|
86
|
+
URL.revokeObjectURL(pdfUrl.split("#")[0]);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}, [pdfUrl]);
|
|
90
|
+
|
|
91
|
+
// Reset loading state when the URL (blob or account) changes
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!pdfUrl) {
|
|
94
|
+
setLoading(false);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (previousUrlRef.current !== pdfUrl) {
|
|
99
|
+
previousUrlRef.current = pdfUrl;
|
|
100
|
+
setLoading(true);
|
|
101
|
+
setError(null);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Fallback: hide spinner after 2 s even if onLoad never fires (e.g. Firefox)
|
|
105
|
+
const timer = setTimeout(() => setLoading(false), 2000);
|
|
106
|
+
return () => clearTimeout(timer);
|
|
107
|
+
}, [pdfUrl, currentAccountIndex]);
|
|
108
|
+
|
|
109
|
+
// ── Navigation ────────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
const canGoPrev = currentAccountIndex > 0;
|
|
112
|
+
const canGoNext = currentAccountIndex < accounts.length - 1;
|
|
113
|
+
|
|
114
|
+
const currentAccount = accounts[currentAccountIndex];
|
|
115
|
+
const accountLabel =
|
|
116
|
+
currentAccount?.name ?? currentAccount?.institutionName ?? "Account";
|
|
117
|
+
|
|
118
|
+
// ── Download ──────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
const handleDownload = () => {
|
|
121
|
+
if (!pdfBlob) return;
|
|
122
|
+
const filename = pdfFilename ?? "bank-statement.pdf";
|
|
123
|
+
const url = URL.createObjectURL(pdfBlob);
|
|
124
|
+
const anchor = document.createElement("a");
|
|
125
|
+
anchor.href = url;
|
|
126
|
+
anchor.download = filename;
|
|
127
|
+
document.body.appendChild(anchor);
|
|
128
|
+
anchor.click();
|
|
129
|
+
document.body.removeChild(anchor);
|
|
130
|
+
URL.revokeObjectURL(url);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// ── Render ────────────────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<Dialog open={open} onOpenChange={(o) => !o && onClose()}>
|
|
137
|
+
<DialogContent
|
|
138
|
+
showCloseButton={false}
|
|
139
|
+
className={cn(
|
|
140
|
+
"flex h-[95vh] max-h-[95vh] w-[95vw] max-w-[95vw] flex-col gap-0 p-0",
|
|
141
|
+
className,
|
|
142
|
+
)}
|
|
143
|
+
data-slot="bank-statement-pdf-viewer"
|
|
144
|
+
>
|
|
145
|
+
{/* Navigation bar */}
|
|
146
|
+
<div className="flex shrink-0 items-center justify-between border-b border-border px-3 py-2">
|
|
147
|
+
<div className="flex items-center gap-2">
|
|
148
|
+
<Button
|
|
149
|
+
variant="ghost"
|
|
150
|
+
size="icon-sm"
|
|
151
|
+
aria-label="Previous account"
|
|
152
|
+
onClick={() => onAccountChange(currentAccountIndex - 1)}
|
|
153
|
+
disabled={!canGoPrev}
|
|
154
|
+
>
|
|
155
|
+
<ChevronLeft className="size-4" />
|
|
156
|
+
</Button>
|
|
157
|
+
|
|
158
|
+
<span className="text-body-medium tabular-nums">
|
|
159
|
+
Account {currentAccountIndex + 1} of {accounts.length}
|
|
160
|
+
</span>
|
|
161
|
+
|
|
162
|
+
<Button
|
|
163
|
+
variant="ghost"
|
|
164
|
+
size="icon-sm"
|
|
165
|
+
aria-label="Next account"
|
|
166
|
+
onClick={() => onAccountChange(currentAccountIndex + 1)}
|
|
167
|
+
disabled={!canGoNext}
|
|
168
|
+
>
|
|
169
|
+
<ChevronRight className="size-4" />
|
|
170
|
+
</Button>
|
|
171
|
+
|
|
172
|
+
<span className="ml-2 text-body-medium text-muted-foreground">
|
|
173
|
+
{accountLabel}
|
|
174
|
+
</span>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<div className="flex items-center gap-1">
|
|
178
|
+
<Button
|
|
179
|
+
variant="ghost"
|
|
180
|
+
size="icon-sm"
|
|
181
|
+
aria-label="Download PDF"
|
|
182
|
+
onClick={handleDownload}
|
|
183
|
+
disabled={!pdfBlob}
|
|
184
|
+
>
|
|
185
|
+
<Download className="size-4" />
|
|
186
|
+
</Button>
|
|
187
|
+
<Button
|
|
188
|
+
variant="ghost"
|
|
189
|
+
size="icon-sm"
|
|
190
|
+
aria-label="Close viewer"
|
|
191
|
+
onClick={onClose}
|
|
192
|
+
>
|
|
193
|
+
<X className="size-4" />
|
|
194
|
+
</Button>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
{/* PDF area */}
|
|
199
|
+
<div className="relative flex flex-1 items-start justify-center overflow-auto bg-muted">
|
|
200
|
+
{!pdfBlob ? (
|
|
201
|
+
<div className="flex h-full w-full items-center justify-center">
|
|
202
|
+
<p className="text-body-medium text-muted-foreground">
|
|
203
|
+
No PDF document available
|
|
204
|
+
</p>
|
|
205
|
+
</div>
|
|
206
|
+
) : (
|
|
207
|
+
<>
|
|
208
|
+
{loading && (
|
|
209
|
+
<div className="absolute left-1/2 top-1/2 z-10 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center gap-2">
|
|
210
|
+
<Spinner />
|
|
211
|
+
<p className="text-body-medium text-muted-foreground">
|
|
212
|
+
Loading PDF…
|
|
213
|
+
</p>
|
|
214
|
+
</div>
|
|
215
|
+
)}
|
|
216
|
+
|
|
217
|
+
{error && !loading && (
|
|
218
|
+
<div className="absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2">
|
|
219
|
+
<p className="text-body-medium text-destructive">{error}</p>
|
|
220
|
+
</div>
|
|
221
|
+
)}
|
|
222
|
+
|
|
223
|
+
<iframe
|
|
224
|
+
key={pdfUrl ?? "no-url"}
|
|
225
|
+
src={pdfUrl ?? undefined}
|
|
226
|
+
className="min-h-full w-full max-w-[1000px] border-none transition-opacity duration-300"
|
|
227
|
+
style={{ opacity: loading ? 0 : 1 }}
|
|
228
|
+
title="Bank Statement PDF"
|
|
229
|
+
onLoad={() => setLoading(false)}
|
|
230
|
+
onError={() => {
|
|
231
|
+
setLoading(false);
|
|
232
|
+
setError("Failed to load PDF");
|
|
233
|
+
}}
|
|
234
|
+
/>
|
|
235
|
+
</>
|
|
236
|
+
)}
|
|
237
|
+
</div>
|
|
238
|
+
</DialogContent>
|
|
239
|
+
</Dialog>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
|
|
5
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
export type BankAccountItem = {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
balance?: string;
|
|
11
|
+
institutionName?: string;
|
|
12
|
+
institutionLogoUrl?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type BankAccountCategory =
|
|
16
|
+
| "banking"
|
|
17
|
+
| "home-loan"
|
|
18
|
+
| "credit-card"
|
|
19
|
+
| "personal-loan";
|
|
20
|
+
|
|
21
|
+
export type BankAccountsByCategory = Partial<
|
|
22
|
+
Record<BankAccountCategory, BankAccountItem[]>
|
|
23
|
+
>;
|
|
24
|
+
|
|
25
|
+
export type BankingAccountsConnectApplicant = {
|
|
26
|
+
name: string;
|
|
27
|
+
email?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type BankingAccountsConnectProps = {
|
|
31
|
+
applicant: BankingAccountsConnectApplicant;
|
|
32
|
+
/** Connected accounts grouped by category. All accounts are flattened and shown in a single grid. */
|
|
33
|
+
accountsByCategory?: BankAccountsByCategory;
|
|
34
|
+
/** Called when the "Connect Your Bank +" tile is clicked. */
|
|
35
|
+
onConnectBank?: () => void;
|
|
36
|
+
onNext?: () => void;
|
|
37
|
+
onPrev?: () => void;
|
|
38
|
+
/** Hide the built-in Previous/Next navigation row — use when the parent wizard shell provides navigation. */
|
|
39
|
+
hideNavigation?: boolean;
|
|
40
|
+
className?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// ─── Component ────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* BankingAccountsConnect — shown on the Connections tab when the applicant
|
|
47
|
+
* already has at least one bank account connected.
|
|
48
|
+
*
|
|
49
|
+
* Renders all connected accounts as horizontal card tiles plus a
|
|
50
|
+
* "Connect Your Bank +" tile to add more. Layout mirrors the bank-selection
|
|
51
|
+
* grid in ConnectBankStep.
|
|
52
|
+
*
|
|
53
|
+
* Figma: WealthX-Backoffice---Mobile-App — node 19308:53046 (Connection section)
|
|
54
|
+
*/
|
|
55
|
+
export function BankingAccountsConnect({
|
|
56
|
+
accountsByCategory = {},
|
|
57
|
+
onConnectBank,
|
|
58
|
+
onNext,
|
|
59
|
+
onPrev,
|
|
60
|
+
hideNavigation = false,
|
|
61
|
+
className,
|
|
62
|
+
}: BankingAccountsConnectProps) {
|
|
63
|
+
// Flatten all category accounts into a single list for display
|
|
64
|
+
const allAccounts = ([] as BankAccountItem[]).concat(
|
|
65
|
+
...Object.values(accountsByCategory),
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div className={cn("flex flex-col gap-6 font-sans", className)}>
|
|
70
|
+
{/* Heading with left accent bar */}
|
|
71
|
+
<div className="border-l-4 border-primary pl-3">
|
|
72
|
+
<h2 className="text-h3 text-foreground">
|
|
73
|
+
Connect Available Banking Information
|
|
74
|
+
</h2>
|
|
75
|
+
<p className="mt-1 text-body-small text-muted-foreground">
|
|
76
|
+
This will help auto populate your application form and remove the need
|
|
77
|
+
to upload bank statements.
|
|
78
|
+
</p>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
{/* Connected accounts grid */}
|
|
82
|
+
<div className="flex flex-col gap-3">
|
|
83
|
+
<h3 className="text-label-large text-foreground">
|
|
84
|
+
Your Connected Accounts
|
|
85
|
+
</h3>
|
|
86
|
+
|
|
87
|
+
{/* 3-column tile grid — same border-collapse trick as ConnectBankStep */}
|
|
88
|
+
<div className="grid grid-cols-3 border-l border-t border-border">
|
|
89
|
+
{allAccounts.map((account: BankAccountItem) => (
|
|
90
|
+
<div
|
|
91
|
+
key={account.id}
|
|
92
|
+
className="flex h-[82px] items-center gap-3 border-b border-r border-border bg-background p-3"
|
|
93
|
+
>
|
|
94
|
+
{/* Institution logo or abbreviation */}
|
|
95
|
+
{account.institutionLogoUrl ? (
|
|
96
|
+
<img
|
|
97
|
+
src={account.institutionLogoUrl}
|
|
98
|
+
alt={account.institutionName ?? ""}
|
|
99
|
+
className="size-[50px] shrink-0 object-contain"
|
|
100
|
+
/>
|
|
101
|
+
) : (
|
|
102
|
+
<div className="flex size-[50px] shrink-0 items-center justify-center bg-muted text-caption text-muted-foreground">
|
|
103
|
+
{account.institutionName?.[0] ?? "?"}
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
|
|
107
|
+
{/* Account name + balance */}
|
|
108
|
+
<div className="flex min-w-0 flex-col">
|
|
109
|
+
<span className="truncate text-body-small text-foreground">
|
|
110
|
+
{account.name}
|
|
111
|
+
</span>
|
|
112
|
+
{account.balance && (
|
|
113
|
+
<span className="text-label-small text-foreground">
|
|
114
|
+
{account.balance}
|
|
115
|
+
</span>
|
|
116
|
+
)}
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
))}
|
|
120
|
+
|
|
121
|
+
{/* "Connect Your Bank +" tile */}
|
|
122
|
+
<button
|
|
123
|
+
type="button"
|
|
124
|
+
onClick={onConnectBank}
|
|
125
|
+
className="flex h-[82px] items-center justify-center gap-1.5 border-b border-r border-border bg-background p-3 transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
|
126
|
+
>
|
|
127
|
+
<span className="text-body-small font-bold text-foreground">
|
|
128
|
+
Connect Your Bank +
|
|
129
|
+
</span>
|
|
130
|
+
</button>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{/* Navigation — hidden when the parent wizard shell owns navigation */}
|
|
135
|
+
{!hideNavigation && (
|
|
136
|
+
<div className="flex items-center justify-between border-t border-border pt-4">
|
|
137
|
+
<Button variant="outline" onClick={onPrev}>
|
|
138
|
+
<ChevronLeftIcon className="mr-1 size-4" />
|
|
139
|
+
Previous
|
|
140
|
+
</Button>
|
|
141
|
+
<Button onClick={onNext}>
|
|
142
|
+
Next
|
|
143
|
+
<ChevronRightIcon className="ml-1 size-4" />
|
|
144
|
+
</Button>
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ─── Icons ────────────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
function ChevronLeftIcon({ className }: { className?: string }) {
|
|
154
|
+
return (
|
|
155
|
+
<svg
|
|
156
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
157
|
+
viewBox="0 0 24 24"
|
|
158
|
+
fill="none"
|
|
159
|
+
stroke="currentColor"
|
|
160
|
+
strokeWidth={2}
|
|
161
|
+
strokeLinecap="round"
|
|
162
|
+
strokeLinejoin="round"
|
|
163
|
+
className={className}
|
|
164
|
+
aria-hidden="true"
|
|
165
|
+
>
|
|
166
|
+
<path d="m15 18-6-6 6-6" />
|
|
167
|
+
</svg>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function ChevronRightIcon({ className }: { className?: string }) {
|
|
172
|
+
return (
|
|
173
|
+
<svg
|
|
174
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
175
|
+
viewBox="0 0 24 24"
|
|
176
|
+
fill="none"
|
|
177
|
+
stroke="currentColor"
|
|
178
|
+
strokeWidth={2}
|
|
179
|
+
strokeLinecap="round"
|
|
180
|
+
strokeLinejoin="round"
|
|
181
|
+
className={className}
|
|
182
|
+
aria-hidden="true"
|
|
183
|
+
>
|
|
184
|
+
<path d="m9 18 6-6-6-6" />
|
|
185
|
+
</svg>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { TrendingUp, TrendingDown, Minus, Plus } from "lucide-react";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
import { formatCurrencyAbbrev } from "@/lib/format-currency";
|
|
5
|
+
import { Button } from "./button";
|
|
6
|
+
|
|
7
|
+
// ─── BorrowCapacityItem ───────────────────────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Displays a single borrowing capacity result field.
|
|
10
|
+
* Shows a muted label, optional sub-label, and the formatted value below.
|
|
11
|
+
*
|
|
12
|
+
* Used inside scenario detail cards on the Borrowing Capacity page.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export interface BorrowCapacityItemProps {
|
|
16
|
+
/** Label above the value (e.g. "Purchase Price") */
|
|
17
|
+
title?: string;
|
|
18
|
+
/** Optional secondary descriptor below the title */
|
|
19
|
+
subTitle?: string;
|
|
20
|
+
/** Pre-formatted value string to display (e.g. "$500,000") */
|
|
21
|
+
value?: string;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function BorrowCapacityItem({
|
|
26
|
+
title,
|
|
27
|
+
subTitle,
|
|
28
|
+
value,
|
|
29
|
+
className,
|
|
30
|
+
}: BorrowCapacityItemProps) {
|
|
31
|
+
if (!title && !value) {
|
|
32
|
+
return <div className={cn("min-h-[52px]", className)} aria-hidden />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className={cn("flex flex-col gap-1", className)}>
|
|
37
|
+
{title && (
|
|
38
|
+
<span className="block min-h-[2.5rem] text-sm text-muted-foreground">
|
|
39
|
+
{title}
|
|
40
|
+
</span>
|
|
41
|
+
)}
|
|
42
|
+
{value && (
|
|
43
|
+
<span className="text-lg font-semibold text-foreground">{value}</span>
|
|
44
|
+
)}
|
|
45
|
+
{subTitle && (
|
|
46
|
+
<span className="text-sm italic text-muted-foreground/70">
|
|
47
|
+
{subTitle}
|
|
48
|
+
</span>
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─── StatisticItem ────────────────────────────────────────────────────────────
|
|
55
|
+
/**
|
|
56
|
+
* Shows a financial trend statistic over a lookback period.
|
|
57
|
+
* Displays a heading ("Last N months"), the absolute dollar change,
|
|
58
|
+
* and the percentage change with a direction icon.
|
|
59
|
+
*
|
|
60
|
+
* Trend colors: positive → primary, flat/negative → muted.
|
|
61
|
+
*
|
|
62
|
+
* Used in the statistics summary row of the Borrowing Capacity page.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
export interface StatisticItemProps {
|
|
66
|
+
/** Number of months to look back (default: 3) */
|
|
67
|
+
loopBackMonths?: number;
|
|
68
|
+
/** Absolute dollar amount of change */
|
|
69
|
+
amountChange?: number;
|
|
70
|
+
/** Percentage change — positive = up, negative = down, 0 = flat */
|
|
71
|
+
amountChangePercentage?: number;
|
|
72
|
+
className?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function StatisticItem({
|
|
76
|
+
loopBackMonths = 3,
|
|
77
|
+
amountChange = 0,
|
|
78
|
+
amountChangePercentage = 0,
|
|
79
|
+
className,
|
|
80
|
+
}: StatisticItemProps) {
|
|
81
|
+
const isPositive = amountChangePercentage > 0;
|
|
82
|
+
const isNegative = amountChangePercentage < 0;
|
|
83
|
+
const TrendIcon = isPositive ? TrendingUp : isNegative ? TrendingDown : Minus;
|
|
84
|
+
const trendClassName = isPositive ? "text-primary" : "text-muted-foreground";
|
|
85
|
+
const amountPrefix = isPositive ? "+" : isNegative ? "−" : "";
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div
|
|
89
|
+
className={cn(
|
|
90
|
+
"flex flex-col justify-center gap-2 border border-border p-3",
|
|
91
|
+
className,
|
|
92
|
+
)}
|
|
93
|
+
>
|
|
94
|
+
<span className="text-sm text-muted-foreground">
|
|
95
|
+
Last {loopBackMonths} month{loopBackMonths !== 1 ? "s" : ""}
|
|
96
|
+
</span>
|
|
97
|
+
<div className="flex items-center justify-between gap-2">
|
|
98
|
+
<span className="text-xl font-semibold tabular-nums text-foreground">
|
|
99
|
+
{amountPrefix}
|
|
100
|
+
{formatCurrencyAbbrev(Math.abs(amountChange), 2)}
|
|
101
|
+
</span>
|
|
102
|
+
<span
|
|
103
|
+
className={cn(
|
|
104
|
+
"flex items-center gap-1 text-sm font-medium tabular-nums",
|
|
105
|
+
trendClassName,
|
|
106
|
+
)}
|
|
107
|
+
>
|
|
108
|
+
<TrendIcon size={14} className="shrink-0" />
|
|
109
|
+
{Math.abs(amountChangePercentage).toFixed(1)}%
|
|
110
|
+
</span>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─── LoanToValueRatio ─────────────────────────────────────────────────────────
|
|
117
|
+
/**
|
|
118
|
+
* Displays a Loan-to-Value Ratio (LVR) as a percentage with a color-coded
|
|
119
|
+
* risk indicator and an optional equity/debt breakdown bar.
|
|
120
|
+
*
|
|
121
|
+
* Risk tiers:
|
|
122
|
+
* ≤ 60% → green (safe)
|
|
123
|
+
* 61–80% → warning (moderate)
|
|
124
|
+
* > 80% → destructive (high)
|
|
125
|
+
*
|
|
126
|
+
* Used in the LVR settings panel of the Borrowing Capacity page.
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
export interface LoanToValueRatioProps {
|
|
130
|
+
/** LVR as a whole number percentage (0–100) */
|
|
131
|
+
lvr: number;
|
|
132
|
+
/** Optional debt amount — shown below the bar when provided */
|
|
133
|
+
debtAmount?: number;
|
|
134
|
+
/** Optional equity amount — shown below the bar when provided */
|
|
135
|
+
equityAmount?: number;
|
|
136
|
+
className?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Thresholds match major Australian lender risk bands
|
|
140
|
+
const LVR_TIER_STYLES = {
|
|
141
|
+
safe: { text: "text-success", bar: "bg-success" },
|
|
142
|
+
moderate: { text: "text-warning", bar: "bg-warning" },
|
|
143
|
+
high: { text: "text-destructive", bar: "bg-destructive" },
|
|
144
|
+
} as const;
|
|
145
|
+
|
|
146
|
+
export function LoanToValueRatio({
|
|
147
|
+
lvr,
|
|
148
|
+
debtAmount,
|
|
149
|
+
equityAmount,
|
|
150
|
+
className,
|
|
151
|
+
}: LoanToValueRatioProps) {
|
|
152
|
+
const clamped = Math.min(100, Math.max(0, lvr));
|
|
153
|
+
const tier = clamped <= 60 ? "safe" : clamped <= 80 ? "moderate" : "high";
|
|
154
|
+
const { text: lvrTextColor, bar: lvrBarColor } = LVR_TIER_STYLES[tier];
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<div className={cn("flex flex-col items-center gap-2", className)}>
|
|
158
|
+
<div className="flex flex-col items-center leading-none">
|
|
159
|
+
<span className={cn("text-3xl font-bold tabular-nums", lvrTextColor)}>
|
|
160
|
+
{clamped.toFixed(0)}%
|
|
161
|
+
</span>
|
|
162
|
+
<span className="mt-1 text-sm font-semibold uppercase tracking-widest text-muted-foreground">
|
|
163
|
+
LVR
|
|
164
|
+
</span>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
{/* Debt-vs-equity bar */}
|
|
168
|
+
<div className="h-1.5 w-full overflow-hidden bg-muted" aria-hidden>
|
|
169
|
+
<div
|
|
170
|
+
className={cn("h-full transition-all", lvrBarColor)}
|
|
171
|
+
style={{ width: `${clamped}%` }}
|
|
172
|
+
/>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
{(debtAmount !== undefined || equityAmount !== undefined) && (
|
|
176
|
+
<div className="flex w-full items-center justify-between text-sm text-muted-foreground">
|
|
177
|
+
{debtAmount !== undefined && (
|
|
178
|
+
<span>Debt {formatCurrencyAbbrev(debtAmount, 1)}</span>
|
|
179
|
+
)}
|
|
180
|
+
{equityAmount !== undefined && (
|
|
181
|
+
<span>Equity {formatCurrencyAbbrev(equityAmount, 1)}</span>
|
|
182
|
+
)}
|
|
183
|
+
</div>
|
|
184
|
+
)}
|
|
185
|
+
</div>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ─── AddScenarioButton ────────────────────────────────────────────────────────
|
|
190
|
+
/**
|
|
191
|
+
* A dashed-border CTA button for adding a new borrowing scenario.
|
|
192
|
+
* Renders as a full-width <button> with a label and Plus icon.
|
|
193
|
+
* Supports a disabled state that removes interactivity.
|
|
194
|
+
*
|
|
195
|
+
* Used on the Borrowing Capacity page to open the "add / compare scenario" flow.
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
export interface AddScenarioButtonProps {
|
|
199
|
+
/** Button label (default: "Compare Loan Options") */
|
|
200
|
+
title?: string;
|
|
201
|
+
/** Disables the button */
|
|
202
|
+
disabled?: boolean;
|
|
203
|
+
/** Click handler */
|
|
204
|
+
onClick?: () => void;
|
|
205
|
+
className?: string;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function AddScenarioButton({
|
|
209
|
+
title = "Compare Loan Options",
|
|
210
|
+
disabled = false,
|
|
211
|
+
onClick,
|
|
212
|
+
className,
|
|
213
|
+
}: AddScenarioButtonProps) {
|
|
214
|
+
return (
|
|
215
|
+
<Button
|
|
216
|
+
variant="outline-secondary"
|
|
217
|
+
disabled={disabled}
|
|
218
|
+
onClick={onClick}
|
|
219
|
+
className={cn(
|
|
220
|
+
"w-full justify-between border-dashed text-base",
|
|
221
|
+
className,
|
|
222
|
+
)}
|
|
223
|
+
>
|
|
224
|
+
<span>{title}</span>
|
|
225
|
+
<Plus size={18} className="shrink-0" />
|
|
226
|
+
</Button>
|
|
227
|
+
);
|
|
228
|
+
}
|