@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,180 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Stepper, Step, StepItem } from "./stepper";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_VIDEO_SRC =
|
|
5
|
+
"https://d1rndq5v7rs3ry.cloudfront.net/padua-landing-video.mp4";
|
|
6
|
+
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// SignupVideoPanel
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
export interface SignupVideoPanelProps {
|
|
12
|
+
/** Defaults to WealthX CDN landing video. */
|
|
13
|
+
videoSrc?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function SignupVideoPanel({
|
|
17
|
+
videoSrc = DEFAULT_VIDEO_SRC,
|
|
18
|
+
}: SignupVideoPanelProps) {
|
|
19
|
+
return (
|
|
20
|
+
<div className="hidden @md:block relative bg-neutral-900 overflow-hidden">
|
|
21
|
+
<video
|
|
22
|
+
autoPlay
|
|
23
|
+
muted
|
|
24
|
+
loop
|
|
25
|
+
playsInline
|
|
26
|
+
className="absolute inset-0 w-full h-full object-cover"
|
|
27
|
+
>
|
|
28
|
+
<source src={videoSrc} type="video/mp4" />
|
|
29
|
+
</video>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// SignupShell — backoffice signup wizard layout
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
export interface SignupShellProps {
|
|
39
|
+
/** Ordered list of step labels used by the stepper and h2 heading. */
|
|
40
|
+
steps: string[];
|
|
41
|
+
/** 0-based active step index. When >= steps.length the success layout is shown. */
|
|
42
|
+
step: number;
|
|
43
|
+
children: React.ReactNode;
|
|
44
|
+
/** Sticky footer content (Prev/Next buttons). Hidden in success state. */
|
|
45
|
+
footer?: React.ReactNode;
|
|
46
|
+
videoSrc?: string;
|
|
47
|
+
/** Page heading above the stepper. Defaults to "Sign Up". */
|
|
48
|
+
title?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function SignupShell({
|
|
52
|
+
steps,
|
|
53
|
+
step,
|
|
54
|
+
children,
|
|
55
|
+
footer,
|
|
56
|
+
videoSrc,
|
|
57
|
+
title = "Sign Up",
|
|
58
|
+
}: SignupShellProps) {
|
|
59
|
+
const isSuccess = step >= steps.length;
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="@md:grid @md:grid-cols-2 h-screen overflow-hidden">
|
|
63
|
+
<SignupVideoPanel videoSrc={videoSrc} />
|
|
64
|
+
<div className="flex flex-col h-full overflow-hidden">
|
|
65
|
+
{isSuccess ? (
|
|
66
|
+
<div className="flex-1 overflow-y-auto min-h-0 flex items-center justify-center">
|
|
67
|
+
{children}
|
|
68
|
+
</div>
|
|
69
|
+
) : (
|
|
70
|
+
<>
|
|
71
|
+
<div className="flex-1 overflow-y-auto min-h-0">
|
|
72
|
+
<div className="flex min-h-full justify-center px-4 py-6 @sm:px-10 @sm:py-10">
|
|
73
|
+
<div className="w-full max-w-[560px] flex flex-col gap-8">
|
|
74
|
+
<h1 className="text-3xl font-bold text-foreground text-center">
|
|
75
|
+
{title}
|
|
76
|
+
</h1>
|
|
77
|
+
<Stepper activeStep={step} className="w-full">
|
|
78
|
+
{steps.map((label) => (
|
|
79
|
+
<Step key={label}>
|
|
80
|
+
<StepItem label={label} />
|
|
81
|
+
</Step>
|
|
82
|
+
))}
|
|
83
|
+
</Stepper>
|
|
84
|
+
<h2 className="text-2xl font-bold text-foreground">
|
|
85
|
+
{steps[step]}
|
|
86
|
+
</h2>
|
|
87
|
+
{children}
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
{footer && (
|
|
92
|
+
<div className="shrink-0 border-t border-border bg-background">
|
|
93
|
+
<div className="w-full max-w-[560px] mx-auto px-0 py-4 flex justify-between">
|
|
94
|
+
{footer}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
)}
|
|
98
|
+
</>
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// FrontendShell — client-facing signup wizard layout
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
export interface FrontendShellProps {
|
|
110
|
+
/** Step labels for the stepper. Required when stepIndex is provided. */
|
|
111
|
+
steps?: string[];
|
|
112
|
+
/** 0-based active step. When undefined the stepper is hidden. */
|
|
113
|
+
stepIndex?: number;
|
|
114
|
+
children: React.ReactNode;
|
|
115
|
+
footer?: React.ReactNode;
|
|
116
|
+
/** When true renders a centered layout without stepper/title (success screen). */
|
|
117
|
+
isSuccess?: boolean;
|
|
118
|
+
videoSrc?: string;
|
|
119
|
+
/** Page heading. Defaults to "Create Account". */
|
|
120
|
+
title?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function FrontendShell({
|
|
124
|
+
steps,
|
|
125
|
+
stepIndex,
|
|
126
|
+
children,
|
|
127
|
+
footer,
|
|
128
|
+
isSuccess = false,
|
|
129
|
+
videoSrc,
|
|
130
|
+
title = "Create Account",
|
|
131
|
+
}: FrontendShellProps) {
|
|
132
|
+
const hasStepper = stepIndex !== undefined && steps !== undefined;
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div className="@md:grid @md:grid-cols-2 h-screen overflow-hidden">
|
|
136
|
+
<SignupVideoPanel videoSrc={videoSrc} />
|
|
137
|
+
<div className="flex flex-col h-full overflow-hidden">
|
|
138
|
+
{isSuccess ? (
|
|
139
|
+
<div className="flex-1 overflow-y-auto min-h-0 flex items-center justify-center">
|
|
140
|
+
{children}
|
|
141
|
+
</div>
|
|
142
|
+
) : (
|
|
143
|
+
<>
|
|
144
|
+
<div className="flex-1 overflow-y-auto min-h-0">
|
|
145
|
+
<div className="flex min-h-full justify-center px-4 py-6 @sm:px-10 @sm:py-10">
|
|
146
|
+
<div className="w-full max-w-[520px] flex flex-col gap-8">
|
|
147
|
+
<h1 className="text-3xl font-bold text-foreground text-center">
|
|
148
|
+
{title}
|
|
149
|
+
</h1>
|
|
150
|
+
{hasStepper && (
|
|
151
|
+
<Stepper activeStep={stepIndex} className="w-full">
|
|
152
|
+
{steps!.map((label) => (
|
|
153
|
+
<Step key={label}>
|
|
154
|
+
<StepItem label={label} />
|
|
155
|
+
</Step>
|
|
156
|
+
))}
|
|
157
|
+
</Stepper>
|
|
158
|
+
)}
|
|
159
|
+
{hasStepper && (
|
|
160
|
+
<h2 className="text-2xl font-bold text-foreground">
|
|
161
|
+
{steps![stepIndex!]}
|
|
162
|
+
</h2>
|
|
163
|
+
)}
|
|
164
|
+
{children}
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
{footer && (
|
|
169
|
+
<div className="shrink-0 border-t border-border bg-background">
|
|
170
|
+
<div className="w-full max-w-[520px] mx-auto px-0 py-4 flex justify-between">
|
|
171
|
+
{footer}
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
</>
|
|
176
|
+
)}
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
@@ -32,6 +32,8 @@ export interface StageTimelineTask {
|
|
|
32
32
|
title: string;
|
|
33
33
|
completed: boolean;
|
|
34
34
|
aiAgentName?: string | null;
|
|
35
|
+
/** When provided alongside `aiAgentName`, shows the auto-complete toggle switch. */
|
|
36
|
+
autoCompleteEnabled?: boolean;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export interface StageTimelineStage {
|
|
@@ -48,6 +50,8 @@ export interface StageTimelineProps {
|
|
|
48
50
|
stages: StageTimelineStage[];
|
|
49
51
|
/** Called when a task checkbox is toggled. */
|
|
50
52
|
onTaskToggle?: (stageId: string, taskId: string) => void;
|
|
53
|
+
/** Called when the auto-complete switch on a task is toggled. */
|
|
54
|
+
onTaskAutoCompleteToggle?: (stageId: string, taskId: string) => void;
|
|
51
55
|
/** Shows a loading skeleton instead of stages. */
|
|
52
56
|
isLoading?: boolean;
|
|
53
57
|
className?: string;
|
|
@@ -60,6 +64,7 @@ export interface StageTimelineProps {
|
|
|
60
64
|
export function StageTimeline({
|
|
61
65
|
stages,
|
|
62
66
|
onTaskToggle,
|
|
67
|
+
onTaskAutoCompleteToggle,
|
|
63
68
|
isLoading = false,
|
|
64
69
|
className,
|
|
65
70
|
}: StageTimelineProps) {
|
|
@@ -186,12 +191,18 @@ export function StageTimeline({
|
|
|
186
191
|
title={task.title}
|
|
187
192
|
completed={task.completed}
|
|
188
193
|
aiAgentName={task.aiAgentName}
|
|
194
|
+
autoCompleteEnabled={task.autoCompleteEnabled}
|
|
189
195
|
size="sm"
|
|
190
196
|
onToggle={
|
|
191
197
|
onTaskToggle
|
|
192
198
|
? () => onTaskToggle(stage.id, task.id)
|
|
193
199
|
: undefined
|
|
194
200
|
}
|
|
201
|
+
onAutoCompleteToggle={
|
|
202
|
+
onTaskAutoCompleteToggle
|
|
203
|
+
? () => onTaskAutoCompleteToggle(stage.id, task.id)
|
|
204
|
+
: undefined
|
|
205
|
+
}
|
|
195
206
|
/>
|
|
196
207
|
))}
|
|
197
208
|
</AccordionContent>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Full-screen success card shown after a loan application is submitted.
|
|
7
|
+
* Extracted from the submitted/ page in the loan application flow.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type SubmissionConfirmationCardProps = {
|
|
11
|
+
onViewSubmission?: () => void;
|
|
12
|
+
className?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function CircleCheckIcon({ className }: { className?: string }) {
|
|
16
|
+
return (
|
|
17
|
+
<svg
|
|
18
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
19
|
+
viewBox="0 0 80 80"
|
|
20
|
+
fill="none"
|
|
21
|
+
className={cn("size-20", className)}
|
|
22
|
+
aria-hidden="true"
|
|
23
|
+
>
|
|
24
|
+
<circle cx="40" cy="40" r="38" stroke="currentColor" strokeWidth="3" />
|
|
25
|
+
<path
|
|
26
|
+
d="M24 40l12 12 20-24"
|
|
27
|
+
stroke="currentColor"
|
|
28
|
+
strokeWidth="3.5"
|
|
29
|
+
strokeLinecap="round"
|
|
30
|
+
strokeLinejoin="round"
|
|
31
|
+
/>
|
|
32
|
+
</svg>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function SubmissionConfirmationCard({
|
|
37
|
+
onViewSubmission,
|
|
38
|
+
className,
|
|
39
|
+
}: SubmissionConfirmationCardProps) {
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
className={cn(
|
|
43
|
+
"flex flex-col items-center gap-6 px-6 py-12 text-center",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
>
|
|
47
|
+
<CircleCheckIcon className="text-primary" />
|
|
48
|
+
|
|
49
|
+
<div className="flex flex-col gap-2">
|
|
50
|
+
<p className="text-2xl font-bold">Awesome!</p>
|
|
51
|
+
<p className="text-2xl font-bold">
|
|
52
|
+
You've submitted your loan application!
|
|
53
|
+
</p>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<p className="max-w-sm text-sm text-muted-foreground">
|
|
57
|
+
Your broker will take a look at your loan application and get back to
|
|
58
|
+
you with the results soon!
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
{onViewSubmission && (
|
|
62
|
+
<Button type="button" variant="outline" onClick={onViewSubmission}>
|
|
63
|
+
View Your Submission
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ChevronRight } from "lucide-react";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
import { formatCurrency } from "@/lib/format-currency";
|
|
5
|
+
import { Button } from "./button";
|
|
6
|
+
import { Skeleton } from "./skeleton";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Organism — "Top 3 Loans Available" section for the Borrowing Capacity page.
|
|
10
|
+
*
|
|
11
|
+
* Layout:
|
|
12
|
+
* - Heading row: "Top 3 Loans Available" (left) + "See All Options" link (right)
|
|
13
|
+
* - Two-column body:
|
|
14
|
+
* - Left: up to 3 `TopThreeProductItem` rows (lender logo, rate, max loan, repayment)
|
|
15
|
+
* - Right: Outcome panel (descriptive text + CTA buttons)
|
|
16
|
+
*
|
|
17
|
+
* All values are pre-formatted / typed — business logic stays in the app layer.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// ─── Sub-types ───────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export interface TopThreeProductItem {
|
|
23
|
+
/** Lender display name (e.g. "ANZ") */
|
|
24
|
+
lender: string;
|
|
25
|
+
/** URL for the lender logo image. Falls back to initials if omitted. */
|
|
26
|
+
lenderLogoUrl?: string;
|
|
27
|
+
/** Interest rate as a percentage (e.g. 5.5 → displayed as "5.50%") */
|
|
28
|
+
interestRate: number;
|
|
29
|
+
/** true = Variable rate, false = Fixed rate */
|
|
30
|
+
isVariable: boolean;
|
|
31
|
+
/** Maximum loan amount in AUD dollars */
|
|
32
|
+
maxLoanAmount: number;
|
|
33
|
+
/** Monthly repayment in AUD dollars */
|
|
34
|
+
monthlyRepayment: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface TopThreeProductProps {
|
|
38
|
+
/** Up to 3 loan products to display */
|
|
39
|
+
items?: TopThreeProductItem[];
|
|
40
|
+
/** Outcome summary text shown in the right panel */
|
|
41
|
+
outcomeText?: string;
|
|
42
|
+
/** Called when "See All Options" is clicked */
|
|
43
|
+
onSeeAllOptions?: () => void;
|
|
44
|
+
/** Called when "Talk To Your Broker" CTA is clicked */
|
|
45
|
+
onTalkToBroker?: () => void;
|
|
46
|
+
/** Called when "Start Loan Application" CTA is clicked */
|
|
47
|
+
onStartLoanApplication?: () => void;
|
|
48
|
+
/** Replace content with a skeleton loading state */
|
|
49
|
+
isLoading?: boolean;
|
|
50
|
+
className?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ─── Internal stat cell ──────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
function StatCell({ value, label }: { value: React.ReactNode; label: string }) {
|
|
56
|
+
return (
|
|
57
|
+
<div className="flex flex-col items-center gap-0.5 text-center">
|
|
58
|
+
<span className="text-base font-semibold tabular-nums text-foreground">
|
|
59
|
+
{value}
|
|
60
|
+
</span>
|
|
61
|
+
<span className="text-xs text-muted-foreground">{label}</span>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ─── Internal product row ─────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
function ProductRow({ item }: { item: TopThreeProductItem }) {
|
|
69
|
+
const initials = item.lender
|
|
70
|
+
.split(" ")
|
|
71
|
+
.map((w) => w[0])
|
|
72
|
+
.slice(0, 2)
|
|
73
|
+
.join("");
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="flex items-center gap-4 py-3">
|
|
77
|
+
{/* Lender logo / initials fallback */}
|
|
78
|
+
<div className="flex h-10 w-10 shrink-0 items-center justify-center border border-border bg-muted text-xs font-semibold text-muted-foreground">
|
|
79
|
+
{item.lenderLogoUrl ? (
|
|
80
|
+
<img
|
|
81
|
+
src={item.lenderLogoUrl}
|
|
82
|
+
alt={item.lender}
|
|
83
|
+
className="h-full w-full object-contain"
|
|
84
|
+
/>
|
|
85
|
+
) : (
|
|
86
|
+
initials
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
{/* Stats — rate, max loan, repayment */}
|
|
91
|
+
<div className="flex flex-1 items-center justify-between gap-2">
|
|
92
|
+
<StatCell
|
|
93
|
+
value={`${item.interestRate.toFixed(2)}%`}
|
|
94
|
+
label={item.isVariable ? "Variable" : "Fixed"}
|
|
95
|
+
/>
|
|
96
|
+
<StatCell
|
|
97
|
+
value={formatCurrency(item.maxLoanAmount)}
|
|
98
|
+
label="Max Loan Amount"
|
|
99
|
+
/>
|
|
100
|
+
<StatCell
|
|
101
|
+
value={formatCurrency(item.monthlyRepayment)}
|
|
102
|
+
label="Monthly Repayments"
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ─── Main component ───────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
export function TopThreeProduct({
|
|
112
|
+
items = [],
|
|
113
|
+
outcomeText,
|
|
114
|
+
onSeeAllOptions,
|
|
115
|
+
onTalkToBroker,
|
|
116
|
+
onStartLoanApplication,
|
|
117
|
+
isLoading = false,
|
|
118
|
+
className,
|
|
119
|
+
}: TopThreeProductProps) {
|
|
120
|
+
const showOutcome = Boolean(
|
|
121
|
+
outcomeText || onTalkToBroker || onStartLoanApplication,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div className={cn("flex flex-col gap-3", className)}>
|
|
126
|
+
{/* Heading row */}
|
|
127
|
+
<div className="flex items-center justify-between">
|
|
128
|
+
<span className="text-sm font-semibold text-foreground">
|
|
129
|
+
Top 3 Loans Available
|
|
130
|
+
</span>
|
|
131
|
+
{onSeeAllOptions && (
|
|
132
|
+
<button
|
|
133
|
+
type="button"
|
|
134
|
+
onClick={onSeeAllOptions}
|
|
135
|
+
className="flex items-center gap-1 text-sm text-primary transition-opacity hover:opacity-70"
|
|
136
|
+
>
|
|
137
|
+
See All Options
|
|
138
|
+
<ChevronRight size={14} className="shrink-0" />
|
|
139
|
+
</button>
|
|
140
|
+
)}
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
{/* Body — products + outcome */}
|
|
144
|
+
<div className="flex gap-4">
|
|
145
|
+
{/* Product list */}
|
|
146
|
+
<div className="flex flex-1 flex-col divide-y divide-border">
|
|
147
|
+
{isLoading
|
|
148
|
+
? Array.from({ length: 3 }).map((_, i) => (
|
|
149
|
+
<div key={i} className="flex items-center gap-4 py-3">
|
|
150
|
+
<Skeleton className="h-10 w-10 shrink-0" />
|
|
151
|
+
<div className="flex flex-1 justify-between gap-4">
|
|
152
|
+
<Skeleton className="h-8 w-16" />
|
|
153
|
+
<Skeleton className="h-8 w-20" />
|
|
154
|
+
<Skeleton className="h-8 w-20" />
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
))
|
|
158
|
+
: items.length > 0
|
|
159
|
+
? items
|
|
160
|
+
.slice(0, 3)
|
|
161
|
+
.map((item, i) => (
|
|
162
|
+
<ProductRow key={`${item.lender}-${i}`} item={item} />
|
|
163
|
+
))
|
|
164
|
+
: !isLoading && (
|
|
165
|
+
<p className="py-6 text-center text-sm text-muted-foreground">
|
|
166
|
+
No lender options available for this scenario.
|
|
167
|
+
</p>
|
|
168
|
+
)}
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
{/* Outcome panel */}
|
|
172
|
+
{showOutcome && (
|
|
173
|
+
<div className="flex w-48 shrink-0 flex-col gap-3 border-l border-border pl-4">
|
|
174
|
+
<span className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
|
|
175
|
+
Outcome
|
|
176
|
+
</span>
|
|
177
|
+
{outcomeText && (
|
|
178
|
+
<p className="text-sm text-foreground">{outcomeText}</p>
|
|
179
|
+
)}
|
|
180
|
+
<div className="flex flex-col gap-2">
|
|
181
|
+
{onTalkToBroker && (
|
|
182
|
+
<Button
|
|
183
|
+
variant="default"
|
|
184
|
+
size="sm"
|
|
185
|
+
onClick={onTalkToBroker}
|
|
186
|
+
className="w-full"
|
|
187
|
+
>
|
|
188
|
+
Talk To Your Broker
|
|
189
|
+
</Button>
|
|
190
|
+
)}
|
|
191
|
+
{onStartLoanApplication && (
|
|
192
|
+
<Button
|
|
193
|
+
variant="outline"
|
|
194
|
+
size="sm"
|
|
195
|
+
onClick={onStartLoanApplication}
|
|
196
|
+
className="w-full"
|
|
197
|
+
>
|
|
198
|
+
Start Loan Application
|
|
199
|
+
</Button>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Section header block used above each chart on the Money (Transactions) page.
|
|
6
|
+
*
|
|
7
|
+
* Matches the app design: large value at the top, category label below,
|
|
8
|
+
* optional period text and footnote beneath.
|
|
9
|
+
*
|
|
10
|
+
* Layout:
|
|
11
|
+
* ┌─────────────────────────────────────────┐
|
|
12
|
+
* │ $37,085 [optional action] │
|
|
13
|
+
* │ Cash Balance │
|
|
14
|
+
* │ 30 Days Total │
|
|
15
|
+
* │ (Based on connected bank transactions) │
|
|
16
|
+
* └─────────────────────────────────────────┘
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export interface TransactionsSummaryBlockProps {
|
|
20
|
+
/** Pre-formatted total value — e.g. "$37,085" — displayed prominently at top */
|
|
21
|
+
value: string;
|
|
22
|
+
/** Section label — e.g. "Cash Balance", "Income", "Expense" */
|
|
23
|
+
label: string;
|
|
24
|
+
/** Period text — e.g. "30 Days Total" */
|
|
25
|
+
period?: string;
|
|
26
|
+
/** Small footnote — e.g. "(Based on connected bank transactions)" */
|
|
27
|
+
footnote?: string;
|
|
28
|
+
/** Optional trailing element — e.g. a Button for "Set Goal" */
|
|
29
|
+
action?: React.ReactNode;
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function TransactionsSummaryBlock({
|
|
34
|
+
value,
|
|
35
|
+
label,
|
|
36
|
+
period,
|
|
37
|
+
footnote,
|
|
38
|
+
action,
|
|
39
|
+
className,
|
|
40
|
+
}: TransactionsSummaryBlockProps) {
|
|
41
|
+
return (
|
|
42
|
+
<div
|
|
43
|
+
className={cn("flex items-start justify-between gap-2 py-3", className)}
|
|
44
|
+
>
|
|
45
|
+
<div className="flex flex-col gap-0.5">
|
|
46
|
+
<p className="text-2xl font-bold tabular-nums text-foreground">
|
|
47
|
+
{value}
|
|
48
|
+
</p>
|
|
49
|
+
<p className="text-sm font-medium text-foreground">{label}</p>
|
|
50
|
+
{period && <p className="text-xs text-muted-foreground">{period}</p>}
|
|
51
|
+
{footnote && (
|
|
52
|
+
<p className="text-xs text-muted-foreground">{footnote}</p>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
{action && <div className="shrink-0">{action}</div>}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
package/src/lib/colors.ts
CHANGED
|
@@ -45,6 +45,18 @@ export function getContrastText(backgroundColor: string): string {
|
|
|
45
45
|
return luminance > 0.179 ? CONTRAST_DARK : CONTRAST_LIGHT;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Returns a CSS color-mix() string blending `color` with transparent at the given fill opacity.
|
|
50
|
+
* Used for swatch/chip backgrounds in income/expense/debt indicators.
|
|
51
|
+
*
|
|
52
|
+
* @example colorMixSwatch("#3B82F6") // "color-mix(in srgb, #3B82F6 15%, transparent)"
|
|
53
|
+
* @example colorMixSwatch("#3B82F6", 0.3) // "color-mix(in srgb, #3B82F6 30%, transparent)"
|
|
54
|
+
*/
|
|
55
|
+
export function colorMixSwatch(color: string, fillOpacity = 0.15): string {
|
|
56
|
+
const percent = Math.round(fillOpacity * 100);
|
|
57
|
+
return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
/** Convert hex to oklch() CSS string */
|
|
49
61
|
export function hexToOklch(hex: string): string {
|
|
50
62
|
const [r, g, b] = hexToRgb(hex);
|
package/src/lib/format-date.ts
CHANGED
|
@@ -54,11 +54,11 @@ export function formatDateWithWeekday(iso: string): string {
|
|
|
54
54
|
* Returns raw string on parse failure.
|
|
55
55
|
*/
|
|
56
56
|
export function formatDateLong(date: Date | string): string {
|
|
57
|
+
const d = typeof date === "string" ? safeParse(date) : date;
|
|
57
58
|
try {
|
|
58
|
-
const d = typeof date === "string" ? safeParse(date) : date;
|
|
59
59
|
return format(d, "EEEE, d MMMM");
|
|
60
60
|
} catch {
|
|
61
|
-
return
|
|
61
|
+
return d.toLocaleDateString();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|