diff --git a/frontend/src/components/dashboard/ContributionGrowthChart.tsx b/frontend/src/components/dashboard/ContributionGrowthChart.tsx
index 37422f7..7927a5f 100644
--- a/frontend/src/components/dashboard/ContributionGrowthChart.tsx
+++ b/frontend/src/components/dashboard/ContributionGrowthChart.tsx
@@ -17,16 +17,20 @@ interface ContributionGrowthChartProps {
isDarkMode: boolean
projectionData: { age: number; Total: number }[]
annualContribution: number
+ showRealValues: boolean
+ inflationRate: number
}
export function ContributionGrowthChart({
isDarkMode,
projectionData,
annualContribution,
+ showRealValues,
+ inflationRate,
}: ContributionGrowthChartProps) {
const data = useMemo(
- () => buildContributionGrowth({ projectionData, annualContribution }),
- [projectionData, annualContribution]
+ () => buildContributionGrowth({ projectionData, annualContribution, showRealValues, inflationRate }),
+ [projectionData, annualContribution, showRealValues, inflationRate]
)
if (data.length === 0) return null
diff --git a/frontend/src/components/dashboard/GrowthChart.tsx b/frontend/src/components/dashboard/GrowthChart.tsx
index 6be3af7..46c7e53 100644
--- a/frontend/src/components/dashboard/GrowthChart.tsx
+++ b/frontend/src/components/dashboard/GrowthChart.tsx
@@ -1,3 +1,4 @@
+import { useState } from 'react'
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'
import type { ProjectionDataPoint } from '@/types/household'
import { formatCompactMoney, formatMoney } from '@/lib/formatting'
@@ -6,18 +7,73 @@ import { TrendingUp } from 'lucide-react'
interface GrowthChartProps {
isDarkMode: boolean
currentProjectionData: ProjectionDataPoint[]
+ conservativeProjectionData: ProjectionDataPoint[]
+ optimisticProjectionData: ProjectionDataPoint[]
yearsToRetirement: number
+ expectedReturn: number
}
-export function GrowthChart({ isDarkMode, currentProjectionData, yearsToRetirement }: GrowthChartProps) {
+export function GrowthChart({
+ isDarkMode,
+ currentProjectionData,
+ conservativeProjectionData,
+ optimisticProjectionData,
+ yearsToRetirement,
+ expectedReturn,
+}: GrowthChartProps) {
+ const [activeScenario, setActiveScenario] = useState<'conservative' | 'realistic' | 'optimistic'>('realistic')
+
if (yearsToRetirement <= 0 || currentProjectionData.length === 0) return null
+ const chartData = activeScenario === 'conservative'
+ ? conservativeProjectionData
+ : activeScenario === 'optimistic'
+ ? optimisticProjectionData
+ : currentProjectionData
+
return (
-
-
- Growth Projection
-
+
+
+
+ Growth Projection
+
+
+ {/* Scenario Toggle */}
+
+
+
+
+
+
+
@@ -34,7 +90,7 @@ export function GrowthChart({ isDarkMode, currentProjectionData, yearsToRetireme
-
+
('growth')
const projectionData = projection.currentProjectionData
const startAge = projectionData.length > 0 ? projectionData[0].age : 0
@@ -30,36 +31,91 @@ export function ProjectionsTab() {
return (
-
}>
-
-
+ {/* 1. Accumulation Phase (Saving) Section */}
+
+
+
+
1. Saving Phase (Accumulation)
+
Projecting your growth path up to retirement age
+
+
+
+
+
+
+
+
-
}>
-
0 ? projectionData[0].Total : 0}
- annualContribution={projection.totalAnnualContributions}
- yearsToRetirement={projection.yearsToRetirement}
- expectedReturn={assumptions.expectedReturn}
- inflationRate={assumptions.inflationRate}
- startAge={startAge}
- showRealValues={assumptions.showRealValues}
- />
-
+ }>
+ {accumulationView === 'growth' && (
+
+ )}
+ {accumulationView === 'contributions' && (
+
+ )}
+ {accumulationView === 'volatility' && (
+ 0 ? projectionData[0].Total : 0}
+ annualContribution={projection.totalAnnualContributions}
+ yearsToRetirement={projection.yearsToRetirement}
+ expectedReturn={assumptions.expectedReturn}
+ inflationRate={assumptions.inflationRate}
+ startAge={startAge}
+ showRealValues={assumptions.showRealValues}
+ />
+ )}
+
+
-
}>
-
-
+ {/* 2. Decumulation Phase (Spending) Section */}
+
+
+
2. Spending Phase (Decumulation)
+
Projecting how long your savings will last in retirement
+
-
}>
+
}>
-
+
+
+ {/* Educational Footer Info */}
diff --git a/frontend/src/contexts/ProjectionContext.tsx b/frontend/src/contexts/ProjectionContext.tsx
index c2c8d39..2639eb4 100644
--- a/frontend/src/contexts/ProjectionContext.tsx
+++ b/frontend/src/contexts/ProjectionContext.tsx
@@ -9,6 +9,8 @@ interface ProjectionContextValueTyped {
wasmLoaded: boolean
wasmError: string | null
projectionData: ProjectionDataPoint[]
+ conservativeProjectionData: ProjectionDataPoint[]
+ optimisticProjectionData: ProjectionDataPoint[]
realProjectionData: ProjectionDataPoint[]
currentProjectionData: ProjectionDataPoint[]
householdRetirementAge: number
@@ -109,6 +111,14 @@ export function ProjectionProvider({ children }: { children: ReactNode }) {
() => buildCombinedProjection(people, calculateProjection, expectedReturn, inflationRate, showRealValues, householdRetirementAge),
[people, calculateProjection, expectedReturn, inflationRate, showRealValues, householdRetirementAge]
)
+ const conservativeProjectionData = useMemo(
+ () => buildCombinedProjection(people, calculateProjection, Math.max(0, expectedReturn - 2), inflationRate, showRealValues, householdRetirementAge),
+ [people, calculateProjection, expectedReturn, inflationRate, showRealValues, householdRetirementAge]
+ )
+ const optimisticProjectionData = useMemo(
+ () => buildCombinedProjection(people, calculateProjection, expectedReturn + 2, inflationRate, showRealValues, householdRetirementAge),
+ [people, calculateProjection, expectedReturn, inflationRate, showRealValues, householdRetirementAge]
+ )
const realProjectionData = useMemo(
() => buildCombinedProjection(people, calculateProjection, expectedReturn, inflationRate, true, householdRetirementAge),
[people, calculateProjection, expectedReturn, inflationRate, householdRetirementAge]
@@ -117,7 +127,8 @@ export function ProjectionProvider({ children }: { children: ReactNode }) {
return (