@wealthx/shadcn 1.3.2 → 1.3.3
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 +262 -226
- package/CHANGELOG.md +6 -0
- package/dist/{chunk-2UM72RJ7.mjs → chunk-2D3HQPFN.mjs} +12 -10
- package/dist/chunk-2EM2FRU6.mjs +613 -0
- package/dist/{chunk-FH6QVUVZ.mjs → chunk-2GIYVERS.mjs} +2 -2
- package/dist/chunk-2P7HP7LR.mjs +68 -0
- package/dist/{chunk-HISNT2MG.mjs → chunk-37AE3OM5.mjs} +5 -5
- package/dist/{chunk-HBZLGDIN.mjs → chunk-3ERBUVHC.mjs} +169 -110
- package/dist/{chunk-C7CQJNMR.mjs → chunk-3VDET466.mjs} +2 -2
- package/dist/{chunk-462HMNO4.mjs → chunk-4MM7LHM5.mjs} +2 -2
- package/dist/{chunk-QMY3AZJH.mjs → chunk-4Z66LMIQ.mjs} +2 -2
- package/dist/{chunk-U5X52X37.mjs → chunk-57ZXILTS.mjs} +6 -6
- package/dist/{chunk-3OYFOX3X.mjs → chunk-5VOTTIXF.mjs} +2 -2
- package/dist/{chunk-LBMRIB3G.mjs → chunk-6AJUS7VX.mjs} +1 -1
- package/dist/{chunk-OODBHKG7.mjs → chunk-6HIOM2HL.mjs} +7 -4
- package/dist/{chunk-BDYZCBRT.mjs → chunk-6QAFGZC2.mjs} +2 -2
- package/dist/{chunk-U4NDAF2P.mjs → chunk-6TX73WG7.mjs} +1 -1
- package/dist/{chunk-GD4BJDJR.mjs → chunk-7BTFGCFC.mjs} +4 -4
- package/dist/{chunk-FAKPBKLT.mjs → chunk-7GWRPXHD.mjs} +4 -4
- package/dist/{chunk-NMOI6CQD.mjs → chunk-7YI3HEBH.mjs} +5 -5
- package/dist/{chunk-T4BJLT57.mjs → chunk-AE7MASLF.mjs} +5 -5
- package/dist/{chunk-VLQZANBF.mjs → chunk-AFML43VJ.mjs} +6 -1
- package/dist/chunk-BBXSNDS3.mjs +260 -0
- package/dist/chunk-BOW7U26Y.mjs +203 -0
- package/dist/{chunk-34NWQURD.mjs → chunk-BS75ICOO.mjs} +2 -2
- package/dist/chunk-D2NSIIXG.mjs +394 -0
- package/dist/{chunk-3GF7OVTP.mjs → chunk-DGNHGNYH.mjs} +2 -2
- package/dist/{chunk-VLARHE5V.mjs → chunk-DMXYRCHM.mjs} +6 -6
- package/dist/{chunk-OGOYQ7BG.mjs → chunk-DQB4EPIS.mjs} +1 -1
- package/dist/{chunk-MIZQHHUO.mjs → chunk-FL6DZFJK.mjs} +106 -38
- package/dist/{chunk-I3RZS7V2.mjs → chunk-FLL633WS.mjs} +19 -33
- package/dist/{chunk-PBL4OQV2.mjs → chunk-FTPBQVQ6.mjs} +4 -4
- package/dist/chunk-FYPSTTEJ.mjs +169 -0
- package/dist/{chunk-6O6KD7CE.mjs → chunk-G27TSQLQ.mjs} +6 -6
- package/dist/{chunk-66MI7Q4B.mjs → chunk-GT3RU6GA.mjs} +2 -2
- package/dist/{chunk-D6ID6M4V.mjs → chunk-GTAVSBDO.mjs} +2 -2
- package/dist/{chunk-24FUO7TD.mjs → chunk-H6NQTIF4.mjs} +2 -2
- package/dist/{chunk-7DHU4VGG.mjs → chunk-HK4HUQTV.mjs} +2 -2
- package/dist/chunk-I4KVSZCH.mjs +101 -0
- package/dist/{chunk-RGVKLTLH.mjs → chunk-IKXYTCSB.mjs} +2 -2
- package/dist/{chunk-Y6DWJSKZ.mjs → chunk-ISUA7DSB.mjs} +1 -1
- package/dist/{chunk-2A5RRQGG.mjs → chunk-JD3YWRNP.mjs} +10 -14
- package/dist/{chunk-J5UICVJS.mjs → chunk-JPGL36WQ.mjs} +2 -2
- package/dist/{chunk-7XJHLGUV.mjs → chunk-JTK6VJXY.mjs} +2 -2
- package/dist/{chunk-7YAU5CY6.mjs → chunk-JVMXMFBB.mjs} +2 -2
- package/dist/{chunk-IAE3F7DR.mjs → chunk-JZY6TNIS.mjs} +21 -21
- package/dist/{chunk-K5A5L6T2.mjs → chunk-K4KOD3KR.mjs} +12 -12
- package/dist/{chunk-MBON7YRJ.mjs → chunk-K5QV4TT6.mjs} +3 -3
- package/dist/{chunk-IHMFS7NZ.mjs → chunk-K5VHK7CM.mjs} +21 -21
- package/dist/{chunk-RJI6GKVF.mjs → chunk-KCWNDYPZ.mjs} +5 -5
- package/dist/{chunk-UFYSFDER.mjs → chunk-KFH36NKF.mjs} +1 -1
- package/dist/{chunk-EBXQWIYG.mjs → chunk-KLTACJ2G.mjs} +5 -5
- package/dist/{chunk-3TTACBDP.mjs → chunk-KWD6GANL.mjs} +4 -4
- package/dist/{chunk-IOJRDS6V.mjs → chunk-L4NSRQ3T.mjs} +218 -147
- package/dist/{chunk-GYMYRIZP.mjs → chunk-LBTHZSBT.mjs} +2 -2
- package/dist/{chunk-AMQZRHEZ.mjs → chunk-LQULK2E3.mjs} +5 -5
- package/dist/{chunk-YJG55G2H.mjs → chunk-LR6LHDP3.mjs} +5 -5
- package/dist/{chunk-7PV3IWCN.mjs → chunk-M4VYX2PV.mjs} +19 -1
- package/dist/{chunk-P76HMUI6.mjs → chunk-MDUKXXIL.mjs} +2 -2
- package/dist/{chunk-LV35NGVG.mjs → chunk-N6Q5IPKT.mjs} +9 -9
- package/dist/{chunk-DOEO3CDL.mjs → chunk-NB3ZL36B.mjs} +1 -1
- package/dist/{chunk-XREGSKX3.mjs → chunk-NOOEKOWY.mjs} +5 -5
- package/dist/{chunk-NL3ZO62D.mjs → chunk-NT4FX27K.mjs} +1 -1
- package/dist/{chunk-QZ4RE6NA.mjs → chunk-NTYQWVLI.mjs} +6 -6
- package/dist/{chunk-ERGGHC2V.mjs → chunk-OEOOYMC2.mjs} +2 -2
- package/dist/{chunk-4GAWMKMI.mjs → chunk-OIKBW2QD.mjs} +291 -54
- package/dist/{chunk-DUJTAXMH.mjs → chunk-OKTJFDPN.mjs} +6 -6
- package/dist/chunk-OLKMCXAR.mjs +1219 -0
- package/dist/{chunk-EI5F6FMT.mjs → chunk-OWFQSXVD.mjs} +3 -3
- package/dist/{chunk-6DZEXFNB.mjs → chunk-P2N2PEFY.mjs} +3 -3
- package/dist/{chunk-NSLMILBT.mjs → chunk-P7CEBZM6.mjs} +2 -2
- package/dist/{chunk-7S5AESZO.mjs → chunk-PNRUH7JY.mjs} +6 -6
- package/dist/{chunk-ZU4NV6RG.mjs → chunk-PNSYFE3K.mjs} +2 -2
- package/dist/{chunk-JKGDCQTZ.mjs → chunk-QTRSCVQ3.mjs} +5 -5
- package/dist/{chunk-ABFDMHOR.mjs → chunk-QX7IFQSF.mjs} +5 -5
- package/dist/{chunk-CFMQP5QS.mjs → chunk-QXKGOMUX.mjs} +6 -6
- package/dist/{chunk-NQPOYKAQ.mjs → chunk-R2ON6CAN.mjs} +2 -2
- package/dist/{chunk-DBHJ5KC3.mjs → chunk-R4HCRDU5.mjs} +1 -1
- package/dist/{chunk-EWRB4PAD.mjs → chunk-RCAOCHWA.mjs} +14 -14
- package/dist/{chunk-EFRENWEJ.mjs → chunk-RSUIPKGX.mjs} +2 -2
- package/dist/{chunk-DGHAXJBN.mjs → chunk-S2FKV4M5.mjs} +5 -5
- package/dist/{chunk-RGU7HOEC.mjs → chunk-SET2ANTY.mjs} +5 -7
- package/dist/chunk-SFH2NJEJ.mjs +47 -0
- package/dist/{chunk-6AW4KJHE.mjs → chunk-SIVYAI3M.mjs} +12 -12
- package/dist/{chunk-5FQIKDKP.mjs → chunk-THVO2N47.mjs} +8 -8
- package/dist/{chunk-JMHR3YGZ.mjs → chunk-TLAWKTSA.mjs} +3 -3
- package/dist/{chunk-HVY6KCCF.mjs → chunk-TOWTPLRC.mjs} +68 -72
- package/dist/{chunk-6JQFUE5I.mjs → chunk-UALR6JGV.mjs} +2 -2
- package/dist/{chunk-N6TNTQL6.mjs → chunk-UJZ4UHWI.mjs} +9 -11
- package/dist/{chunk-MARPPFOJ.mjs → chunk-UNACI2YK.mjs} +2 -2
- package/dist/{chunk-3NCUZIFP.mjs → chunk-V6XGXYCJ.mjs} +7 -7
- package/dist/chunk-VB5M6OZQ.mjs +57 -0
- package/dist/{chunk-5IS7G74I.mjs → chunk-VY5NEUP7.mjs} +6 -6
- package/dist/{chunk-JHJHG4GO.mjs → chunk-WE4YKBDE.mjs} +2 -2
- package/dist/{chunk-BKNFWEH2.mjs → chunk-WL6WVV47.mjs} +3 -3
- package/dist/{chunk-FWCSY2DS.mjs → chunk-WNQUEZJF.mjs} +22 -1
- package/dist/{chunk-2Y7YJKPE.mjs → chunk-WZ6UJCBL.mjs} +1 -1
- package/dist/{chunk-UMTOX62O.mjs → chunk-XYPW2XA5.mjs} +13 -10
- package/dist/chunk-Y2MTAVAK.mjs +34 -0
- package/dist/{chunk-6CR5N2JW.mjs → chunk-YCWLFG27.mjs} +6 -6
- package/dist/{chunk-PU4YZQXV.mjs → chunk-YE67AALL.mjs} +12 -12
- package/dist/{chunk-M3FV7LOK.mjs → chunk-YEWNFK5S.mjs} +6 -1
- package/dist/{chunk-R3VSPKNP.mjs → chunk-YIZHS72Z.mjs} +11 -12
- package/dist/{chunk-7PYJD5JI.mjs → chunk-ZEDMKQK2.mjs} +2 -2
- package/dist/{chunk-N2PT566P.mjs → chunk-ZFCDYW6N.mjs} +4 -4
- package/dist/chunk-ZGQIVGIN.mjs +57 -0
- package/dist/{chunk-Q2BGOAMG.mjs → chunk-ZKWXDQDG.mjs} +4 -4
- package/dist/{chunk-GHC7LLUX.mjs → chunk-ZOWL2L5J.mjs} +5 -5
- package/dist/components/ui/accordion.mjs +3 -3
- package/dist/components/ui/add-column-modal.js +2 -2
- package/dist/components/ui/add-column-modal.mjs +10 -10
- package/dist/components/ui/add-lead-modal.js +424 -82
- package/dist/components/ui/add-lead-modal.mjs +12 -9
- package/dist/components/ui/advisor-card.js +2 -2
- package/dist/components/ui/advisor-card.mjs +8 -8
- package/dist/components/ui/ai-assistant-drawer.js +2 -2
- package/dist/components/ui/ai-assistant-drawer.mjs +9 -9
- package/dist/components/ui/ai-builder.js +958 -0
- package/dist/components/ui/ai-builder.mjs +25 -0
- package/dist/components/ui/ai-conversations.js +2045 -0
- package/dist/components/ui/ai-conversations.mjs +41 -0
- package/dist/components/ui/alert-dialog.js +2 -2
- package/dist/components/ui/alert-dialog.mjs +5 -5
- package/dist/components/ui/alert.mjs +3 -3
- package/dist/components/ui/appointment-action-dialogs.js +19 -3
- package/dist/components/ui/appointment-action-dialogs.mjs +15 -14
- package/dist/components/ui/appointment-availability-settings.js +181 -111
- package/dist/components/ui/appointment-availability-settings.mjs +20 -18
- package/dist/components/ui/appointment-book-dialog.js +113 -24
- package/dist/components/ui/appointment-book-dialog.mjs +21 -20
- package/dist/components/ui/appointment-calendar-view.js +19 -3
- package/dist/components/ui/appointment-calendar-view.mjs +10 -9
- package/dist/components/ui/appointment-detail-sheet.js +19 -3
- package/dist/components/ui/appointment-detail-sheet.mjs +18 -17
- package/dist/components/ui/appointment-gmail-connect.js +49 -89
- package/dist/components/ui/appointment-gmail-connect.mjs +8 -9
- package/dist/components/ui/appointment-mini-card.js +2 -2
- package/dist/components/ui/appointment-mini-card.mjs +6 -6
- package/dist/components/ui/appointment-time-slot-picker.mjs +6 -6
- package/dist/components/ui/appointment-upcoming-card.js +19 -3
- package/dist/components/ui/appointment-upcoming-card.mjs +15 -14
- package/dist/components/ui/auth-logo.js +95 -0
- package/dist/components/ui/auth-logo.mjs +8 -0
- package/dist/components/ui/auth-page-layout.js +108 -0
- package/dist/components/ui/auth-page-layout.mjs +8 -0
- package/dist/components/ui/avatar.mjs +3 -3
- package/dist/components/ui/backoffice-alert-history-chart.js +2 -2
- package/dist/components/ui/backoffice-alert-history-chart.mjs +9 -9
- package/dist/components/ui/backoffice-alerts-chart.js +2 -2
- package/dist/components/ui/backoffice-alerts-chart.mjs +11 -11
- package/dist/components/ui/backoffice-connections-chart.js +2 -2
- package/dist/components/ui/backoffice-connections-chart.mjs +11 -11
- package/dist/components/ui/backoffice-contact-history-chart.js +2 -2
- package/dist/components/ui/backoffice-contact-history-chart.mjs +9 -9
- package/dist/components/ui/badge.mjs +4 -4
- package/dist/components/ui/borrowing-capacity-line-chart.js +145 -132
- package/dist/components/ui/borrowing-capacity-line-chart.mjs +9 -9
- package/dist/components/ui/button.js +2 -2
- package/dist/components/ui/button.mjs +4 -4
- package/dist/components/ui/calendar.js +17 -3
- package/dist/components/ui/calendar.mjs +6 -5
- package/dist/components/ui/card.mjs +3 -3
- package/dist/components/ui/cash-balance-line-chart.js +157 -152
- package/dist/components/ui/cash-balance-line-chart.mjs +9 -9
- package/dist/components/ui/cashflow-bar-chart.js +2 -2
- package/dist/components/ui/cashflow-bar-chart.mjs +9 -9
- package/dist/components/ui/chat-widget-primitives.js +573 -0
- package/dist/components/ui/chat-widget-primitives.mjs +21 -0
- package/dist/components/ui/chat-widget.js +1268 -0
- package/dist/components/ui/chat-widget.mjs +29 -0
- package/dist/components/ui/checkbox.mjs +3 -3
- package/dist/components/ui/chip.js +2 -2
- package/dist/components/ui/chip.mjs +6 -6
- package/dist/components/ui/color-picker.js +2 -2
- package/dist/components/ui/color-picker.mjs +7 -7
- package/dist/components/ui/combobox.mjs +3 -3
- package/dist/components/ui/data-table.js +2 -2
- package/dist/components/ui/data-table.mjs +12 -12
- package/dist/components/ui/date-picker.js +22 -6
- package/dist/components/ui/date-picker.mjs +9 -8
- package/dist/components/ui/dialog.js +2 -2
- package/dist/components/ui/dialog.mjs +5 -5
- package/dist/components/ui/document-checklist-template.js +630 -0
- package/dist/components/ui/document-checklist-template.mjs +15 -0
- package/dist/components/ui/drawer.js +2 -2
- package/dist/components/ui/drawer.mjs +3 -3
- package/dist/components/ui/dropdown-menu.mjs +3 -3
- package/dist/components/ui/empty.mjs +3 -3
- package/dist/components/ui/expense-bar-chart.js +2 -2
- package/dist/components/ui/expense-bar-chart.mjs +9 -9
- package/dist/components/ui/field.mjs +5 -5
- package/dist/components/ui/financial-cards.js +431 -291
- package/dist/components/ui/financial-cards.mjs +10 -9
- package/dist/components/ui/financial-drawers.js +4 -4
- package/dist/components/ui/financial-drawers.mjs +8 -8
- package/dist/components/ui/financial-primitives.mjs +3 -3
- package/dist/components/ui/financial-sections.js +8 -9
- package/dist/components/ui/financial-sections.mjs +12 -12
- package/dist/components/ui/form-primitives.mjs +8 -8
- package/dist/components/ui/income-bar-chart.js +2 -2
- package/dist/components/ui/income-bar-chart.mjs +9 -9
- package/dist/components/ui/input-group.js +2 -2
- package/dist/components/ui/input-group.mjs +7 -7
- package/dist/components/ui/input-otp.mjs +3 -3
- package/dist/components/ui/input.mjs +3 -3
- package/dist/components/ui/kanban-column.js +19 -23
- package/dist/components/ui/kanban-column.mjs +14 -14
- package/dist/components/ui/label.mjs +3 -3
- package/dist/components/ui/onboarding-layout.js +476 -0
- package/dist/components/ui/onboarding-layout.mjs +11 -0
- package/dist/components/ui/opportunity-card.js +2 -2
- package/dist/components/ui/opportunity-card.mjs +12 -12
- package/dist/components/ui/opportunity-edit-modals.js +22 -6
- package/dist/components/ui/opportunity-edit-modals.mjs +21 -20
- package/dist/components/ui/opportunity-summary-tab.js +991 -674
- package/dist/components/ui/opportunity-summary-tab.mjs +26 -26
- package/dist/components/ui/page-header.mjs +3 -3
- package/dist/components/ui/page-top-bar.mjs +3 -3
- package/dist/components/ui/pagination.js +2 -2
- package/dist/components/ui/pagination.mjs +6 -6
- package/dist/components/ui/password-strength-tooltip.js +197 -0
- package/dist/components/ui/password-strength-tooltip.mjs +11 -0
- package/dist/components/ui/pipeline-alerts.mjs +3 -3
- package/dist/components/ui/pipeline-board.js +19 -23
- package/dist/components/ui/pipeline-board.mjs +18 -18
- package/dist/components/ui/pipeline-chart.js +12 -6
- package/dist/components/ui/pipeline-chart.mjs +4 -3
- package/dist/components/ui/pipeline-dialogs.js +28 -12
- package/dist/components/ui/pipeline-dialogs.mjs +14 -13
- package/dist/components/ui/pipeline-primitives.mjs +6 -6
- package/dist/components/ui/popover.mjs +3 -3
- package/dist/components/ui/progress.mjs +3 -3
- package/dist/components/ui/property-cashflow-doughnut-chart.js +2 -2
- package/dist/components/ui/property-cashflow-doughnut-chart.mjs +9 -9
- package/dist/components/ui/property-debt-equity-doughnut-chart.js +2 -2
- package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +9 -9
- package/dist/components/ui/property-mobile-estimate-line-chart.js +2 -2
- package/dist/components/ui/property-mobile-estimate-line-chart.mjs +9 -9
- package/dist/components/ui/radio-group.mjs +3 -3
- package/dist/components/ui/select.mjs +3 -3
- package/dist/components/ui/separator.mjs +3 -3
- package/dist/components/ui/sheet.mjs +3 -3
- package/dist/components/ui/sidebar-nav.js +6 -5
- package/dist/components/ui/sidebar-nav.mjs +7 -7
- package/dist/components/ui/skeleton.mjs +3 -3
- package/dist/components/ui/slider.mjs +3 -3
- package/dist/components/ui/sonner.mjs +2 -2
- package/dist/components/ui/spinner.mjs +3 -3
- package/dist/components/ui/stage-timeline.mjs +10 -10
- package/dist/components/ui/stepper.mjs +3 -3
- package/dist/components/ui/switch.mjs +3 -3
- package/dist/components/ui/table.mjs +3 -3
- package/dist/components/ui/tabs.mjs +3 -3
- package/dist/components/ui/textarea.mjs +3 -3
- package/dist/components/ui/toggle-group.mjs +4 -4
- package/dist/components/ui/toggle.mjs +3 -3
- package/dist/components/ui/tooltip.mjs +3 -3
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +2 -2
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +9 -9
- package/dist/components/ui/transactions-income-expense-bar-chart.js +2 -2
- package/dist/components/ui/transactions-income-expense-bar-chart.mjs +9 -9
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +2 -2
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +9 -9
- package/dist/components/ui/two-fa-setup-form.js +612 -0
- package/dist/components/ui/two-fa-setup-form.mjs +16 -0
- package/dist/components/ui/upload-card.js +187 -0
- package/dist/components/ui/upload-card.mjs +10 -0
- package/dist/components/ui/video-background.js +118 -0
- package/dist/components/ui/video-background.mjs +8 -0
- package/dist/index.js +12764 -9396
- package/dist/index.mjs +341 -245
- package/dist/lib/colors.mjs +1 -1
- package/dist/lib/theme-provider.mjs +1 -1
- package/dist/lib/typography.mjs +2 -2
- package/dist/lib/utils.js +8 -2
- package/dist/lib/utils.mjs +6 -4
- package/dist/styles.css +1 -1
- package/package.json +61 -1
- package/src/components/index.tsx +126 -1
- package/src/components/ui/add-lead-modal.tsx +101 -142
- package/src/components/ui/ai-builder.tsx +560 -0
- package/src/components/ui/ai-conversations.tsx +1690 -0
- package/src/components/ui/appointment-availability-settings.tsx +152 -101
- package/src/components/ui/appointment-book-dialog.tsx +138 -24
- package/src/components/ui/appointment-calendar-view.tsx +2 -3
- package/src/components/ui/appointment-gmail-connect.tsx +23 -42
- package/src/components/ui/auth-logo.tsx +50 -0
- package/src/components/ui/auth-page-layout.tsx +59 -0
- package/src/components/ui/borrowing-capacity-line-chart.tsx +10 -8
- package/src/components/ui/button.tsx +2 -2
- package/src/components/ui/calendar.tsx +2 -1
- package/src/components/ui/cash-balance-line-chart.tsx +10 -14
- package/src/components/ui/chart-shared.tsx +10 -0
- package/src/components/ui/chat-widget-primitives.tsx +336 -0
- package/src/components/ui/chat-widget.tsx +822 -0
- package/src/components/ui/document-checklist-template.tsx +264 -0
- package/src/components/ui/drawer.tsx +2 -2
- package/src/components/ui/financial-cards.tsx +176 -78
- package/src/components/ui/financial-drawers.tsx +2 -2
- package/src/components/ui/financial-sections.tsx +1 -1
- package/src/components/ui/kanban-column.tsx +2 -5
- package/src/components/ui/onboarding-layout.tsx +109 -0
- package/src/components/ui/opportunity-summary-tab.tsx +469 -142
- package/src/components/ui/password-strength-tooltip.tsx +70 -0
- package/src/components/ui/pipeline-chart.tsx +2 -6
- package/src/components/ui/sidebar-nav.tsx +1 -11
- package/src/components/ui/two-fa-setup-form.tsx +229 -0
- package/src/components/ui/upload-card.tsx +98 -0
- package/src/components/ui/video-background.tsx +55 -0
- package/src/lib/format-date.ts +26 -0
- package/src/lib/utils.ts +11 -0
- package/src/styles/styles-css.ts +1 -1
- package/tsup.config.ts +13 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { GripVertical, Plus, Trash2 } from "lucide-react";
|
|
3
|
+
import { Button } from "./button";
|
|
4
|
+
import { Input } from "./input";
|
|
5
|
+
import { Switch } from "./switch";
|
|
6
|
+
import {
|
|
7
|
+
Select,
|
|
8
|
+
SelectContent,
|
|
9
|
+
SelectItem,
|
|
10
|
+
SelectTrigger,
|
|
11
|
+
SelectValue,
|
|
12
|
+
} from "./select";
|
|
13
|
+
import { cn } from "../../lib/utils";
|
|
14
|
+
|
|
15
|
+
/** Predefined document category options advisors can pick from. */
|
|
16
|
+
const DOCUMENT_TYPES = [
|
|
17
|
+
"Income Verification",
|
|
18
|
+
"Bank Statements",
|
|
19
|
+
"Rental Income",
|
|
20
|
+
"Property Evidence",
|
|
21
|
+
"Liabilities",
|
|
22
|
+
"Identity",
|
|
23
|
+
"Employment Contract",
|
|
24
|
+
"Notice of Assessment",
|
|
25
|
+
"Contract of Sale",
|
|
26
|
+
"Savings History",
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export interface ChecklistCategory {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
/** Required for the main applicant. */
|
|
33
|
+
requiredMain: boolean;
|
|
34
|
+
/** Required for the co-applicant. */
|
|
35
|
+
requiredCo: boolean;
|
|
36
|
+
/** true when the advisor typed a custom name not in the predefined list. */
|
|
37
|
+
custom?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface DocumentChecklistTemplateProps {
|
|
41
|
+
/** Initial list of checklist categories. */
|
|
42
|
+
categories?: ChecklistCategory[];
|
|
43
|
+
/** Called on every edit (add / change / delete). */
|
|
44
|
+
onChange?: (categories: ChecklistCategory[]) => void;
|
|
45
|
+
/** Called when the advisor clicks Save. */
|
|
46
|
+
onSave?: (categories: ChecklistCategory[]) => void;
|
|
47
|
+
/** Called when the advisor clicks Cancel. */
|
|
48
|
+
onCancel?: () => void;
|
|
49
|
+
className?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* DocumentChecklistTemplate — organism
|
|
54
|
+
*
|
|
55
|
+
* Editable list of document categories. Each category has separate Required
|
|
56
|
+
* toggles for Main and Co applicants. Name is chosen from a predefined
|
|
57
|
+
* dropdown or typed as a custom value.
|
|
58
|
+
*/
|
|
59
|
+
export function DocumentChecklistTemplate({
|
|
60
|
+
categories: initial = [],
|
|
61
|
+
onChange,
|
|
62
|
+
onSave,
|
|
63
|
+
onCancel,
|
|
64
|
+
className,
|
|
65
|
+
}: DocumentChecklistTemplateProps) {
|
|
66
|
+
const [categories, setCategories] = useState<ChecklistCategory[]>(() =>
|
|
67
|
+
initial.map((c) => ({
|
|
68
|
+
...c,
|
|
69
|
+
custom: c.custom ?? !DOCUMENT_TYPES.includes(c.name),
|
|
70
|
+
})),
|
|
71
|
+
);
|
|
72
|
+
const [isDirty, setIsDirty] = useState(false);
|
|
73
|
+
|
|
74
|
+
function update(next: ChecklistCategory[]) {
|
|
75
|
+
setCategories(next);
|
|
76
|
+
setIsDirty(true);
|
|
77
|
+
onChange?.(next);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function handleSelectType(id: string, value: string) {
|
|
81
|
+
if (value === "__custom__") {
|
|
82
|
+
update(
|
|
83
|
+
categories.map((c) =>
|
|
84
|
+
c.id === id ? { ...c, name: "", custom: true } : c,
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
update(
|
|
89
|
+
categories.map((c) =>
|
|
90
|
+
c.id === id ? { ...c, name: value, custom: false } : c,
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function handleCustomName(id: string, name: string) {
|
|
97
|
+
update(categories.map((c) => (c.id === id ? { ...c, name } : c)));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function handleToggle(id: string, field: "requiredMain" | "requiredCo") {
|
|
101
|
+
update(
|
|
102
|
+
categories.map((c) => (c.id === id ? { ...c, [field]: !c[field] } : c)),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function handleDelete(id: string) {
|
|
107
|
+
update(categories.filter((c) => c.id !== id));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function handleAdd() {
|
|
111
|
+
update([
|
|
112
|
+
...categories,
|
|
113
|
+
{
|
|
114
|
+
id: `cat-${Date.now()}`,
|
|
115
|
+
name: "",
|
|
116
|
+
requiredMain: true,
|
|
117
|
+
requiredCo: false,
|
|
118
|
+
custom: false,
|
|
119
|
+
},
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const COLS = "grid-cols-[20px_1fr_64px_64px_32px]";
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div className={cn("flex flex-col", className)}>
|
|
127
|
+
{/* ── Header — title only ── */}
|
|
128
|
+
<div className="shrink-0 border-b border-border px-6 py-4">
|
|
129
|
+
<span className="text-label-large text-foreground">
|
|
130
|
+
Document Checklist Template
|
|
131
|
+
</span>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{/* ── Description ── */}
|
|
135
|
+
<div className="shrink-0 border-b border-border px-6 py-3">
|
|
136
|
+
<p className="text-body-small text-muted-foreground">
|
|
137
|
+
Define the document categories required for loan applications. Set
|
|
138
|
+
required status separately for Main and Co-applicants.
|
|
139
|
+
</p>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
{/* ── Body ── */}
|
|
143
|
+
<div className="flex flex-col overflow-y-auto">
|
|
144
|
+
{/* Column headers */}
|
|
145
|
+
{categories.length > 0 && (
|
|
146
|
+
<div
|
|
147
|
+
className={cn(
|
|
148
|
+
"grid shrink-0 items-center gap-3 border-b border-border bg-muted/30 px-6 py-2",
|
|
149
|
+
COLS,
|
|
150
|
+
)}
|
|
151
|
+
>
|
|
152
|
+
<span />
|
|
153
|
+
<span className="text-xs font-medium text-muted-foreground">
|
|
154
|
+
Category Name
|
|
155
|
+
</span>
|
|
156
|
+
<span className="text-center text-xs font-medium text-muted-foreground">
|
|
157
|
+
Main
|
|
158
|
+
</span>
|
|
159
|
+
<span className="text-center text-xs font-medium text-muted-foreground">
|
|
160
|
+
Co
|
|
161
|
+
</span>
|
|
162
|
+
<span />
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
|
|
166
|
+
{/* Rows */}
|
|
167
|
+
{categories.length === 0 ? (
|
|
168
|
+
<div className="flex items-center justify-center py-12 text-sm text-muted-foreground">
|
|
169
|
+
No categories yet. Add one below.
|
|
170
|
+
</div>
|
|
171
|
+
) : (
|
|
172
|
+
<div className="divide-y divide-border">
|
|
173
|
+
{categories.map((cat) => (
|
|
174
|
+
<div
|
|
175
|
+
key={cat.id}
|
|
176
|
+
className={cn("grid items-center gap-3 px-6 py-3", COLS)}
|
|
177
|
+
>
|
|
178
|
+
<GripVertical className="size-4 shrink-0 text-muted-foreground/30" />
|
|
179
|
+
|
|
180
|
+
{/* Name: Select (predefined) or Input (custom) */}
|
|
181
|
+
{cat.custom ? (
|
|
182
|
+
<Input
|
|
183
|
+
value={cat.name}
|
|
184
|
+
onChange={(e) => handleCustomName(cat.id, e.target.value)}
|
|
185
|
+
placeholder="Type category name…"
|
|
186
|
+
className="h-8 text-sm"
|
|
187
|
+
autoFocus
|
|
188
|
+
/>
|
|
189
|
+
) : (
|
|
190
|
+
<Select
|
|
191
|
+
value={cat.name || ""}
|
|
192
|
+
onValueChange={(v) => handleSelectType(cat.id, v)}
|
|
193
|
+
>
|
|
194
|
+
<SelectTrigger size="sm" className="w-full">
|
|
195
|
+
<SelectValue placeholder="Select type…" />
|
|
196
|
+
</SelectTrigger>
|
|
197
|
+
<SelectContent>
|
|
198
|
+
{DOCUMENT_TYPES.map((type) => (
|
|
199
|
+
<SelectItem key={type} value={type}>
|
|
200
|
+
{type}
|
|
201
|
+
</SelectItem>
|
|
202
|
+
))}
|
|
203
|
+
<SelectItem value="__custom__">Custom…</SelectItem>
|
|
204
|
+
</SelectContent>
|
|
205
|
+
</Select>
|
|
206
|
+
)}
|
|
207
|
+
|
|
208
|
+
<div className="flex justify-center">
|
|
209
|
+
<Switch
|
|
210
|
+
checked={cat.requiredMain}
|
|
211
|
+
onCheckedChange={() => handleToggle(cat.id, "requiredMain")}
|
|
212
|
+
size="sm"
|
|
213
|
+
/>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<div className="flex justify-center">
|
|
217
|
+
<Switch
|
|
218
|
+
checked={cat.requiredCo}
|
|
219
|
+
onCheckedChange={() => handleToggle(cat.id, "requiredCo")}
|
|
220
|
+
size="sm"
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<Button
|
|
225
|
+
variant="ghost"
|
|
226
|
+
size="icon"
|
|
227
|
+
className="size-8 text-muted-foreground hover:text-destructive"
|
|
228
|
+
onClick={() => handleDelete(cat.id)}
|
|
229
|
+
>
|
|
230
|
+
<Trash2 className="size-4" />
|
|
231
|
+
</Button>
|
|
232
|
+
</div>
|
|
233
|
+
))}
|
|
234
|
+
</div>
|
|
235
|
+
)}
|
|
236
|
+
|
|
237
|
+
{/* Add Category */}
|
|
238
|
+
<div className="border-t border-border px-6 py-4">
|
|
239
|
+
<Button
|
|
240
|
+
variant="outline"
|
|
241
|
+
size="sm"
|
|
242
|
+
className="gap-1.5"
|
|
243
|
+
onClick={handleAdd}
|
|
244
|
+
>
|
|
245
|
+
<Plus className="size-4" />
|
|
246
|
+
Add Category
|
|
247
|
+
</Button>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
{/* ── Footer ── */}
|
|
252
|
+
<div className="flex shrink-0 justify-end gap-2 border-t border-border px-6 py-4">
|
|
253
|
+
{onCancel && (
|
|
254
|
+
<Button variant="outline" onClick={onCancel}>
|
|
255
|
+
Cancel
|
|
256
|
+
</Button>
|
|
257
|
+
)}
|
|
258
|
+
<Button onClick={() => onSave?.(categories)} disabled={!isDirty}>
|
|
259
|
+
Save
|
|
260
|
+
</Button>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
@@ -85,8 +85,8 @@ function DrawerContent({
|
|
|
85
85
|
// WealthX: no rounded corners (Figma: sharp edges)
|
|
86
86
|
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:border-b",
|
|
87
87
|
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:border-t",
|
|
88
|
-
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l
|
|
89
|
-
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r
|
|
88
|
+
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l",
|
|
89
|
+
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r",
|
|
90
90
|
className,
|
|
91
91
|
)}
|
|
92
92
|
data-slot="drawer-content"
|
|
@@ -22,6 +22,12 @@ import type { LucideIcon } from "lucide-react";
|
|
|
22
22
|
import { cn } from "@/lib/utils";
|
|
23
23
|
import { formatDateShort } from "@/lib/format-date";
|
|
24
24
|
import { Badge } from "./badge";
|
|
25
|
+
import {
|
|
26
|
+
Accordion,
|
|
27
|
+
AccordionContent,
|
|
28
|
+
AccordionItem,
|
|
29
|
+
AccordionTrigger,
|
|
30
|
+
} from "./accordion";
|
|
25
31
|
import { RadioGroup, RadioGroupItem } from "./radio-group";
|
|
26
32
|
import {
|
|
27
33
|
FinancialDetailField,
|
|
@@ -129,11 +135,16 @@ export function PropertyCard({
|
|
|
129
135
|
variant="ghost"
|
|
130
136
|
aria-expanded={expanded}
|
|
131
137
|
onClick={() => setExpanded((prev) => !prev)}
|
|
132
|
-
className="h-auto w-full justify-start gap-1.5 px-5 py-3 text-left"
|
|
138
|
+
className="h-auto w-full justify-start gap-1.5 px-5 py-3 text-left has-[>svg]:px-5"
|
|
133
139
|
>
|
|
134
|
-
<span className="text-label-medium text-foreground">
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
<span className="flex-1 min-w-0 truncate text-label-medium text-foreground">
|
|
141
|
+
{address}
|
|
142
|
+
</span>
|
|
143
|
+
{type && (
|
|
144
|
+
<Badge className="shrink-0" variant="outline">
|
|
145
|
+
{type}
|
|
146
|
+
</Badge>
|
|
147
|
+
)}
|
|
137
148
|
<ChevronDown
|
|
138
149
|
className={cn(
|
|
139
150
|
"h-5 w-5 shrink-0 text-muted-foreground transition-transform duration-200",
|
|
@@ -158,14 +169,16 @@ export function PropertyCard({
|
|
|
158
169
|
<div
|
|
159
170
|
className={cn(
|
|
160
171
|
"grid gap-5 px-5 py-[15px]",
|
|
161
|
-
isLinkedToBank ? "grid-cols-
|
|
172
|
+
isLinkedToBank ? "grid-cols-2" : "grid-cols-1",
|
|
162
173
|
)}
|
|
163
174
|
>
|
|
164
175
|
<FinancialDetailField label="Estimated Value" value={estimated} />
|
|
165
176
|
{isLinkedToBank && (
|
|
166
177
|
<>
|
|
167
178
|
<FinancialDetailField label="Loan Amount" value={loanAmount} />
|
|
168
|
-
<
|
|
179
|
+
<div className="col-span-2">
|
|
180
|
+
<FinancialDetailField label="Equity" value={equity} />
|
|
181
|
+
</div>
|
|
169
182
|
</>
|
|
170
183
|
)}
|
|
171
184
|
</div>
|
|
@@ -622,6 +635,8 @@ export interface AboutCardProps {
|
|
|
622
635
|
gender?: string;
|
|
623
636
|
maritalStatus?: string;
|
|
624
637
|
numDependants?: string;
|
|
638
|
+
/** Individual dependant records — shows DOB + age for each. */
|
|
639
|
+
dependants?: Array<{ dob: string }>;
|
|
625
640
|
citizenStatus?: string;
|
|
626
641
|
residentialAddress?: string;
|
|
627
642
|
residentialStatus?: string;
|
|
@@ -631,6 +646,19 @@ export interface AboutCardProps {
|
|
|
631
646
|
passport?: string;
|
|
632
647
|
propertyInTrust?: string;
|
|
633
648
|
companyOwnership?: string;
|
|
649
|
+
/** Remove the outer card border. Use when the card is already inside a bordered container. */
|
|
650
|
+
borderless?: boolean;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function ageFromDob(dobStr: string): number | null {
|
|
654
|
+
if (!dobStr) return null;
|
|
655
|
+
const dob = new Date(dobStr);
|
|
656
|
+
if (isNaN(dob.getTime())) return null;
|
|
657
|
+
const today = new Date();
|
|
658
|
+
let age = today.getFullYear() - dob.getFullYear();
|
|
659
|
+
const m = today.getMonth() - dob.getMonth();
|
|
660
|
+
if (m < 0 || (m === 0 && today.getDate() < dob.getDate())) age--;
|
|
661
|
+
return age >= 0 ? age : null;
|
|
634
662
|
}
|
|
635
663
|
|
|
636
664
|
/**
|
|
@@ -647,6 +675,7 @@ export function AboutCard({
|
|
|
647
675
|
gender,
|
|
648
676
|
maritalStatus,
|
|
649
677
|
numDependants,
|
|
678
|
+
dependants,
|
|
650
679
|
citizenStatus,
|
|
651
680
|
residentialAddress,
|
|
652
681
|
residentialStatus,
|
|
@@ -656,6 +685,7 @@ export function AboutCard({
|
|
|
656
685
|
passport,
|
|
657
686
|
propertyInTrust,
|
|
658
687
|
companyOwnership,
|
|
688
|
+
borderless = false,
|
|
659
689
|
}: AboutCardProps) {
|
|
660
690
|
const fullName =
|
|
661
691
|
[title, firstName, lastName].filter(Boolean).join(" ") || "—";
|
|
@@ -671,13 +701,36 @@ export function AboutCard({
|
|
|
671
701
|
: undefined;
|
|
672
702
|
|
|
673
703
|
return (
|
|
674
|
-
<div
|
|
675
|
-
|
|
704
|
+
<div
|
|
705
|
+
className={cn(
|
|
706
|
+
"overflow-hidden divide-y divide-border",
|
|
707
|
+
!borderless && "border border-border",
|
|
708
|
+
)}
|
|
709
|
+
>
|
|
710
|
+
{/* Identity — personal details + citizenship documents */}
|
|
711
|
+
<div className="grid grid-cols-4 gap-x-6 gap-y-4 px-5 py-4">
|
|
676
712
|
<FinancialDetailField label="Full Name" value={fullName} />
|
|
677
713
|
<FinancialDetailField label="Date of Birth" value={dob || "—"} />
|
|
678
714
|
<FinancialDetailField label="Gender" value={gender || "—"} />
|
|
715
|
+
<FinancialDetailField
|
|
716
|
+
label="Citizenship"
|
|
717
|
+
value={citizenStatus || "—"}
|
|
718
|
+
/>
|
|
719
|
+
<FinancialDetailField
|
|
720
|
+
label="Driver's Licence"
|
|
721
|
+
value={driversLicence || "—"}
|
|
722
|
+
/>
|
|
723
|
+
<FinancialDetailField label="Passport" value={passport || "—"} />
|
|
724
|
+
</div>
|
|
725
|
+
|
|
726
|
+
{/* Contact */}
|
|
727
|
+
<div className="grid grid-cols-4 gap-x-6 gap-y-4 px-5 py-4">
|
|
679
728
|
<FinancialDetailField label="Phone" value={phone || "—"} />
|
|
680
729
|
<FinancialDetailField label="Email" value={email || "—"} />
|
|
730
|
+
</div>
|
|
731
|
+
|
|
732
|
+
{/* Family — marital status + dependants as a dedicated section */}
|
|
733
|
+
<div className="grid grid-cols-4 gap-x-6 gap-y-4 px-5 py-4">
|
|
681
734
|
<FinancialDetailField
|
|
682
735
|
label="Marital Status"
|
|
683
736
|
value={maritalStatus || "—"}
|
|
@@ -686,14 +739,30 @@ export function AboutCard({
|
|
|
686
739
|
label="No. of Dependants"
|
|
687
740
|
value={numDependants ?? "—"}
|
|
688
741
|
/>
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
742
|
+
{dependants &&
|
|
743
|
+
dependants.map((dep, i) => {
|
|
744
|
+
const age = ageFromDob(dep.dob);
|
|
745
|
+
const dobFormatted = formatDateShort(dep.dob) || "—";
|
|
746
|
+
const value =
|
|
747
|
+
age !== null ? `${dobFormatted} · age ${age}` : dobFormatted;
|
|
748
|
+
return (
|
|
749
|
+
<FinancialDetailField
|
|
750
|
+
key={i}
|
|
751
|
+
label={`Dependant ${i + 1}`}
|
|
752
|
+
value={value}
|
|
753
|
+
/>
|
|
754
|
+
);
|
|
755
|
+
})}
|
|
756
|
+
</div>
|
|
757
|
+
|
|
758
|
+
{/* Residence */}
|
|
759
|
+
<div className="grid grid-cols-4 gap-x-6 gap-y-4 px-5 py-4">
|
|
760
|
+
<div className="col-span-2">
|
|
761
|
+
<FinancialDetailField
|
|
762
|
+
label="Residential Address"
|
|
763
|
+
value={residentialAddress || "—"}
|
|
764
|
+
/>
|
|
765
|
+
</div>
|
|
697
766
|
<FinancialDetailField
|
|
698
767
|
label="Residential Status"
|
|
699
768
|
value={residentialStatus || "—"}
|
|
@@ -701,11 +770,10 @@ export function AboutCard({
|
|
|
701
770
|
{timeAtAddress && (
|
|
702
771
|
<FinancialDetailField label="Time at Address" value={timeAtAddress} />
|
|
703
772
|
)}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
<FinancialDetailField label="Passport" value={passport || "—"} />
|
|
773
|
+
</div>
|
|
774
|
+
|
|
775
|
+
{/* Ownership */}
|
|
776
|
+
<div className="grid grid-cols-4 gap-x-6 gap-y-4 px-5 py-4">
|
|
709
777
|
<FinancialDetailField
|
|
710
778
|
label="Property in Trust"
|
|
711
779
|
value={propertyInTrust || "—"}
|
|
@@ -740,73 +808,92 @@ export interface IncomeCardProps {
|
|
|
740
808
|
items: IncomeCardItem[];
|
|
741
809
|
/** Pre-formatted total monthly income e.g. "$12,300" */
|
|
742
810
|
totalMonthly?: string;
|
|
811
|
+
/** Remove the outer card border. Use when the card is already inside a bordered container. */
|
|
812
|
+
borderless?: boolean;
|
|
743
813
|
}
|
|
744
814
|
|
|
745
|
-
|
|
746
815
|
/**
|
|
747
816
|
* Display card for applicant income items.
|
|
748
|
-
* Each income source
|
|
817
|
+
* Each income source is an accordion row: collapsed = type + amount,
|
|
818
|
+
* expanded = full employment details.
|
|
749
819
|
*/
|
|
750
|
-
export function IncomeCard({
|
|
820
|
+
export function IncomeCard({
|
|
821
|
+
items,
|
|
822
|
+
totalMonthly,
|
|
823
|
+
borderless = false,
|
|
824
|
+
}: IncomeCardProps) {
|
|
751
825
|
if (items.length === 0) {
|
|
752
826
|
return (
|
|
753
|
-
<div className="
|
|
827
|
+
<div className={cn("px-5 py-4", !borderless && "border border-border")}>
|
|
754
828
|
<p className="text-sm text-muted-foreground">No income recorded.</p>
|
|
755
829
|
</div>
|
|
756
830
|
);
|
|
757
831
|
}
|
|
758
832
|
|
|
759
833
|
return (
|
|
760
|
-
<div
|
|
761
|
-
{
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
834
|
+
<div
|
|
835
|
+
className={cn(
|
|
836
|
+
"overflow-hidden flex flex-col",
|
|
837
|
+
!borderless && "border border-border",
|
|
838
|
+
)}
|
|
839
|
+
>
|
|
840
|
+
<Accordion openMultiple>
|
|
841
|
+
{items.map((item, i) => (
|
|
842
|
+
<AccordionItem key={i} value={String(i)}>
|
|
843
|
+
<AccordionTrigger className="px-5">
|
|
844
|
+
<div className="flex flex-1 items-center justify-between pr-2">
|
|
845
|
+
<div className="flex items-center gap-2">
|
|
846
|
+
<span className="text-label-medium text-foreground">
|
|
847
|
+
{item.incomeType}
|
|
848
|
+
</span>
|
|
849
|
+
{item.jobTitle && (
|
|
850
|
+
<span className="text-body-small text-muted-foreground">
|
|
851
|
+
· {item.jobTitle}
|
|
852
|
+
</span>
|
|
853
|
+
)}
|
|
854
|
+
</div>
|
|
855
|
+
<span className="text-label-medium text-foreground">
|
|
856
|
+
{item.amountLabel}
|
|
857
|
+
</span>
|
|
858
|
+
</div>
|
|
859
|
+
</AccordionTrigger>
|
|
860
|
+
<AccordionContent className="px-5">
|
|
861
|
+
<div className="grid grid-cols-3 gap-x-6 gap-y-4 pb-2 pt-1">
|
|
862
|
+
<FinancialDetailField
|
|
863
|
+
label="Job Title"
|
|
864
|
+
value={item.jobTitle || "—"}
|
|
865
|
+
/>
|
|
866
|
+
<FinancialDetailField
|
|
867
|
+
label="Company"
|
|
868
|
+
value={item.companyName || "—"}
|
|
869
|
+
/>
|
|
870
|
+
<FinancialDetailField
|
|
871
|
+
label="Start Date"
|
|
872
|
+
value={formatDateShort(item.startDate)}
|
|
873
|
+
/>
|
|
874
|
+
<FinancialDetailField
|
|
875
|
+
label="Status"
|
|
876
|
+
value={
|
|
877
|
+
item.stillInPosition === undefined
|
|
878
|
+
? "—"
|
|
879
|
+
: item.stillInPosition
|
|
880
|
+
? "Still in position"
|
|
881
|
+
: item.endDate
|
|
882
|
+
? `Ended ${formatDateShort(item.endDate)}`
|
|
883
|
+
: "No longer in position"
|
|
884
|
+
}
|
|
885
|
+
/>
|
|
886
|
+
{item.companyAddress && (
|
|
887
|
+
<FinancialDetailField
|
|
888
|
+
label="Company Address"
|
|
889
|
+
value={item.companyAddress}
|
|
890
|
+
/>
|
|
891
|
+
)}
|
|
892
|
+
</div>
|
|
893
|
+
</AccordionContent>
|
|
894
|
+
</AccordionItem>
|
|
895
|
+
))}
|
|
896
|
+
</Accordion>
|
|
810
897
|
{totalMonthly && (
|
|
811
898
|
<FinancialSubtotalFrame>
|
|
812
899
|
<FinancialSubtotalBlock
|
|
@@ -865,23 +952,34 @@ export interface ExpensesCardProps {
|
|
|
865
952
|
items: ExpensesCardItem[];
|
|
866
953
|
/** Pre-formatted total monthly expenses e.g. "$2,100" */
|
|
867
954
|
totalMonthly?: string;
|
|
955
|
+
/** Remove the outer card border. Use when the card is already inside a bordered container. */
|
|
956
|
+
borderless?: boolean;
|
|
868
957
|
}
|
|
869
958
|
|
|
870
959
|
/**
|
|
871
960
|
* Display card for applicant expense items.
|
|
872
961
|
* Each expense renders as an icon-labelled row with a destructive amount value.
|
|
873
962
|
*/
|
|
874
|
-
export function ExpensesCard({
|
|
963
|
+
export function ExpensesCard({
|
|
964
|
+
items,
|
|
965
|
+
totalMonthly,
|
|
966
|
+
borderless = false,
|
|
967
|
+
}: ExpensesCardProps) {
|
|
875
968
|
if (items.length === 0) {
|
|
876
969
|
return (
|
|
877
|
-
<div className="
|
|
970
|
+
<div className={cn("px-5 py-4", !borderless && "border border-border")}>
|
|
878
971
|
<p className="text-sm text-muted-foreground">No expenses recorded.</p>
|
|
879
972
|
</div>
|
|
880
973
|
);
|
|
881
974
|
}
|
|
882
975
|
|
|
883
976
|
return (
|
|
884
|
-
<div
|
|
977
|
+
<div
|
|
978
|
+
className={cn(
|
|
979
|
+
"overflow-hidden flex flex-col",
|
|
980
|
+
!borderless && "border border-border",
|
|
981
|
+
)}
|
|
982
|
+
>
|
|
885
983
|
<div className="flex flex-col">
|
|
886
984
|
{items.map((item, i) => {
|
|
887
985
|
const Icon = getExpenseIcon(item.expenseType);
|
|
@@ -106,7 +106,7 @@ export function SummaryReportDrawer({
|
|
|
106
106
|
showCloseButton={false}
|
|
107
107
|
className="w-[min(1080px,90vw)] max-w-none p-0"
|
|
108
108
|
>
|
|
109
|
-
<div className="flex max-h-[100dvh] min-h-0 flex-1 flex-col overflow-hidden px-8 py-6">
|
|
109
|
+
<div className="flex max-h-[100dvh] min-h-0 flex-1 flex-col gap-4 overflow-hidden px-8 py-6">
|
|
110
110
|
{/* ── Header chrome ── */}
|
|
111
111
|
<div className="shrink-0 space-y-4">
|
|
112
112
|
<div className="flex flex-col gap-3">
|
|
@@ -147,7 +147,7 @@ export function SummaryReportDrawer({
|
|
|
147
147
|
{contactName} View
|
|
148
148
|
</span>
|
|
149
149
|
<Button
|
|
150
|
-
variant="outline"
|
|
150
|
+
variant="outline-secondary"
|
|
151
151
|
size="sm"
|
|
152
152
|
onClick={onCreateJointView}
|
|
153
153
|
>
|
|
@@ -83,7 +83,7 @@ export function PropertyHoldingsSection({
|
|
|
83
83
|
{items.map((item, i) => (
|
|
84
84
|
<div
|
|
85
85
|
key={`${item.address}-${i}`}
|
|
86
|
-
className={i
|
|
86
|
+
className={i % 2 !== 0 ? "border-l border-border pl-5" : "pr-5"}
|
|
87
87
|
>
|
|
88
88
|
<PropertyCard {...item} borderless />
|
|
89
89
|
</div>
|