@wealthx/shadcn 1.1.0 → 1.2.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 +235 -154
- package/CHANGELOG.md +6 -0
- package/dist/{chunk-6OJF6XRN.mjs → chunk-24FUO7TD.mjs} +4 -8
- package/dist/{chunk-4AJ5HWHD.mjs → chunk-2I5S2AMY.mjs} +3 -3
- package/dist/chunk-2SF672SZ.mjs +161 -0
- package/dist/{chunk-GPRJQ24C.mjs → chunk-34NWQURD.mjs} +2 -2
- package/dist/{chunk-MQ72DIBH.mjs → chunk-3GF7OVTP.mjs} +14 -5
- package/dist/chunk-3WMX6KWS.mjs +245 -0
- package/dist/{chunk-PMKODV6M.mjs → chunk-462HMNO4.mjs} +6 -10
- package/dist/chunk-4CX4SBRO.mjs +153 -0
- package/dist/chunk-4MN6UQHG.mjs +443 -0
- package/dist/{chunk-GLW2UO6O.mjs → chunk-5QQVZTVZ.mjs} +82 -61
- package/dist/{chunk-BGP2N52Z.mjs → chunk-66MI7Q4B.mjs} +5 -5
- package/dist/chunk-6FCGKSZX.mjs +268 -0
- package/dist/{chunk-CGOKTPXU.mjs → chunk-6JQFUE5I.mjs} +20 -23
- package/dist/{chunk-Z3MK2KKZ.mjs → chunk-7DHU4VGG.mjs} +7 -3
- package/dist/{chunk-VZ2NR7L3.mjs → chunk-7PYJD5JI.mjs} +35 -27
- package/dist/{chunk-JU2RUWHF.mjs → chunk-7XJHLGUV.mjs} +1 -1
- package/dist/{chunk-BMFN37JH.mjs → chunk-7YAU5CY6.mjs} +1 -1
- package/dist/chunk-A56YQQHG.mjs +402 -0
- package/dist/chunk-AH52LG6N.mjs +315 -0
- package/dist/{chunk-SLWCCURD.mjs → chunk-CLIN5525.mjs} +8 -4
- package/dist/{chunk-3VQNJ235.mjs → chunk-CSDO6VBW.mjs} +7 -0
- package/dist/chunk-D4ILTPOG.mjs +293 -0
- package/dist/{chunk-HS7TFG7V.mjs → chunk-D6ID6M4V.mjs} +1 -1
- package/dist/chunk-DOH3EHX7.mjs +378 -0
- package/dist/{chunk-MJIEMGRD.mjs → chunk-EFRENWEJ.mjs} +9 -17
- package/dist/{chunk-YBXCIF5Q.mjs → chunk-ERGGHC2V.mjs} +36 -49
- package/dist/{chunk-OXQQNQZI.mjs → chunk-FEZKMUCF.mjs} +10 -1
- package/dist/{chunk-55CEW76V.mjs → chunk-FH6QVUVZ.mjs} +1 -1
- package/dist/chunk-FMAXJ2SI.mjs +71 -0
- package/dist/chunk-FZIXGLMV.mjs +173 -0
- package/dist/{chunk-DS2AMHN2.mjs → chunk-GYMYRIZP.mjs} +2 -2
- package/dist/{chunk-KQDD5MU3.mjs → chunk-H45TKD34.mjs} +5 -5
- package/dist/{chunk-BBJBJSXQ.mjs → chunk-J5UICVJS.mjs} +1 -1
- package/dist/{chunk-RL772EH7.mjs → chunk-JHJHG4GO.mjs} +4 -12
- package/dist/{chunk-RN67642N.mjs → chunk-KMCGSZTX.mjs} +47 -41
- package/dist/{chunk-FHNT55I5.mjs → chunk-KUDCQ4FI.mjs} +4 -4
- package/dist/chunk-LE6YFY6D.mjs +209 -0
- package/dist/{chunk-NLLKTU4B.mjs → chunk-LLVQKSU3.mjs} +21 -17
- package/dist/{chunk-KKHTJNMM.mjs → chunk-MARPPFOJ.mjs} +8 -4
- package/dist/{chunk-6AFMNC42.mjs → chunk-N2PT566P.mjs} +15 -11
- package/dist/chunk-NLCKVHWB.mjs +161 -0
- package/dist/{chunk-YN5SYTOO.mjs → chunk-NQPOYKAQ.mjs} +9 -5
- package/dist/{chunk-ZZV5JVNW.mjs → chunk-NSLMILBT.mjs} +3 -7
- package/dist/chunk-NXA3CZ7A.mjs +248 -0
- package/dist/chunk-OGOYQ7BG.mjs +150 -0
- package/dist/{chunk-3NQGYJEZ.mjs → chunk-P6AM5V7O.mjs} +10 -18
- package/dist/{chunk-CZ3BW5GL.mjs → chunk-P76HMUI6.mjs} +5 -11
- package/dist/chunk-PCPLO5HT.mjs +671 -0
- package/dist/chunk-PG6K5XEC.mjs +475 -0
- package/dist/{chunk-5JGQAAQV.mjs → chunk-PJHPSRYD.mjs} +84 -62
- package/dist/{chunk-DDPA2XXS.mjs → chunk-PMB3A7V3.mjs} +2 -2
- package/dist/chunk-PR6V5XKM.mjs +209 -0
- package/dist/{chunk-46OFHMQA.mjs → chunk-Q76O3RIQ.mjs} +10 -6
- package/dist/chunk-QVKWW6KE.mjs +272 -0
- package/dist/chunk-RGU7HOEC.mjs +140 -0
- package/dist/{chunk-JF4PHPD5.mjs → chunk-RGVKLTLH.mjs} +4 -4
- package/dist/{chunk-VG6UF6UT.mjs → chunk-RP3SQYA3.mjs} +2 -2
- package/dist/chunk-RRBS6D63.mjs +163 -0
- package/dist/{chunk-UEL4RD5P.mjs → chunk-SMQ3DG25.mjs} +80 -67
- package/dist/chunk-SPJ5KXW7.mjs +199 -0
- package/dist/chunk-SYOD63OZ.mjs +225 -0
- package/dist/chunk-UFYSFDER.mjs +42 -0
- package/dist/chunk-VACKZOMY.mjs +190 -0
- package/dist/chunk-VLQZANBF.mjs +42 -0
- package/dist/chunk-WA6O6EUR.mjs +1885 -0
- package/dist/{chunk-E3K6O4FZ.mjs → chunk-WAZD7NFU.mjs} +5 -2
- package/dist/chunk-WG6JGJXB.mjs +165 -0
- package/dist/{chunk-I64K754C.mjs → chunk-WNGWBVLV.mjs} +2 -2
- package/dist/{chunk-3U7SD3MS.mjs → chunk-WOEHFRGB.mjs} +3 -3
- package/dist/{chunk-DKZRJOMF.mjs → chunk-XIRTEFKH.mjs} +12 -12
- package/dist/chunk-Y6DWJSKZ.mjs +79 -0
- package/dist/chunk-YKPROFLB.mjs +161 -0
- package/dist/{chunk-CJ46PDXE.mjs → chunk-ZRO5JO3H.mjs} +106 -66
- package/dist/{chunk-VYMHBV6D.mjs → chunk-ZU4NV6RG.mjs} +5 -3
- package/dist/components/ui/accordion.js +40 -4
- package/dist/components/ui/accordion.mjs +2 -2
- package/dist/components/ui/add-column-modal.js +789 -0
- package/dist/components/ui/add-column-modal.mjs +17 -0
- package/dist/components/ui/add-lead-modal.js +647 -0
- package/dist/components/ui/add-lead-modal.mjs +16 -0
- package/dist/components/ui/ai-assistant-drawer.js +686 -0
- package/dist/components/ui/ai-assistant-drawer.mjs +16 -0
- package/dist/components/ui/alert-dialog.js +37 -5
- package/dist/components/ui/alert-dialog.mjs +4 -4
- package/dist/components/ui/alert.js +37 -11
- package/dist/components/ui/alert.mjs +2 -2
- package/dist/components/ui/avatar.js +36 -8
- package/dist/components/ui/avatar.mjs +2 -2
- package/dist/components/ui/backoffice-alert-history-chart.js +624 -0
- package/dist/components/ui/backoffice-alert-history-chart.mjs +16 -0
- package/dist/components/ui/backoffice-contact-history-chart.js +687 -0
- package/dist/components/ui/backoffice-contact-history-chart.mjs +16 -0
- package/dist/components/ui/badge.js +37 -2
- package/dist/components/ui/badge.mjs +2 -2
- package/dist/components/ui/borrowing-capacity-line-chart.js +639 -0
- package/dist/components/ui/borrowing-capacity-line-chart.mjs +16 -0
- package/dist/components/ui/button.js +35 -3
- package/dist/components/ui/button.mjs +2 -2
- package/dist/components/ui/calendar.js +43 -19
- package/dist/components/ui/calendar.mjs +3 -3
- package/dist/components/ui/card.js +40 -4
- package/dist/components/ui/card.mjs +2 -2
- package/dist/components/ui/cash-balance-line-chart.js +627 -0
- package/dist/components/ui/cash-balance-line-chart.mjs +16 -0
- package/dist/components/ui/cashflow-bar-chart.js +123 -69
- package/dist/components/ui/cashflow-bar-chart.mjs +8 -8
- package/dist/components/ui/checkbox.js +36 -5
- package/dist/components/ui/checkbox.mjs +2 -3
- package/dist/components/ui/chip.js +37 -2
- package/dist/components/ui/chip.mjs +3 -3
- package/dist/components/ui/combobox.js +68 -49
- package/dist/components/ui/combobox.mjs +2 -2
- package/dist/components/ui/data-table.js +160 -88
- package/dist/components/ui/data-table.mjs +10 -11
- package/dist/components/ui/date-picker.js +44 -20
- package/dist/components/ui/date-picker.mjs +6 -7
- package/dist/components/ui/dialog.js +44 -12
- package/dist/components/ui/dialog.mjs +4 -4
- package/dist/components/ui/drawer.js +46 -10
- package/dist/components/ui/drawer.mjs +3 -3
- package/dist/components/ui/dropdown-menu.js +40 -16
- package/dist/components/ui/dropdown-menu.mjs +3 -3
- package/dist/components/ui/empty.js +41 -5
- package/dist/components/ui/empty.mjs +2 -2
- package/dist/components/ui/expense-bar-chart.js +165 -66
- package/dist/components/ui/expense-bar-chart.mjs +8 -8
- package/dist/components/ui/field.js +53 -21
- package/dist/components/ui/field.mjs +4 -4
- package/dist/components/ui/financial-cards.js +1002 -0
- package/dist/components/ui/financial-cards.mjs +24 -0
- package/dist/components/ui/financial-drawers.js +637 -0
- package/dist/components/ui/financial-drawers.mjs +17 -0
- package/dist/components/ui/financial-primitives.js +218 -0
- package/dist/components/ui/financial-primitives.mjs +22 -0
- package/dist/components/ui/financial-sections.js +1422 -0
- package/dist/components/ui/financial-sections.mjs +30 -0
- package/dist/components/ui/form-primitives.js +682 -0
- package/dist/components/ui/form-primitives.mjs +19 -0
- package/dist/components/ui/income-bar-chart.js +163 -65
- package/dist/components/ui/income-bar-chart.mjs +8 -8
- package/dist/components/ui/input-group.js +43 -7
- package/dist/components/ui/input-group.mjs +5 -5
- package/dist/components/ui/input-otp.js +39 -3
- package/dist/components/ui/input-otp.mjs +2 -2
- package/dist/components/ui/input.js +34 -2
- package/dist/components/ui/input.mjs +2 -2
- package/dist/components/ui/kanban-column.js +1143 -0
- package/dist/components/ui/kanban-column.mjs +20 -0
- package/dist/components/ui/label.js +35 -7
- package/dist/components/ui/label.mjs +2 -2
- package/dist/components/ui/opportunity-card.js +960 -0
- package/dist/components/ui/opportunity-card.mjs +20 -0
- package/dist/components/ui/opportunity-edit-modals.js +3360 -0
- package/dist/components/ui/opportunity-edit-modals.mjs +37 -0
- package/dist/components/ui/opportunity-summary-tab.js +4365 -0
- package/dist/components/ui/opportunity-summary-tab.mjs +34 -0
- package/dist/components/ui/pagination.js +35 -3
- package/dist/components/ui/pagination.mjs +3 -3
- package/dist/components/ui/pipeline-alerts.js +103 -0
- package/dist/components/ui/pipeline-alerts.mjs +8 -0
- package/dist/components/ui/pipeline-board.js +1408 -0
- package/dist/components/ui/pipeline-board.mjs +24 -0
- package/dist/components/ui/pipeline-chart.js +216 -0
- package/dist/components/ui/pipeline-chart.mjs +10 -0
- package/dist/components/ui/pipeline-dialogs.js +1183 -0
- package/dist/components/ui/pipeline-dialogs.mjs +23 -0
- package/dist/components/ui/pipeline-primitives.js +300 -0
- package/dist/components/ui/pipeline-primitives.mjs +11 -0
- package/dist/components/ui/popover.js +45 -4
- package/dist/components/ui/popover.mjs +3 -3
- package/dist/components/ui/progress.js +33 -1
- package/dist/components/ui/progress.mjs +2 -2
- package/dist/components/ui/property-cashflow-doughnut-chart.js +523 -0
- package/dist/components/ui/property-cashflow-doughnut-chart.mjs +16 -0
- package/dist/components/ui/property-debt-equity-doughnut-chart.js +521 -0
- package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +16 -0
- package/dist/components/ui/property-mobile-estimate-line-chart.js +682 -0
- package/dist/components/ui/property-mobile-estimate-line-chart.mjs +16 -0
- package/dist/components/ui/radio-group.js +33 -1
- package/dist/components/ui/radio-group.mjs +2 -2
- package/dist/components/ui/select.js +66 -26
- package/dist/components/ui/select.mjs +3 -3
- package/dist/components/ui/separator.js +33 -1
- package/dist/components/ui/separator.mjs +2 -2
- package/dist/components/ui/sheet.js +37 -9
- package/dist/components/ui/sheet.mjs +3 -3
- package/dist/components/ui/skeleton.js +33 -1
- package/dist/components/ui/skeleton.mjs +2 -2
- package/dist/components/ui/slider.js +86 -102
- package/dist/components/ui/slider.mjs +2 -2
- package/dist/components/ui/spinner.js +33 -1
- package/dist/components/ui/spinner.mjs +2 -2
- package/dist/components/ui/stage-timeline.js +579 -0
- package/dist/components/ui/stage-timeline.mjs +15 -0
- package/dist/components/ui/switch.js +37 -4
- package/dist/components/ui/switch.mjs +2 -3
- package/dist/components/ui/table.js +37 -5
- package/dist/components/ui/table.mjs +2 -2
- package/dist/components/ui/tabs.js +36 -12
- package/dist/components/ui/tabs.mjs +2 -2
- package/dist/components/ui/textarea.js +34 -2
- package/dist/components/ui/textarea.mjs +2 -2
- package/dist/components/ui/toggle-group.js +35 -4
- package/dist/components/ui/toggle-group.mjs +3 -4
- package/dist/components/ui/toggle.js +35 -4
- package/dist/components/ui/toggle.mjs +2 -3
- package/dist/components/ui/tooltip.js +51 -22
- package/dist/components/ui/tooltip.mjs +3 -3
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +528 -0
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +16 -0
- package/dist/components/ui/transactions-income-expense-bar-chart.js +76 -38
- package/dist/components/ui/transactions-income-expense-bar-chart.mjs +8 -8
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +528 -0
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +16 -0
- package/dist/index.js +11616 -3831
- package/dist/index.mjs +333 -161
- package/dist/lib/theme-provider.js +10 -1
- package/dist/lib/theme-provider.mjs +1 -1
- package/dist/lib/typography.js +8 -0
- package/dist/lib/typography.mjs +3 -1
- package/dist/lib/utils.js +33 -1
- package/dist/lib/utils.mjs +1 -1
- package/dist/styles.css +1 -1
- package/package.json +140 -5
- package/src/components/index.tsx +296 -42
- package/src/components/ui/accordion.tsx +6 -3
- package/src/components/ui/add-column-modal.tsx +339 -0
- package/src/components/ui/add-lead-modal.tsx +290 -0
- package/src/components/ui/ai-assistant-drawer.tsx +408 -0
- package/src/components/ui/alert-dialog.tsx +80 -54
- package/src/components/ui/alert.tsx +28 -28
- package/src/components/ui/avatar.tsx +30 -29
- package/src/components/ui/backoffice-alert-history-chart.tsx +260 -0
- package/src/components/ui/backoffice-contact-history-chart.tsx +325 -0
- package/src/components/ui/badge.tsx +17 -15
- package/src/components/ui/borrowing-capacity-line-chart.tsx +357 -0
- package/src/components/ui/button.tsx +30 -27
- package/src/components/ui/calendar.tsx +53 -67
- package/src/components/ui/card.tsx +27 -24
- package/src/components/ui/cash-balance-line-chart.tsx +302 -0
- package/src/components/ui/cashflow-bar-chart.tsx +104 -77
- package/src/components/ui/chart-shared.tsx +176 -15
- package/src/components/ui/checkbox.tsx +30 -26
- package/src/components/ui/combobox.tsx +78 -72
- package/src/components/ui/data-table.tsx +160 -99
- package/src/components/ui/date-picker.tsx +0 -2
- package/src/components/ui/dialog.tsx +70 -60
- package/src/components/ui/drawer.tsx +57 -48
- package/src/components/ui/dropdown-menu.tsx +90 -82
- package/src/components/ui/empty.tsx +31 -27
- package/src/components/ui/expense-bar-chart.tsx +83 -65
- package/src/components/ui/field.tsx +70 -62
- package/src/components/ui/financial-cards.tsx +830 -0
- package/src/components/ui/financial-drawers.tsx +339 -0
- package/src/components/ui/financial-primitives.tsx +331 -0
- package/src/components/ui/financial-sections.tsx +672 -0
- package/src/components/ui/form-primitives.tsx +536 -0
- package/src/components/ui/income-bar-chart.tsx +79 -60
- package/src/components/ui/input-group.tsx +41 -34
- package/src/components/ui/input-otp.tsx +29 -24
- package/src/components/ui/input.tsx +8 -8
- package/src/components/ui/kanban-column.tsx +333 -0
- package/src/components/ui/label.tsx +9 -12
- package/src/components/ui/opportunity-card.tsx +616 -0
- package/src/components/ui/opportunity-edit-modals.tsx +2528 -0
- package/src/components/ui/opportunity-summary-tab.tsx +579 -0
- package/src/components/ui/pipeline-alerts.tsx +74 -0
- package/src/components/ui/pipeline-board.tsx +268 -0
- package/src/components/ui/pipeline-chart.tsx +173 -0
- package/src/components/ui/pipeline-dialogs.tsx +303 -0
- package/src/components/ui/pipeline-primitives.tsx +108 -0
- package/src/components/ui/popover.tsx +41 -36
- package/src/components/ui/property-cashflow-doughnut-chart.tsx +188 -0
- package/src/components/ui/property-debt-equity-doughnut-chart.tsx +185 -0
- package/src/components/ui/property-mobile-estimate-line-chart.tsx +393 -0
- package/src/components/ui/select.tsx +65 -52
- package/src/components/ui/sheet.tsx +55 -52
- package/src/components/ui/slider.tsx +54 -77
- package/src/components/ui/stage-timeline.tsx +205 -0
- package/src/components/ui/switch.tsx +42 -29
- package/src/components/ui/table.tsx +28 -28
- package/src/components/ui/tabs.tsx +22 -28
- package/src/components/ui/textarea.tsx +8 -8
- package/src/components/ui/toggle-group.tsx +0 -2
- package/src/components/ui/toggle.tsx +13 -15
- package/src/components/ui/tooltip.tsx +30 -28
- package/src/components/ui/transactions-expense-categories-doughnut-chart.tsx +191 -0
- package/src/components/ui/transactions-income-expense-bar-chart.tsx +45 -38
- package/src/components/ui/transactions-liabilities-breakdown-doughnut-chart.tsx +191 -0
- package/src/lib/theme-provider.tsx +10 -0
- package/src/lib/typography.ts +9 -0
- package/src/lib/utils.ts +41 -3
- package/src/styles/globals.css +371 -124
- package/src/styles/styles-css.ts +1 -1
- package/tsup.config.ts +27 -0
- package/dist/chunk-3EQP72AW.mjs +0 -58
- package/dist/chunk-K74JRTJR.mjs +0 -105
- package/dist/chunk-V7CNWJT3.mjs +0 -10
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Button } from "./button";
|
|
3
|
+
import { Separator } from "./separator";
|
|
4
|
+
import {
|
|
5
|
+
Accordion,
|
|
6
|
+
AccordionItem,
|
|
7
|
+
AccordionTrigger,
|
|
8
|
+
AccordionContent,
|
|
9
|
+
} from "./accordion";
|
|
10
|
+
import {
|
|
11
|
+
PropertyCard,
|
|
12
|
+
DebtCard,
|
|
13
|
+
OtherLiabilityCard,
|
|
14
|
+
AlertCard,
|
|
15
|
+
type PropertyCardProps,
|
|
16
|
+
type DebtCardProps,
|
|
17
|
+
type OtherLiabilityCardProps,
|
|
18
|
+
type AlertCardProps,
|
|
19
|
+
type AlertActionType,
|
|
20
|
+
type AlertSeverity,
|
|
21
|
+
} from "./financial-cards";
|
|
22
|
+
import {
|
|
23
|
+
FinancialCardHeader,
|
|
24
|
+
FinancialDetailField,
|
|
25
|
+
FinancialLineItem,
|
|
26
|
+
FinancialSectionLabel,
|
|
27
|
+
FinancialSubtotalFrame,
|
|
28
|
+
FinancialSubtotalBlock,
|
|
29
|
+
} from "./financial-primitives";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Financial section components — WealthX DS (Level 4)
|
|
33
|
+
*
|
|
34
|
+
* Composed from Level 3 cards into full page sections.
|
|
35
|
+
* Used inside the Summary Report Drawer and Opportunity Details Drawer.
|
|
36
|
+
*
|
|
37
|
+
* ```
|
|
38
|
+
* Level 2 → FinancialDetailField, FinancialLvrBar … (financial-primitives)
|
|
39
|
+
* Level 3 → PropertyCard, DebtCard, AlertCard … (financial-cards)
|
|
40
|
+
* Level 4 → PropertyHoldingsSection, DebtSection … ← here
|
|
41
|
+
* Level 5 → SummaryReportDrawer, OpportunityDetailsDrawer …
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* Component inventory:
|
|
45
|
+
* FinancialViewSection — bordered card wrapping income + properties + current liabilities
|
|
46
|
+
* PropertyHoldingsSection — grid of PropertyCards under a section header
|
|
47
|
+
* DebtSection — grid of DebtCards under a section header
|
|
48
|
+
* OtherLiabilitiesSection — grid of OtherLiabilityCards under a section header
|
|
49
|
+
* IncomeExpenseSection — 3-column income / expenses / future-payments grid
|
|
50
|
+
* AlertAccordion — collapsible accordion wrapping a grid of AlertCards
|
|
51
|
+
* LoanScenarioSection — read-only Loan Quiz card (4-column grid)
|
|
52
|
+
* FinancialBottomSummary — 3 stacked summary cards: cashflow / assets / net position
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// PropertyHoldingsSection
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
export interface PropertyHoldingsSectionProps {
|
|
60
|
+
/** Section heading. Defaults to "Property Holdings". */
|
|
61
|
+
title?: string;
|
|
62
|
+
/** Each item maps 1:1 to a PropertyCard. */
|
|
63
|
+
items: PropertyCardProps[];
|
|
64
|
+
/**
|
|
65
|
+
* When true renders columns without individual card borders, separated by a 1px divider.
|
|
66
|
+
* Use inside `FinancialViewSection` to match the Figma Financial View card layout.
|
|
67
|
+
*/
|
|
68
|
+
borderless?: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Two-column grid of PropertyCards under a section header. */
|
|
72
|
+
export function PropertyHoldingsSection({
|
|
73
|
+
title = "Property Holdings",
|
|
74
|
+
items,
|
|
75
|
+
borderless = false,
|
|
76
|
+
}: PropertyHoldingsSectionProps) {
|
|
77
|
+
if (items.length === 0) return null;
|
|
78
|
+
return (
|
|
79
|
+
<div>
|
|
80
|
+
<FinancialCardHeader>{title}</FinancialCardHeader>
|
|
81
|
+
{borderless ? (
|
|
82
|
+
<div className="grid grid-cols-2">
|
|
83
|
+
{items.map((item, i) => (
|
|
84
|
+
<div
|
|
85
|
+
key={`${item.address}-${i}`}
|
|
86
|
+
className={i > 0 ? "border-l border-border pl-5" : "pr-5"}
|
|
87
|
+
>
|
|
88
|
+
<PropertyCard {...item} borderless />
|
|
89
|
+
</div>
|
|
90
|
+
))}
|
|
91
|
+
</div>
|
|
92
|
+
) : (
|
|
93
|
+
<div className="grid grid-cols-2 gap-5">
|
|
94
|
+
{items.map((item, i) => (
|
|
95
|
+
<PropertyCard key={`${item.address}-${i}`} {...item} />
|
|
96
|
+
))}
|
|
97
|
+
</div>
|
|
98
|
+
)}
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// DebtSection
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
export interface DebtSectionProps {
|
|
108
|
+
/** Section heading. Defaults to "Mortgages & Investment Loans". */
|
|
109
|
+
title?: string;
|
|
110
|
+
/** Each item maps 1:1 to a DebtCard. */
|
|
111
|
+
items: DebtCardProps[];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Two-column grid of DebtCards under a section header. */
|
|
115
|
+
export function DebtSection({
|
|
116
|
+
title = "Mortgages & Investment Loans",
|
|
117
|
+
items,
|
|
118
|
+
}: DebtSectionProps) {
|
|
119
|
+
if (items.length === 0) return null;
|
|
120
|
+
return (
|
|
121
|
+
<div>
|
|
122
|
+
<FinancialCardHeader>{title}</FinancialCardHeader>
|
|
123
|
+
<div className="grid grid-cols-2 gap-3">
|
|
124
|
+
{items.map((item, i) => (
|
|
125
|
+
<DebtCard key={item.lenderName ?? i} {...item} />
|
|
126
|
+
))}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// OtherLiabilitiesSection
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
export interface OtherLiabilitiesSectionProps {
|
|
137
|
+
/** Section heading. Defaults to "Other Liabilities". */
|
|
138
|
+
title?: string;
|
|
139
|
+
/** Each item maps 1:1 to an OtherLiabilityCard. */
|
|
140
|
+
items: OtherLiabilityCardProps[];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Two-column grid of OtherLiabilityCards under a section header. */
|
|
144
|
+
export function OtherLiabilitiesSection({
|
|
145
|
+
title = "Other Liabilities",
|
|
146
|
+
items,
|
|
147
|
+
}: OtherLiabilitiesSectionProps) {
|
|
148
|
+
if (items.length === 0) return null;
|
|
149
|
+
return (
|
|
150
|
+
<div>
|
|
151
|
+
<FinancialCardHeader>{title}</FinancialCardHeader>
|
|
152
|
+
<div className="grid grid-cols-2 gap-5">
|
|
153
|
+
{items.map((item, i) => (
|
|
154
|
+
<OtherLiabilityCard
|
|
155
|
+
key={`${item.lenderName ?? item.type}-${i}`}
|
|
156
|
+
{...item}
|
|
157
|
+
/>
|
|
158
|
+
))}
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// IncomeExpenseSection
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
export interface SummaryLineItem {
|
|
169
|
+
label: string;
|
|
170
|
+
/** Formatted value string e.g. "$9,500". Renders "—" when falsy. */
|
|
171
|
+
value?: string | null;
|
|
172
|
+
/**
|
|
173
|
+
* When true renders the value in `text-destructive`.
|
|
174
|
+
* Use for expenses, liabilities, or negative cashflow rows.
|
|
175
|
+
*/
|
|
176
|
+
destructive?: boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface SummaryColumn {
|
|
180
|
+
/** Column heading override. */
|
|
181
|
+
label?: string;
|
|
182
|
+
items: SummaryLineItem[];
|
|
183
|
+
/** Formatted monthly average displayed in the tinted footer. */
|
|
184
|
+
monthlyAverage?: string;
|
|
185
|
+
/** Formatted 12-month total displayed in the tinted footer. */
|
|
186
|
+
totalLast12Months?: string;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface IncomeExpenseSectionProps {
|
|
190
|
+
income?: SummaryColumn;
|
|
191
|
+
expenses?: SummaryColumn;
|
|
192
|
+
futurePayments?: SummaryColumn;
|
|
193
|
+
/** Override the "Future Payments" column heading. */
|
|
194
|
+
futurePaymentsHeading?: string;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Three-column layout: income | expenses | future payments.
|
|
199
|
+
*
|
|
200
|
+
* Each column has a header, a scrollable list of `FinancialLineItem` rows,
|
|
201
|
+
* and a brand-tinted `FinancialSubtotalFrame` footer.
|
|
202
|
+
*/
|
|
203
|
+
export function IncomeExpenseSection({
|
|
204
|
+
income,
|
|
205
|
+
expenses,
|
|
206
|
+
futurePayments,
|
|
207
|
+
futurePaymentsHeading = "Future Payments",
|
|
208
|
+
}: IncomeExpenseSectionProps) {
|
|
209
|
+
return (
|
|
210
|
+
<div className="grid grid-cols-3">
|
|
211
|
+
{/* Income */}
|
|
212
|
+
<div className="flex flex-col pr-5">
|
|
213
|
+
<FinancialCardHeader>
|
|
214
|
+
{income?.label ?? "Average Monthly Income"}
|
|
215
|
+
</FinancialCardHeader>
|
|
216
|
+
<div className="flex flex-1 flex-col pb-4">
|
|
217
|
+
{(income?.items ?? []).map((item) => (
|
|
218
|
+
<FinancialLineItem
|
|
219
|
+
key={item.label}
|
|
220
|
+
label={item.label}
|
|
221
|
+
value={item.value}
|
|
222
|
+
destructive={item.destructive}
|
|
223
|
+
/>
|
|
224
|
+
))}
|
|
225
|
+
</div>
|
|
226
|
+
<FinancialSubtotalFrame>
|
|
227
|
+
<FinancialSubtotalBlock
|
|
228
|
+
monthlyAverage={income?.monthlyAverage}
|
|
229
|
+
totalLast12Months={income?.totalLast12Months}
|
|
230
|
+
/>
|
|
231
|
+
</FinancialSubtotalFrame>
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
{/* Expenses */}
|
|
235
|
+
<div className="flex flex-col border-x border-border px-5">
|
|
236
|
+
<FinancialCardHeader>
|
|
237
|
+
{expenses?.label ?? "Monthly Expenses and Commitments"}
|
|
238
|
+
</FinancialCardHeader>
|
|
239
|
+
<div className="flex flex-1 flex-col pb-4">
|
|
240
|
+
{(expenses?.items ?? []).map((item) => (
|
|
241
|
+
<FinancialLineItem
|
|
242
|
+
key={item.label}
|
|
243
|
+
label={item.label}
|
|
244
|
+
value={item.value}
|
|
245
|
+
destructive={item.destructive}
|
|
246
|
+
/>
|
|
247
|
+
))}
|
|
248
|
+
</div>
|
|
249
|
+
<FinancialSubtotalFrame>
|
|
250
|
+
<FinancialSubtotalBlock
|
|
251
|
+
monthlyAverage={expenses?.monthlyAverage}
|
|
252
|
+
totalLast12Months={expenses?.totalLast12Months}
|
|
253
|
+
/>
|
|
254
|
+
</FinancialSubtotalFrame>
|
|
255
|
+
</div>
|
|
256
|
+
|
|
257
|
+
{/* Future Payments */}
|
|
258
|
+
<div className="flex flex-col pl-5">
|
|
259
|
+
<FinancialCardHeader>
|
|
260
|
+
{futurePayments?.label ?? futurePaymentsHeading}
|
|
261
|
+
</FinancialCardHeader>
|
|
262
|
+
<div className="flex flex-1 flex-col pb-4">
|
|
263
|
+
{(futurePayments?.items ?? []).map((item) => (
|
|
264
|
+
<FinancialLineItem
|
|
265
|
+
key={item.label}
|
|
266
|
+
label={item.label}
|
|
267
|
+
value={item.value}
|
|
268
|
+
destructive={item.destructive}
|
|
269
|
+
/>
|
|
270
|
+
))}
|
|
271
|
+
</div>
|
|
272
|
+
<FinancialSubtotalFrame>
|
|
273
|
+
<FinancialSubtotalBlock
|
|
274
|
+
monthlyAverage={futurePayments?.monthlyAverage}
|
|
275
|
+
totalLast12Months={futurePayments?.totalLast12Months}
|
|
276
|
+
/>
|
|
277
|
+
</FinancialSubtotalFrame>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
// AlertAccordion
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
|
|
287
|
+
const SEVERITY_BG: Record<AlertSeverity, string> = {
|
|
288
|
+
NEED_ACTION: "bg-destructive text-destructive-foreground",
|
|
289
|
+
WATCH: "bg-warning text-warning-foreground",
|
|
290
|
+
INSIGHT: "bg-success text-success-foreground",
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
export interface AlertAccordionSavePayload {
|
|
294
|
+
alertId: string;
|
|
295
|
+
action: AlertActionType;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export interface AlertAccordionProps {
|
|
299
|
+
/** List of alerts — each maps 1:1 to an AlertCard. */
|
|
300
|
+
alerts: AlertCardProps[];
|
|
301
|
+
/**
|
|
302
|
+
* Called when the user clicks Save.
|
|
303
|
+
* Receives only alerts with a pending dismiss or snooze action selected.
|
|
304
|
+
* When omitted the Save button is never shown.
|
|
305
|
+
*/
|
|
306
|
+
onSaveActions?: (actions: AlertAccordionSavePayload[]) => void;
|
|
307
|
+
/** When `true` the Save button shows "Saving…" and is disabled. */
|
|
308
|
+
isSaving?: boolean;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Collapsible accordion wrapping a 3-column grid of AlertCards.
|
|
313
|
+
*
|
|
314
|
+
* - The trigger header shows the section title + severity count badges.
|
|
315
|
+
* - A Save button appears when the user has pending dismiss/snooze selections
|
|
316
|
+
* and `onSaveActions` is provided.
|
|
317
|
+
* - Returns `null` when `alerts` is empty.
|
|
318
|
+
*/
|
|
319
|
+
export function AlertAccordion({
|
|
320
|
+
alerts,
|
|
321
|
+
onSaveActions,
|
|
322
|
+
isSaving = false,
|
|
323
|
+
}: AlertAccordionProps) {
|
|
324
|
+
const [actionMap, setActionMap] = useState<Record<string, AlertActionType>>(
|
|
325
|
+
{},
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
const handleActionChange = (id: string) => (action: AlertActionType) => {
|
|
329
|
+
setActionMap((prev) => ({ ...prev, [id]: action }));
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const handleSave = (e: React.MouseEvent) => {
|
|
333
|
+
e.stopPropagation();
|
|
334
|
+
onSaveActions?.(
|
|
335
|
+
Object.entries(actionMap).map(([alertId, action]) => ({
|
|
336
|
+
alertId,
|
|
337
|
+
action,
|
|
338
|
+
})),
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const countBySeverity = alerts.reduce<Record<string, number>>((acc, a) => {
|
|
343
|
+
acc[a.severityCode] = (acc[a.severityCode] || 0) + 1;
|
|
344
|
+
return acc;
|
|
345
|
+
}, {});
|
|
346
|
+
|
|
347
|
+
const hasPendingActions = Object.keys(actionMap).length > 0;
|
|
348
|
+
|
|
349
|
+
if (alerts.length === 0) return null;
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<Accordion>
|
|
353
|
+
<AccordionItem value="alerts" className="border-0">
|
|
354
|
+
<AccordionTrigger className="min-h-14 cursor-pointer border border-primary/20 bg-primary/10 px-4 py-2.5 hover:bg-primary/10 hover:no-underline">
|
|
355
|
+
<div className="flex w-full items-center justify-between">
|
|
356
|
+
<div className="flex items-center gap-2.5">
|
|
357
|
+
<span className="text-label-medium text-foreground">Alerts</span>
|
|
358
|
+
{(["INSIGHT", "WATCH", "NEED_ACTION"] as const).map((code) =>
|
|
359
|
+
countBySeverity[code] ? (
|
|
360
|
+
<span
|
|
361
|
+
key={code}
|
|
362
|
+
className={`flex h-6 w-6 items-center justify-center rounded-full text-xs font-semibold leading-none ${SEVERITY_BG[code]}`}
|
|
363
|
+
>
|
|
364
|
+
{countBySeverity[code]}
|
|
365
|
+
</span>
|
|
366
|
+
) : null,
|
|
367
|
+
)}
|
|
368
|
+
</div>
|
|
369
|
+
{hasPendingActions && onSaveActions && (
|
|
370
|
+
<Button
|
|
371
|
+
variant="outline"
|
|
372
|
+
size="sm"
|
|
373
|
+
onClick={handleSave}
|
|
374
|
+
disabled={isSaving}
|
|
375
|
+
>
|
|
376
|
+
{isSaving ? "Saving..." : "Save"}
|
|
377
|
+
</Button>
|
|
378
|
+
)}
|
|
379
|
+
</div>
|
|
380
|
+
</AccordionTrigger>
|
|
381
|
+
<AccordionContent className="p-0 pb-0">
|
|
382
|
+
<div className="grid grid-cols-3 gap-2.5 border border-t-0 border-primary/20 p-3">
|
|
383
|
+
{alerts.map((alert) => (
|
|
384
|
+
<AlertCard
|
|
385
|
+
key={alert.id}
|
|
386
|
+
{...alert}
|
|
387
|
+
selectedAction={actionMap[alert.id] ?? null}
|
|
388
|
+
onActionChange={handleActionChange(alert.id)}
|
|
389
|
+
/>
|
|
390
|
+
))}
|
|
391
|
+
</div>
|
|
392
|
+
</AccordionContent>
|
|
393
|
+
</AccordionItem>
|
|
394
|
+
</Accordion>
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
// LoanScenarioSection
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
|
|
402
|
+
export interface LoanScenarioSectionProps {
|
|
403
|
+
/** Override the section heading. Defaults to "Loan Scenario (Loan Quiz)". */
|
|
404
|
+
title?: string;
|
|
405
|
+
/** "Lending Type" — e.g. "Home Loan", "Investment Loan" */
|
|
406
|
+
lendingType?: string;
|
|
407
|
+
purposeOfLoan?: string;
|
|
408
|
+
loanAmount?: string;
|
|
409
|
+
propertyEstimate?: string;
|
|
410
|
+
estLvr?: string;
|
|
411
|
+
/** Cash or deposit available e.g. "$120,000" */
|
|
412
|
+
cashDeposit?: string;
|
|
413
|
+
propertyAddress?: string;
|
|
414
|
+
duration?: string;
|
|
415
|
+
importantFeatures?: string;
|
|
416
|
+
topThreePriorities?: string;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Read-only Loan Quiz card — 4-column grid matching the LoanQuiz component in backoffice.
|
|
421
|
+
*
|
|
422
|
+
* Row 1: Lending Type | Purpose of Loan | Loan Amount | Property Estimate
|
|
423
|
+
* Row 2: EST LVR | Cash/Deposit | Property Address | Duration
|
|
424
|
+
* Row 3: Important Features | Top Three Priorities
|
|
425
|
+
*
|
|
426
|
+
* Mirrors `LoanQuiz.tsx` in backoffice OpportunityDetailsDrawer.
|
|
427
|
+
*/
|
|
428
|
+
export function LoanScenarioSection({
|
|
429
|
+
title = "Loan Scenario (Loan Quiz)",
|
|
430
|
+
lendingType,
|
|
431
|
+
purposeOfLoan,
|
|
432
|
+
loanAmount,
|
|
433
|
+
propertyEstimate,
|
|
434
|
+
estLvr,
|
|
435
|
+
cashDeposit,
|
|
436
|
+
propertyAddress,
|
|
437
|
+
duration,
|
|
438
|
+
importantFeatures,
|
|
439
|
+
topThreePriorities,
|
|
440
|
+
}: LoanScenarioSectionProps) {
|
|
441
|
+
return (
|
|
442
|
+
<div className="border border-border p-4">
|
|
443
|
+
<div className="mb-4">
|
|
444
|
+
<FinancialSectionLabel>{title}</FinancialSectionLabel>
|
|
445
|
+
</div>
|
|
446
|
+
<div className="grid grid-cols-4 gap-x-6 gap-y-4">
|
|
447
|
+
{/* Row 1 */}
|
|
448
|
+
<FinancialDetailField label="Lending Type" value={lendingType} />
|
|
449
|
+
<FinancialDetailField label="Purpose of Loan" value={purposeOfLoan} />
|
|
450
|
+
<FinancialDetailField label="Loan Amount" value={loanAmount} />
|
|
451
|
+
<FinancialDetailField
|
|
452
|
+
label="Property Estimate"
|
|
453
|
+
value={propertyEstimate}
|
|
454
|
+
/>
|
|
455
|
+
{/* Row 2 */}
|
|
456
|
+
<FinancialDetailField label="EST LVR" value={estLvr} />
|
|
457
|
+
<FinancialDetailField label="Cash/Deposit" value={cashDeposit} />
|
|
458
|
+
<FinancialDetailField
|
|
459
|
+
label="Property Address"
|
|
460
|
+
value={propertyAddress}
|
|
461
|
+
/>
|
|
462
|
+
<FinancialDetailField label="Duration" value={duration} />
|
|
463
|
+
{/* Row 3 */}
|
|
464
|
+
<FinancialDetailField
|
|
465
|
+
label="Important Features"
|
|
466
|
+
value={importantFeatures}
|
|
467
|
+
/>
|
|
468
|
+
<FinancialDetailField
|
|
469
|
+
label="Top Three Priorities"
|
|
470
|
+
value={topThreePriorities}
|
|
471
|
+
/>
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// ---------------------------------------------------------------------------
|
|
478
|
+
// FinancialBottomSummary
|
|
479
|
+
// ---------------------------------------------------------------------------
|
|
480
|
+
|
|
481
|
+
export interface BottomSummaryLineItem {
|
|
482
|
+
label: string;
|
|
483
|
+
value?: string | null;
|
|
484
|
+
destructive?: boolean;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export interface FinancialBottomSummaryProps {
|
|
488
|
+
/** Incoming vs Outgoing Summary card items. */
|
|
489
|
+
cashflowItems?: BottomSummaryLineItem[];
|
|
490
|
+
/** Net surplus/deficit value e.g. "$1,050". */
|
|
491
|
+
netSurplus?: string;
|
|
492
|
+
/** Whether net surplus is negative (renders in destructive color). */
|
|
493
|
+
netSurplusDestructive?: boolean;
|
|
494
|
+
/** Assets card items. */
|
|
495
|
+
assetItems?: BottomSummaryLineItem[];
|
|
496
|
+
/** Total assets value e.g. "$3,630,000". */
|
|
497
|
+
totalAssets?: string;
|
|
498
|
+
/** Total liabilities value e.g. "$1,263,200". Renders in destructive. */
|
|
499
|
+
totalLiabilities?: string;
|
|
500
|
+
/** Net position value e.g. "$2,366,800". */
|
|
501
|
+
netPosition?: string;
|
|
502
|
+
/** Whether net position is negative. */
|
|
503
|
+
netPositionDestructive?: boolean;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Three summary cards stacked vertically:
|
|
508
|
+
* 1. Incoming vs Outgoing Summary — cashflow line items + net surplus
|
|
509
|
+
* 2. Assets — asset line items + total
|
|
510
|
+
* 3. Net Position — total liabilities + assets + net position
|
|
511
|
+
*
|
|
512
|
+
* Mirrors `financial-bottom-summary.tsx` in backoffice.
|
|
513
|
+
*/
|
|
514
|
+
export function FinancialBottomSummary({
|
|
515
|
+
cashflowItems = [],
|
|
516
|
+
netSurplus,
|
|
517
|
+
netSurplusDestructive = false,
|
|
518
|
+
assetItems = [],
|
|
519
|
+
totalAssets,
|
|
520
|
+
totalLiabilities,
|
|
521
|
+
netPosition,
|
|
522
|
+
netPositionDestructive = false,
|
|
523
|
+
}: FinancialBottomSummaryProps) {
|
|
524
|
+
return (
|
|
525
|
+
<div className="border border-border">
|
|
526
|
+
{/* Card 1: Incoming vs Outgoing Summary */}
|
|
527
|
+
<div className="p-4">
|
|
528
|
+
<div className="mb-3">
|
|
529
|
+
<FinancialSectionLabel>
|
|
530
|
+
Incoming vs Outgoing Summary
|
|
531
|
+
</FinancialSectionLabel>
|
|
532
|
+
</div>
|
|
533
|
+
<div className="flex flex-col">
|
|
534
|
+
{cashflowItems.map((item) => (
|
|
535
|
+
<FinancialLineItem
|
|
536
|
+
key={item.label}
|
|
537
|
+
label={item.label}
|
|
538
|
+
value={item.value}
|
|
539
|
+
destructive={item.destructive}
|
|
540
|
+
/>
|
|
541
|
+
))}
|
|
542
|
+
</div>
|
|
543
|
+
<FinancialSubtotalFrame>
|
|
544
|
+
<FinancialSubtotalBlock
|
|
545
|
+
monthlyAverage={netSurplus}
|
|
546
|
+
label={netSurplusDestructive ? "Net Deficit" : "Net Surplus"}
|
|
547
|
+
/>
|
|
548
|
+
</FinancialSubtotalFrame>
|
|
549
|
+
</div>
|
|
550
|
+
|
|
551
|
+
<Separator />
|
|
552
|
+
|
|
553
|
+
{/* Card 2: Assets */}
|
|
554
|
+
<div className="p-4">
|
|
555
|
+
<div className="mb-3">
|
|
556
|
+
<FinancialSectionLabel>Assets</FinancialSectionLabel>
|
|
557
|
+
</div>
|
|
558
|
+
<div className="flex flex-col">
|
|
559
|
+
{assetItems.map((item) => (
|
|
560
|
+
<FinancialLineItem
|
|
561
|
+
key={item.label}
|
|
562
|
+
label={item.label}
|
|
563
|
+
value={item.value}
|
|
564
|
+
destructive={item.destructive}
|
|
565
|
+
/>
|
|
566
|
+
))}
|
|
567
|
+
</div>
|
|
568
|
+
<FinancialSubtotalFrame>
|
|
569
|
+
<FinancialSubtotalBlock
|
|
570
|
+
monthlyAverage={totalAssets}
|
|
571
|
+
label="Total Assets"
|
|
572
|
+
/>
|
|
573
|
+
</FinancialSubtotalFrame>
|
|
574
|
+
</div>
|
|
575
|
+
|
|
576
|
+
<Separator />
|
|
577
|
+
|
|
578
|
+
{/* Card 3: Net Position */}
|
|
579
|
+
<div className="p-4">
|
|
580
|
+
<div className="mb-3">
|
|
581
|
+
<FinancialSectionLabel>Net Position</FinancialSectionLabel>
|
|
582
|
+
</div>
|
|
583
|
+
<div className="flex flex-col">
|
|
584
|
+
<FinancialLineItem
|
|
585
|
+
label="Total Liabilities"
|
|
586
|
+
value={totalLiabilities}
|
|
587
|
+
destructive
|
|
588
|
+
/>
|
|
589
|
+
<FinancialLineItem label="Total Assets" value={totalAssets} />
|
|
590
|
+
</div>
|
|
591
|
+
<FinancialSubtotalFrame>
|
|
592
|
+
<FinancialSubtotalBlock
|
|
593
|
+
monthlyAverage={netPosition}
|
|
594
|
+
label={netPositionDestructive ? "Net Deficit" : "Net Position"}
|
|
595
|
+
/>
|
|
596
|
+
</FinancialSubtotalFrame>
|
|
597
|
+
</div>
|
|
598
|
+
</div>
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// ---------------------------------------------------------------------------
|
|
603
|
+
// FinancialViewSection
|
|
604
|
+
// ---------------------------------------------------------------------------
|
|
605
|
+
|
|
606
|
+
export interface FinancialViewSectionProps {
|
|
607
|
+
/** Override the "Financial View" section label. */
|
|
608
|
+
title?: string;
|
|
609
|
+
income?: IncomeExpenseSectionProps["income"];
|
|
610
|
+
expenses?: IncomeExpenseSectionProps["expenses"];
|
|
611
|
+
futurePayments?: IncomeExpenseSectionProps["futurePayments"];
|
|
612
|
+
futurePaymentsHeading?: string;
|
|
613
|
+
/** Section heading for property columns. Defaults to "Property Assets and Liabilities". */
|
|
614
|
+
propertyTitle?: string;
|
|
615
|
+
/** Each item renders as a borderless property column with a 1px divider. */
|
|
616
|
+
properties?: PropertyCardProps[];
|
|
617
|
+
/** Section heading for current liabilities. Defaults to "Current Liabilities". */
|
|
618
|
+
currentLiabilitiesTitle?: string;
|
|
619
|
+
/** Each item maps 1:1 to a DebtCard. */
|
|
620
|
+
currentLiabilities?: DebtCardProps[];
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Composite Financial View card — wraps income, property and current liabilities
|
|
625
|
+
* inside a single bordered container, matching the Figma Financial View design.
|
|
626
|
+
*
|
|
627
|
+
* Property columns render without individual card borders (borderless),
|
|
628
|
+
* separated by a 1px divider — same visual language as the income columns.
|
|
629
|
+
* Current Liabilities (DebtCards) retain their individual borders.
|
|
630
|
+
*/
|
|
631
|
+
export function FinancialViewSection({
|
|
632
|
+
title = "Financial View",
|
|
633
|
+
income,
|
|
634
|
+
expenses,
|
|
635
|
+
futurePayments,
|
|
636
|
+
futurePaymentsHeading,
|
|
637
|
+
propertyTitle = "Property Assets and Liabilities",
|
|
638
|
+
properties = [],
|
|
639
|
+
currentLiabilitiesTitle = "Current Liabilities",
|
|
640
|
+
currentLiabilities = [],
|
|
641
|
+
}: FinancialViewSectionProps) {
|
|
642
|
+
return (
|
|
643
|
+
<div className="border border-border p-4 flex flex-col gap-4">
|
|
644
|
+
<FinancialSectionLabel>{title}</FinancialSectionLabel>
|
|
645
|
+
<IncomeExpenseSection
|
|
646
|
+
income={income}
|
|
647
|
+
expenses={expenses}
|
|
648
|
+
futurePayments={futurePayments}
|
|
649
|
+
futurePaymentsHeading={futurePaymentsHeading}
|
|
650
|
+
/>
|
|
651
|
+
{properties.length > 0 && (
|
|
652
|
+
<>
|
|
653
|
+
<Separator />
|
|
654
|
+
<PropertyHoldingsSection
|
|
655
|
+
title={propertyTitle}
|
|
656
|
+
items={properties}
|
|
657
|
+
borderless
|
|
658
|
+
/>
|
|
659
|
+
</>
|
|
660
|
+
)}
|
|
661
|
+
{currentLiabilities.length > 0 && (
|
|
662
|
+
<>
|
|
663
|
+
<Separator />
|
|
664
|
+
<DebtSection
|
|
665
|
+
title={currentLiabilitiesTitle}
|
|
666
|
+
items={currentLiabilities}
|
|
667
|
+
/>
|
|
668
|
+
</>
|
|
669
|
+
)}
|
|
670
|
+
</div>
|
|
671
|
+
);
|
|
672
|
+
}
|