@wealthx/shadcn 1.4.0 → 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 +12 -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,120 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import { formatCurrency } from "@/lib/format-currency";
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
import { Badge } from "@/components/ui/badge";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Displays a read-only list of income entries with edit/delete actions and an
|
|
9
|
+
* "Add income" CTA. Extracted from the loan application income tab.
|
|
10
|
+
* Consumers pre-calculate per-year totals before passing them in.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export type IncomeSummaryItem = {
|
|
14
|
+
/** Primary label — e.g. "Developer at Acme Corp" or "Rental Income" */
|
|
15
|
+
title: string;
|
|
16
|
+
/** Annualised income in whole dollars */
|
|
17
|
+
amountPerYear: number;
|
|
18
|
+
/** Optional duration string — "Employed for 3.5 yrs" */
|
|
19
|
+
employmentDuration?: string;
|
|
20
|
+
/** Small tag chips — employment status, basis, type */
|
|
21
|
+
statusTags?: string[];
|
|
22
|
+
/** Non-PAYG income source label */
|
|
23
|
+
source?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type IncomeSummaryComponentProps = {
|
|
27
|
+
incomes: IncomeSummaryItem[];
|
|
28
|
+
onAdd: () => void;
|
|
29
|
+
onEdit: (index: number) => void;
|
|
30
|
+
onDelete: (index: number) => void;
|
|
31
|
+
className?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function IncomeSummaryComponent({
|
|
35
|
+
incomes,
|
|
36
|
+
onAdd,
|
|
37
|
+
onEdit,
|
|
38
|
+
onDelete,
|
|
39
|
+
className,
|
|
40
|
+
}: IncomeSummaryComponentProps) {
|
|
41
|
+
if (!incomes.length) {
|
|
42
|
+
return (
|
|
43
|
+
<div className={cn("flex flex-col gap-4", className)}>
|
|
44
|
+
<p className="text-sm text-muted-foreground">No incomes added yet.</p>
|
|
45
|
+
<Button type="button" variant="outline" onClick={onAdd}>
|
|
46
|
+
+ Add an income
|
|
47
|
+
</Button>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div className={cn("flex flex-col gap-4", className)}>
|
|
54
|
+
<div className="flex flex-col gap-3">
|
|
55
|
+
{incomes.map((income, index) => (
|
|
56
|
+
<div
|
|
57
|
+
key={index}
|
|
58
|
+
className="flex flex-col gap-2 border border-border p-4"
|
|
59
|
+
>
|
|
60
|
+
{/* Title row + actions */}
|
|
61
|
+
<div className="flex items-center justify-between gap-2">
|
|
62
|
+
<span className="text-base font-semibold">{income.title}</span>
|
|
63
|
+
<div className="flex gap-2">
|
|
64
|
+
<Button
|
|
65
|
+
type="button"
|
|
66
|
+
variant="outline"
|
|
67
|
+
size="sm"
|
|
68
|
+
onClick={() => onEdit(index)}
|
|
69
|
+
>
|
|
70
|
+
Edit
|
|
71
|
+
</Button>
|
|
72
|
+
<Button
|
|
73
|
+
type="button"
|
|
74
|
+
variant="outline"
|
|
75
|
+
size="sm"
|
|
76
|
+
onClick={() => onDelete(index)}
|
|
77
|
+
className="border-destructive text-destructive hover:bg-destructive/10"
|
|
78
|
+
>
|
|
79
|
+
Delete
|
|
80
|
+
</Button>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
{/* Amount + duration */}
|
|
85
|
+
<div className="flex items-center justify-between text-sm">
|
|
86
|
+
<span>{formatCurrency(income.amountPerYear)} Per Year</span>
|
|
87
|
+
{income.employmentDuration && (
|
|
88
|
+
<span className="text-muted-foreground">
|
|
89
|
+
{income.employmentDuration}
|
|
90
|
+
</span>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
{/* Status tags */}
|
|
95
|
+
{income.statusTags && income.statusTags.length > 0 && (
|
|
96
|
+
<div className="flex flex-wrap gap-2">
|
|
97
|
+
{income.statusTags.map((tag) => (
|
|
98
|
+
<Badge key={tag} variant="secondary">
|
|
99
|
+
{tag}
|
|
100
|
+
</Badge>
|
|
101
|
+
))}
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
104
|
+
|
|
105
|
+
{/* Non-PAYG source */}
|
|
106
|
+
{income.source && (
|
|
107
|
+
<span className="text-sm text-muted-foreground">
|
|
108
|
+
Source: {income.source}
|
|
109
|
+
</span>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
))}
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<Button type="button" variant="outline" onClick={onAdd}>
|
|
116
|
+
+ Add an income
|
|
117
|
+
</Button>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import { Card, CardContent } from "@/components/ui/card";
|
|
5
|
+
import { Input } from "@/components/ui/input";
|
|
6
|
+
import { Checkbox } from "@/components/ui/checkbox";
|
|
7
|
+
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|
8
|
+
import { LoanOptionGroup } from "@/components/ui/loan-option-group";
|
|
9
|
+
import {
|
|
10
|
+
CurrencyInputWithSlider,
|
|
11
|
+
AddressAutocomplete,
|
|
12
|
+
} from "@/components/ui/form-primitives";
|
|
13
|
+
import {
|
|
14
|
+
Accordion,
|
|
15
|
+
AccordionItem,
|
|
16
|
+
AccordionTrigger,
|
|
17
|
+
AccordionContent,
|
|
18
|
+
} from "@/components/ui/accordion";
|
|
19
|
+
import { IncomeBarChart } from "@/components/ui/income-bar-chart";
|
|
20
|
+
import type { IncomeBarChartData } from "@/components/ui/income-bar-chart";
|
|
21
|
+
import { formatCurrency } from "@/lib/format-currency";
|
|
22
|
+
|
|
23
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const EMPLOYMENT_TYPE_OPTIONS = [
|
|
26
|
+
{ value: "payg", label: "PAYG" },
|
|
27
|
+
{ value: "self-employed", label: "Self Employed" },
|
|
28
|
+
{ value: "unemployed", label: "Unemployed" },
|
|
29
|
+
{ value: "retired", label: "Retired" },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const EMPLOYMENT_STATUS_OPTIONS = [
|
|
33
|
+
{ value: "primary", label: "Primary" },
|
|
34
|
+
{ value: "secondary", label: "Secondary" },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const EMPLOYMENT_BASIS_OPTIONS = [
|
|
38
|
+
{ value: "contract", label: "Contract" },
|
|
39
|
+
{ value: "temporary", label: "Temporary" },
|
|
40
|
+
{ value: "casual", label: "Casual" },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const INCOME_FREQUENCY_OPTIONS = [
|
|
44
|
+
{ value: "monthly", label: "Monthly" },
|
|
45
|
+
{ value: "weekly", label: "Weekly" },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
export type IncomeEmploymentType =
|
|
51
|
+
| "payg"
|
|
52
|
+
| "self-employed"
|
|
53
|
+
| "unemployed"
|
|
54
|
+
| "retired";
|
|
55
|
+
|
|
56
|
+
export type IncomeEmploymentStatus = "primary" | "secondary";
|
|
57
|
+
|
|
58
|
+
export type IncomeEmploymentBasis =
|
|
59
|
+
| "contract"
|
|
60
|
+
| "temporary"
|
|
61
|
+
| "casual"
|
|
62
|
+
| "full-time"
|
|
63
|
+
| "part-time";
|
|
64
|
+
|
|
65
|
+
export type IncomeFrequency = "monthly" | "weekly";
|
|
66
|
+
|
|
67
|
+
export type IncomeCompanyType = "public" | "private";
|
|
68
|
+
|
|
69
|
+
export type IncomeWorkSource = {
|
|
70
|
+
id: string;
|
|
71
|
+
/** Accordion header label — defaults to "Main Income Source" */
|
|
72
|
+
label?: string;
|
|
73
|
+
employmentType?: IncomeEmploymentType;
|
|
74
|
+
employmentStatus?: IncomeEmploymentStatus;
|
|
75
|
+
employmentBasis?: IncomeEmploymentBasis;
|
|
76
|
+
jobTitle?: string;
|
|
77
|
+
startDate?: string;
|
|
78
|
+
/** Whether still in this position — when false, endDate is required */
|
|
79
|
+
stillInPosition?: boolean;
|
|
80
|
+
endDate?: string;
|
|
81
|
+
companyName?: string;
|
|
82
|
+
companyAddress?: string;
|
|
83
|
+
incomeAmount?: number;
|
|
84
|
+
incomeFrequency?: IncomeFrequency;
|
|
85
|
+
companyType?: IncomeCompanyType;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type IncomeWorkDetailsProps = {
|
|
89
|
+
/** Rendered as "{applicantName} Income" in the heading */
|
|
90
|
+
applicantName: string;
|
|
91
|
+
/** Total from Open Banking — shown in summary card above the chart */
|
|
92
|
+
totalIncome?: number;
|
|
93
|
+
/** Monthly income data for the IncomeBarChart */
|
|
94
|
+
incomeData?: IncomeBarChartData | null;
|
|
95
|
+
/** Work Details accordion sources */
|
|
96
|
+
sources: IncomeWorkSource[];
|
|
97
|
+
onSourceChange?: (id: string, updates: Partial<IncomeWorkSource>) => void;
|
|
98
|
+
onAddSource?: () => void;
|
|
99
|
+
/** "Add More Account +" button in the summary card */
|
|
100
|
+
onConnectMore?: () => void;
|
|
101
|
+
className?: string;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// ─── Income source form ───────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
function IncomeSourceForm({
|
|
107
|
+
source,
|
|
108
|
+
onChange,
|
|
109
|
+
}: {
|
|
110
|
+
source: IncomeWorkSource;
|
|
111
|
+
onChange: (updates: Partial<IncomeWorkSource>) => void;
|
|
112
|
+
}) {
|
|
113
|
+
return (
|
|
114
|
+
<div className="flex flex-col gap-4 pt-2">
|
|
115
|
+
{/* Employment type */}
|
|
116
|
+
<LoanOptionGroup
|
|
117
|
+
options={EMPLOYMENT_TYPE_OPTIONS}
|
|
118
|
+
value={source.employmentType ?? ""}
|
|
119
|
+
onChange={(v) => {
|
|
120
|
+
if (typeof v === "string")
|
|
121
|
+
onChange({ employmentType: v as IncomeEmploymentType });
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
|
|
125
|
+
{/* Employment Status */}
|
|
126
|
+
<LoanOptionGroup
|
|
127
|
+
title="Employment Status"
|
|
128
|
+
options={EMPLOYMENT_STATUS_OPTIONS}
|
|
129
|
+
value={source.employmentStatus ?? ""}
|
|
130
|
+
onChange={(v) => {
|
|
131
|
+
if (typeof v === "string")
|
|
132
|
+
onChange({ employmentStatus: v as IncomeEmploymentStatus });
|
|
133
|
+
}}
|
|
134
|
+
/>
|
|
135
|
+
|
|
136
|
+
{/* Employment Type (basis) */}
|
|
137
|
+
<LoanOptionGroup
|
|
138
|
+
title="Employment Type"
|
|
139
|
+
options={EMPLOYMENT_BASIS_OPTIONS}
|
|
140
|
+
value={source.employmentBasis ?? ""}
|
|
141
|
+
onChange={(v) => {
|
|
142
|
+
if (typeof v === "string")
|
|
143
|
+
onChange({ employmentBasis: v as IncomeEmploymentBasis });
|
|
144
|
+
}}
|
|
145
|
+
/>
|
|
146
|
+
|
|
147
|
+
{/* Job Title */}
|
|
148
|
+
<div className="flex flex-col gap-1.5">
|
|
149
|
+
<label className="text-label-small text-muted-foreground">
|
|
150
|
+
Job Title
|
|
151
|
+
</label>
|
|
152
|
+
<Input
|
|
153
|
+
value={source.jobTitle ?? ""}
|
|
154
|
+
onChange={(e) => onChange({ jobTitle: e.target.value })}
|
|
155
|
+
placeholder="e.g. Software Engineer"
|
|
156
|
+
/>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
{/* Start Date + optional End Date (shown side-by-side when not still in position) */}
|
|
160
|
+
<div
|
|
161
|
+
className={
|
|
162
|
+
source.stillInPosition === false
|
|
163
|
+
? "grid grid-cols-2 gap-3"
|
|
164
|
+
: undefined
|
|
165
|
+
}
|
|
166
|
+
>
|
|
167
|
+
<div className="flex flex-col gap-1.5">
|
|
168
|
+
<label className="text-label-small text-muted-foreground">
|
|
169
|
+
Start Date
|
|
170
|
+
</label>
|
|
171
|
+
<Input
|
|
172
|
+
type="date"
|
|
173
|
+
value={source.startDate ?? ""}
|
|
174
|
+
onChange={(e) => onChange({ startDate: e.target.value })}
|
|
175
|
+
/>
|
|
176
|
+
</div>
|
|
177
|
+
{source.stillInPosition === false && (
|
|
178
|
+
<div className="flex flex-col gap-1.5">
|
|
179
|
+
<label className="text-label-small text-muted-foreground">
|
|
180
|
+
End Date
|
|
181
|
+
</label>
|
|
182
|
+
<Input
|
|
183
|
+
type="date"
|
|
184
|
+
value={source.endDate ?? ""}
|
|
185
|
+
onChange={(e) => onChange({ endDate: e.target.value })}
|
|
186
|
+
/>
|
|
187
|
+
</div>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
{/* Still in position checkbox */}
|
|
192
|
+
<div className="flex items-center gap-2">
|
|
193
|
+
<Checkbox
|
|
194
|
+
id={`${source.id}-still-in-position`}
|
|
195
|
+
checked={source.stillInPosition ?? true}
|
|
196
|
+
onCheckedChange={(checked) =>
|
|
197
|
+
onChange({ stillInPosition: checked === true })
|
|
198
|
+
}
|
|
199
|
+
/>
|
|
200
|
+
<label
|
|
201
|
+
htmlFor={`${source.id}-still-in-position`}
|
|
202
|
+
className="text-body-small cursor-pointer"
|
|
203
|
+
>
|
|
204
|
+
Still in position
|
|
205
|
+
</label>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
{/* Company Name */}
|
|
209
|
+
<div className="flex flex-col gap-1.5">
|
|
210
|
+
<label className="text-label-small text-muted-foreground">
|
|
211
|
+
Company Name
|
|
212
|
+
</label>
|
|
213
|
+
<Input
|
|
214
|
+
value={source.companyName ?? ""}
|
|
215
|
+
onChange={(e) => onChange({ companyName: e.target.value })}
|
|
216
|
+
placeholder="e.g. Acme Corporation"
|
|
217
|
+
/>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
{/* Company Address — autocomplete */}
|
|
221
|
+
<div className="flex flex-col gap-1.5">
|
|
222
|
+
<label className="text-label-small text-muted-foreground">
|
|
223
|
+
Company Address
|
|
224
|
+
</label>
|
|
225
|
+
<AddressAutocomplete
|
|
226
|
+
value={source.companyAddress ?? ""}
|
|
227
|
+
onValueChange={(v) => onChange({ companyAddress: v })}
|
|
228
|
+
/>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
{/* Income Amount + Frequency — input/slider left, toggle right */}
|
|
232
|
+
<div className="flex flex-col gap-1.5">
|
|
233
|
+
<label className="text-label-small text-muted-foreground">
|
|
234
|
+
Income Amount
|
|
235
|
+
</label>
|
|
236
|
+
<div className="flex items-start gap-3">
|
|
237
|
+
<CurrencyInputWithSlider
|
|
238
|
+
className="flex-1"
|
|
239
|
+
value={source.incomeAmount ?? 0}
|
|
240
|
+
min={0}
|
|
241
|
+
max={50000}
|
|
242
|
+
step={100}
|
|
243
|
+
onValueChange={(v) => onChange({ incomeAmount: v })}
|
|
244
|
+
/>
|
|
245
|
+
<LoanOptionGroup
|
|
246
|
+
className="shrink-0"
|
|
247
|
+
options={INCOME_FREQUENCY_OPTIONS}
|
|
248
|
+
value={source.incomeFrequency ?? ""}
|
|
249
|
+
onChange={(v) => {
|
|
250
|
+
if (typeof v === "string")
|
|
251
|
+
onChange({ incomeFrequency: v as IncomeFrequency });
|
|
252
|
+
}}
|
|
253
|
+
/>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
|
|
257
|
+
{/* Type of Company */}
|
|
258
|
+
<div className="flex flex-col gap-2">
|
|
259
|
+
<span className="text-label-small text-muted-foreground">
|
|
260
|
+
Type of Company
|
|
261
|
+
</span>
|
|
262
|
+
<RadioGroup
|
|
263
|
+
value={source.companyType}
|
|
264
|
+
onValueChange={(v) =>
|
|
265
|
+
onChange({ companyType: v as IncomeCompanyType })
|
|
266
|
+
}
|
|
267
|
+
className="flex flex-row gap-4"
|
|
268
|
+
>
|
|
269
|
+
<div className="flex items-center gap-2">
|
|
270
|
+
<RadioGroupItem value="public" id={`${source.id}-public`} />
|
|
271
|
+
<label
|
|
272
|
+
htmlFor={`${source.id}-public`}
|
|
273
|
+
className="text-body-small cursor-pointer"
|
|
274
|
+
>
|
|
275
|
+
Public
|
|
276
|
+
</label>
|
|
277
|
+
</div>
|
|
278
|
+
<div className="flex items-center gap-2">
|
|
279
|
+
<RadioGroupItem value="private" id={`${source.id}-private`} />
|
|
280
|
+
<label
|
|
281
|
+
htmlFor={`${source.id}-private`}
|
|
282
|
+
className="text-body-small cursor-pointer"
|
|
283
|
+
>
|
|
284
|
+
Private
|
|
285
|
+
</label>
|
|
286
|
+
</div>
|
|
287
|
+
</RadioGroup>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ─── Component ────────────────────────────────────────────────────────────────
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* IncomeWorkDetails — Income section of the loan application wizard.
|
|
297
|
+
*
|
|
298
|
+
* Shows:
|
|
299
|
+
* 1. "{applicantName} Income" heading
|
|
300
|
+
* 2. Open Banking summary card — total, mini bar chart, "Add More Account +"
|
|
301
|
+
* 3. Income Sources — "Total Income" indicator bar
|
|
302
|
+
* 4. Work Details — accordion of employment source forms
|
|
303
|
+
*
|
|
304
|
+
* Figma: WealthX-Backoffice---Mobile-App — node 19308:53126
|
|
305
|
+
*/
|
|
306
|
+
export function IncomeWorkDetails({
|
|
307
|
+
applicantName,
|
|
308
|
+
totalIncome,
|
|
309
|
+
incomeData,
|
|
310
|
+
sources,
|
|
311
|
+
onSourceChange,
|
|
312
|
+
onAddSource,
|
|
313
|
+
onConnectMore,
|
|
314
|
+
className,
|
|
315
|
+
}: IncomeWorkDetailsProps) {
|
|
316
|
+
const [openItems, setOpenItems] = React.useState<string[]>(
|
|
317
|
+
sources.length > 0 ? [sources[0].id] : [],
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
// Auto-open any source that was added after initial render
|
|
321
|
+
React.useEffect(() => {
|
|
322
|
+
setOpenItems((current) => {
|
|
323
|
+
const currentSet = new Set(current);
|
|
324
|
+
const newIds = sources
|
|
325
|
+
.map((s) => s.id)
|
|
326
|
+
.filter((id) => !currentSet.has(id));
|
|
327
|
+
return newIds.length > 0 ? [...current, ...newIds] : current;
|
|
328
|
+
});
|
|
329
|
+
}, [sources]);
|
|
330
|
+
|
|
331
|
+
return (
|
|
332
|
+
<div className={cn("flex flex-col gap-6 font-sans", className)}>
|
|
333
|
+
{/* Heading */}
|
|
334
|
+
<h2 className="text-h1 text-foreground">{applicantName}'s Income</h2>
|
|
335
|
+
|
|
336
|
+
{/* Open Banking summary — left card + right chart */}
|
|
337
|
+
{totalIncome !== undefined && (
|
|
338
|
+
<div className="flex items-center gap-4">
|
|
339
|
+
{/* Left: bordered card — amount + button */}
|
|
340
|
+
<Card className="shrink-0 w-[202px]">
|
|
341
|
+
<CardContent className="flex flex-col gap-3 p-4">
|
|
342
|
+
<div className="flex flex-col gap-1 flex-1">
|
|
343
|
+
<span className="text-h2 text-foreground">
|
|
344
|
+
{formatCurrency(totalIncome)}
|
|
345
|
+
</span>
|
|
346
|
+
<span className="text-body-small text-muted-foreground">
|
|
347
|
+
Total latest 12 months
|
|
348
|
+
</span>
|
|
349
|
+
</div>
|
|
350
|
+
<Button
|
|
351
|
+
variant="secondary"
|
|
352
|
+
size="sm"
|
|
353
|
+
className="w-fit"
|
|
354
|
+
onClick={onConnectMore}
|
|
355
|
+
>
|
|
356
|
+
Add More Account +
|
|
357
|
+
</Button>
|
|
358
|
+
</CardContent>
|
|
359
|
+
</Card>
|
|
360
|
+
|
|
361
|
+
{/* Right: bare bar chart with Y-axis + X-axis */}
|
|
362
|
+
{incomeData && (
|
|
363
|
+
<IncomeBarChart
|
|
364
|
+
incomeData={incomeData}
|
|
365
|
+
bare
|
|
366
|
+
showLegend={false}
|
|
367
|
+
showYAxis
|
|
368
|
+
showXAxis
|
|
369
|
+
defaultPeriod={12}
|
|
370
|
+
height={160}
|
|
371
|
+
className="flex-1"
|
|
372
|
+
/>
|
|
373
|
+
)}
|
|
374
|
+
</div>
|
|
375
|
+
)}
|
|
376
|
+
|
|
377
|
+
{/* Income Sources */}
|
|
378
|
+
<div className="flex flex-col gap-2">
|
|
379
|
+
<h3 className="text-h3 text-foreground">Income Sources</h3>
|
|
380
|
+
<div className="flex flex-col gap-1.5">
|
|
381
|
+
<span className="text-label-small text-muted-foreground">
|
|
382
|
+
Total Income
|
|
383
|
+
</span>
|
|
384
|
+
{/* Full-width indicator bar — green when totalIncome > 0, muted otherwise */}
|
|
385
|
+
<div
|
|
386
|
+
className={cn(
|
|
387
|
+
"h-5 w-full",
|
|
388
|
+
totalIncome ? "bg-primary" : "bg-muted",
|
|
389
|
+
)}
|
|
390
|
+
/>
|
|
391
|
+
</div>
|
|
392
|
+
</div>
|
|
393
|
+
|
|
394
|
+
{/* Work Details */}
|
|
395
|
+
<div className="flex flex-col gap-3">
|
|
396
|
+
<h3 className="text-h3 text-foreground">Work Details</h3>
|
|
397
|
+
<Accordion
|
|
398
|
+
type="multiple"
|
|
399
|
+
value={openItems}
|
|
400
|
+
onValueChange={setOpenItems}
|
|
401
|
+
className="border-t border-border"
|
|
402
|
+
>
|
|
403
|
+
{sources.map((source) => (
|
|
404
|
+
<AccordionItem key={source.id} value={source.id}>
|
|
405
|
+
<AccordionTrigger>
|
|
406
|
+
{source.label ?? "Main Income Source"}
|
|
407
|
+
</AccordionTrigger>
|
|
408
|
+
<AccordionContent className="text-foreground">
|
|
409
|
+
<IncomeSourceForm
|
|
410
|
+
source={source}
|
|
411
|
+
onChange={(updates) => onSourceChange?.(source.id, updates)}
|
|
412
|
+
/>
|
|
413
|
+
</AccordionContent>
|
|
414
|
+
</AccordionItem>
|
|
415
|
+
))}
|
|
416
|
+
</Accordion>
|
|
417
|
+
|
|
418
|
+
<Button
|
|
419
|
+
variant="outline"
|
|
420
|
+
size="sm"
|
|
421
|
+
className="w-fit"
|
|
422
|
+
onClick={onAddSource}
|
|
423
|
+
>
|
|
424
|
+
Add More +
|
|
425
|
+
</Button>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
);
|
|
429
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
TrendingUp,
|
|
4
|
+
Home,
|
|
5
|
+
ShoppingBag,
|
|
6
|
+
CreditCard,
|
|
7
|
+
PiggyBank,
|
|
8
|
+
TrendingDown,
|
|
9
|
+
} from "lucide-react";
|
|
10
|
+
import { Card, CardContent, CardHeader, CardTitle } from "./card";
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
import { formatCurrency } from "@/lib/format-currency";
|
|
13
|
+
|
|
14
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
export type IncomingOutgoingsLabel =
|
|
17
|
+
| "Total Income"
|
|
18
|
+
| "Living Expenses"
|
|
19
|
+
| "Lifestyle Expenses"
|
|
20
|
+
| "Debt Repayments"
|
|
21
|
+
| "Surplus Income & Savings"
|
|
22
|
+
| "Over Spending";
|
|
23
|
+
|
|
24
|
+
export interface IncomingOutgoingsItem {
|
|
25
|
+
label: IncomingOutgoingsLabel;
|
|
26
|
+
/** Dollar value */
|
|
27
|
+
value: number;
|
|
28
|
+
/** CSS color string for the bar fill and icon */
|
|
29
|
+
color: string;
|
|
30
|
+
/** CSS color string for the bar track background */
|
|
31
|
+
bgColor: string;
|
|
32
|
+
/** Bar fill width as a percentage 0–100 */
|
|
33
|
+
pct: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface IncomingOutgoingsCardProps {
|
|
37
|
+
items: IncomingOutgoingsItem[];
|
|
38
|
+
title?: string;
|
|
39
|
+
className?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── Icon map ─────────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
const ICON_MAP: Record<
|
|
45
|
+
IncomingOutgoingsLabel,
|
|
46
|
+
React.ComponentType<{ size?: number; className?: string }>
|
|
47
|
+
> = {
|
|
48
|
+
"Total Income": TrendingUp,
|
|
49
|
+
"Living Expenses": Home,
|
|
50
|
+
"Lifestyle Expenses": ShoppingBag,
|
|
51
|
+
"Debt Repayments": CreditCard,
|
|
52
|
+
"Surplus Income & Savings": PiggyBank,
|
|
53
|
+
"Over Spending": TrendingDown,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// ─── Component ────────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export function IncomingOutgoingsCard({
|
|
59
|
+
items,
|
|
60
|
+
title = "Incoming and outgoings",
|
|
61
|
+
className,
|
|
62
|
+
}: IncomingOutgoingsCardProps) {
|
|
63
|
+
if (!items?.length) return null;
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Card className={cn("h-full", className)}>
|
|
67
|
+
<CardHeader className="pb-2">
|
|
68
|
+
<CardTitle className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
69
|
+
{title}
|
|
70
|
+
</CardTitle>
|
|
71
|
+
</CardHeader>
|
|
72
|
+
<CardContent className="flex flex-col gap-5">
|
|
73
|
+
{items.map((item) => {
|
|
74
|
+
const Icon = ICON_MAP[item.label];
|
|
75
|
+
return (
|
|
76
|
+
<div key={item.label} className="flex flex-col gap-1">
|
|
77
|
+
<div className="flex items-center justify-between gap-2">
|
|
78
|
+
<span className="flex items-center gap-1.5 text-sm text-foreground">
|
|
79
|
+
{Icon && (
|
|
80
|
+
<Icon
|
|
81
|
+
size={16}
|
|
82
|
+
className="shrink-0"
|
|
83
|
+
style={{ color: item.color }}
|
|
84
|
+
/>
|
|
85
|
+
)}
|
|
86
|
+
{item.label}
|
|
87
|
+
</span>
|
|
88
|
+
<span className="shrink-0 text-sm font-medium text-foreground">
|
|
89
|
+
{formatCurrency(item.value)}
|
|
90
|
+
</span>
|
|
91
|
+
</div>
|
|
92
|
+
<div
|
|
93
|
+
className="h-1.5 w-full overflow-hidden"
|
|
94
|
+
style={{ background: item.bgColor }}
|
|
95
|
+
aria-hidden="true"
|
|
96
|
+
>
|
|
97
|
+
<div
|
|
98
|
+
className="h-full transition-all"
|
|
99
|
+
style={{
|
|
100
|
+
background: item.color,
|
|
101
|
+
width: `${Math.min(100, Math.max(0, item.pct))}%`,
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
})}
|
|
108
|
+
</CardContent>
|
|
109
|
+
</Card>
|
|
110
|
+
);
|
|
111
|
+
}
|