diff --git a/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx b/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx index 8bfc654902..be38ba8991 100644 --- a/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx @@ -27,6 +27,7 @@ type CrossoverGraphProps = { x: string; investmentIncome: number; expenses: number; + nestEgg: number; isProjection?: boolean; }>; start: string; @@ -60,6 +61,7 @@ export function CrossoverGraph({ x: string; investmentIncome: number | string; expenses: number | string; + nestEgg: number | string; isProjection?: boolean; }; }; @@ -118,6 +120,21 @@ export function CrossoverGraph({
{format(payload[0].payload.expenses, 'financial')}
+ +
+ {payload[0].payload.isProjection ? ( + Target Nest Egg: + ) : ( + Nest Egg: + )} +
+
{format(payload[0].payload.nestEgg, 'financial')}
+
diff --git a/packages/desktop-client/src/components/reports/reports/Crossover.tsx b/packages/desktop-client/src/components/reports/reports/Crossover.tsx index 57f87df3ba..c716eea713 100644 --- a/packages/desktop-client/src/components/reports/reports/Crossover.tsx +++ b/packages/desktop-client/src/components/reports/reports/Crossover.tsx @@ -57,6 +57,7 @@ type CrossoverData = { x: string; investmentIncome: number; expenses: number; + nestEgg: number; isProjection?: boolean; }>; start: string; @@ -69,6 +70,7 @@ type CrossoverData = { historicalReturn: number | null; yearsToRetire: number | null; targetMonthlyIncome: number | null; + targetNestEgg: number | null; }; export function Crossover() { @@ -299,6 +301,9 @@ function CrossoverInner({ widget }: CrossoverInnerProps) { // Get target monthly income from spreadsheet data const targetMonthlyIncome = data?.targetMonthlyIncome ?? null; + // Get target nest egg from spreadsheet data + const targetNestEgg = data?.targetNestEgg ?? null; + const navigate = useNavigate(); const { isNarrowWidth } = useResponsive(); @@ -791,6 +796,20 @@ function CrossoverInner({ widget }: CrossoverInnerProps) { + + + Target Nest Egg:{' '} + + {targetNestEgg != null && !isNaN(targetNestEgg) + ? format(targetNestEgg, 'financial') + : t('N/A')} + + + diff --git a/packages/desktop-client/src/components/reports/reports/CrossoverCard.tsx b/packages/desktop-client/src/components/reports/reports/CrossoverCard.tsx index 69b4368216..30fc25900f 100644 --- a/packages/desktop-client/src/components/reports/reports/CrossoverCard.tsx +++ b/packages/desktop-client/src/components/reports/reports/CrossoverCard.tsx @@ -32,6 +32,7 @@ type CrossoverData = { x: string; investmentIncome: number; expenses: number; + nestEgg: number; isProjection?: boolean; }>; start: string; @@ -44,6 +45,7 @@ type CrossoverData = { historicalReturn: number | null; yearsToRetire: number | null; targetMonthlyIncome: number | null; + targetNestEgg: number | null; }; type CrossoverCardProps = { diff --git a/packages/desktop-client/src/components/reports/spreadsheets/crossover-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/crossover-spreadsheet.ts index e385a803d8..c9c5589a12 100644 --- a/packages/desktop-client/src/components/reports/spreadsheets/crossover-spreadsheet.ts +++ b/packages/desktop-client/src/components/reports/spreadsheets/crossover-spreadsheet.ts @@ -80,6 +80,7 @@ export function createCrossoverSpreadsheet({ historicalReturn: null, yearsToRetire: null, targetMonthlyIncome: null, + targetNestEgg: null, }); return; } @@ -231,6 +232,7 @@ function recalculate( x: string; investmentIncome: number; expenses: number; + nestEgg: number; isProjection?: boolean; }> = []; @@ -245,6 +247,7 @@ function recalculate( x: d.format(d.parseISO(month + '-01'), 'MMM yyyy'), investmentIncome: Math.round(monthlyIncome), expenses: spend, + nestEgg: balance, }); lastBalance = balance; lastExpense = spend; @@ -355,6 +358,7 @@ function recalculate( x: d.format(monthCursor, 'MMM yyyy'), investmentIncome: Math.round(projectedIncome), expenses: Math.round(projectedExpenses), + nestEgg: Math.round(projectedBalance), isProjection: true, }); @@ -370,6 +374,7 @@ function recalculate( // Calculate years to retire based on crossover point let yearsToRetire: number | null = null; let targetMonthlyIncome: number | null = null; + let targetNestEgg: number | null = null; if (crossoverIndex != null && crossoverIndex < data.length) { const crossoverData = data[crossoverIndex]; @@ -379,6 +384,8 @@ function recalculate( const monthsDiff = d.differenceInMonths(crossoverDate, currentDate); yearsToRetire = monthsDiff > 0 ? monthsDiff / 12 : 0; targetMonthlyIncome = crossoverData.expenses; + // Calculate target nest egg: target monthly income / monthly safe withdrawal rate + targetNestEgg = Math.round(targetMonthlyIncome / monthlySWR); } } @@ -405,5 +412,7 @@ function recalculate( yearsToRetire, // Target monthly income at crossover point targetMonthlyIncome, + // Target nest egg at crossover point + targetNestEgg, }; } diff --git a/upcoming-release-notes/6384.md b/upcoming-release-notes/6384.md new file mode 100644 index 0000000000..b086d9d0e3 --- /dev/null +++ b/upcoming-release-notes/6384.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [sjones512] +--- + +Add a nest egg field to show projected net worth on the crossover point report