diff --git a/src/components/features/AccumulationStrategy.tsx b/src/components/features/AccumulationStrategy.tsx index 4a7649f..c94c727 100644 --- a/src/components/features/AccumulationStrategy.tsx +++ b/src/components/features/AccumulationStrategy.tsx @@ -1,7 +1,8 @@ import React, { useState, useMemo } from 'react'; import { UserProfile } from '../../types'; -import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell, Legend } from 'recharts'; +import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip as RechartsTooltip, ResponsiveContainer, PieChart, Pie, Cell, Legend } from 'recharts'; import { Calendar, Wallet, TrendingUp, Table as TableIcon, Info, Rocket, ArrowRight, PieChart as PieIcon } from 'lucide-react'; +import Tooltip from '../common/Tooltip'; interface AccumulationStrategyProps { profile: UserProfile; @@ -113,6 +114,7 @@ const AccumulationStrategy: React.FC = ({ profile, se
+
@@ -184,7 +186,7 @@ const AccumulationStrategy: React.FC = ({ profile, se tick={{ fontSize: 10 }} width={50} /> - `$${value.toLocaleString()}`} labelFormatter={(label) => `Age ${label}`} @@ -231,7 +233,7 @@ const AccumulationStrategy: React.FC = ({ profile, se ))} - `$${value.toLocaleString()}`} contentStyle={{ backgroundColor: tooltipBg, color: tooltipText, borderRadius: '8px' }} /> diff --git a/src/components/features/FireAnalysis.tsx b/src/components/features/FireAnalysis.tsx index 32bddcd..0f6fcc7 100644 --- a/src/components/features/FireAnalysis.tsx +++ b/src/components/features/FireAnalysis.tsx @@ -1,9 +1,10 @@ import React, { useState, useMemo } from 'react'; import { UserProfile } from '../../types'; import { calculateFireMilestones } from '../../services/fireCalculations'; -import { FireInputs } from '../types/fire'; +import { FireInputs } from '../../types/fire'; import { Flame, TrendingUp, DollarSign, Calendar, RefreshCw } from 'lucide-react'; import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip as RechartsTooltip } from 'recharts'; +import Tooltip from '../common/Tooltip'; interface FireAnalysisProps { profile: UserProfile; @@ -334,6 +335,11 @@ const FireAnalysis: React.FC = ({ profile, isDarkMode }) => {

{milestone.type} FIRE + {milestone.type === 'Lean' && } + {milestone.type === 'Standard' && } + {milestone.type === 'Fat' && } + {milestone.type === 'Coast' && } + {milestone.type === 'Barista' && } {milestone.percentageProgress >= 100 && ( Achieved diff --git a/src/components/features/InputSection.tsx b/src/components/features/InputSection.tsx index 3db5034..537f505 100644 --- a/src/components/features/InputSection.tsx +++ b/src/components/features/InputSection.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { UserProfile, FilingStatus } from '../../types'; import { HelpCircle, DollarSign, Briefcase, Activity, TrendingUp, PiggyBank, RotateCcw, PlusCircle, AlertTriangle, Calculator } from 'lucide-react'; import PortfolioSelectorModal from '../modals/PortfolioSelectorModal'; +import Tooltip from '../common/Tooltip'; interface InputSectionProps { profile: UserProfile; @@ -90,6 +91,7 @@ const InputSection: React.FC = ({ profile, setProfile, onRest // const isFutureScenario = (Number(profile.age) || 0) !== profile.baseAge; const [activeModal, setActiveModal] = useState<'accumulation' | 'retirement' | null>(null); + const [showRestartConfirm, setShowRestartConfirm] = useState(false); const accumulationYears = Math.max(5, (profile.age || 65) - (profile.baseAge || 30)); // Min 5 years to show meaningful data const retirementLongevityYears = Math.max(30, 95 - (profile.age || 65)); // Plan for at least 30 years or until age 95 @@ -106,12 +108,20 @@ const InputSection: React.FC = ({ profile, setProfile, onRest

- + {!showRestartConfirm ? ( + + ) : ( +
+ Are you sure? + + +
+ )} {profile.age < profile.baseAge && (
@@ -167,7 +177,10 @@ const InputSection: React.FC = ({ profile, setProfile, onRest
- +
+ +
+
@@ -203,12 +219,15 @@ const InputSection: React.FC = ({ profile, setProfile, onRest {[ { label: 'Traditional IRA / 401k', key: 'traditionalIRA' as const }, { label: 'Roth IRA / 401k', key: 'rothIRA' as const }, - { label: 'Roth Carry/Basis', key: 'rothBasis' as const }, + { label: 'Roth Carry/Basis', key: 'rothBasis' as const, tooltip: 'Your total accumulated contributions to Roth accounts. This basis can be withdrawn tax-free and penalty-free at any time, making it a key liquidity source before age 59½.' }, { label: 'Taxable Brokerage', key: 'brokerage' as const }, - { label: 'HSA', key: 'hsa' as const }, + { label: 'HSA', key: 'hsa' as const, tooltip: 'Health Savings Account balance. Funds can be withdrawn tax-free for qualified medical expenses.' }, ].map((item) => (
- +
$ = ({ longevity, profil ? 'bg-green-50 dark:bg-green-950/30 border-green-200 dark:border-green-900' : 'bg-orange-50 dark:bg-orange-950/30 border-orange-200 dark:border-orange-900' }`}> -

+

Initial Withdrawal Rate +

{(initialWithdrawalRate * 100).toFixed(1)}% @@ -96,7 +98,7 @@ const LongevityAnalysis: React.FC = ({ longevity, profil width={80} stroke={axisColor} /> - { if (active && payload && payload.length) { const data = payload[0].payload; @@ -219,7 +221,7 @@ const LongevityAnalysis: React.FC = ({ longevity, profil width={80} stroke={axisColor} /> - { if (active && payload && payload.length) { @@ -284,7 +286,7 @@ const LongevityAnalysis: React.FC = ({ longevity, profil {/* RMD indicator (age 73+) */} {data.rmdAmount > 0 && (
- (RMD Required): + (RMD Required): ${Math.round(data.rmdAmount).toLocaleString()}
)} diff --git a/src/components/features/StrategyResults.tsx b/src/components/features/StrategyResults.tsx index d3969a4..712f2dd 100644 --- a/src/components/features/StrategyResults.tsx +++ b/src/components/features/StrategyResults.tsx @@ -1,8 +1,9 @@ import React, { useState, useEffect } from 'react'; import { StrategyResult, UserProfile } from '../../types'; -import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Legend, CartesianGrid } from 'recharts'; +import { PieChart, Pie, Cell, Tooltip as RechartsTooltip, ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Legend, CartesianGrid } from 'recharts'; import { AlertCircle, CheckCircle, TrendingUp, Sparkles, MessageSquare, RefreshCw, ShieldAlert, Lock, Wallet, Info, AlertTriangle, ArrowRightLeft } from 'lucide-react'; import { getGeminiAdvice } from '../../services/geminiService'; +import Tooltip from '../common/Tooltip'; interface StrategyResultsProps { result: StrategyResult; @@ -214,7 +215,7 @@ const StrategyResults: React.FC = ({ result, profile, isDa

{formatCurrency(result.taxableSocialSecurity)}

- Provisional Income + Provisional Income

{formatCurrency(result.provisionalIncome)}

@@ -248,7 +249,7 @@ const StrategyResults: React.FC = ({ result, profile, isDa

- Effective Marginal Rate + Effective Marginal Rate

0.30 ? 'text-red-600 dark:text-red-400' : 'text-slate-900 dark:text-white' @@ -310,7 +311,7 @@ const StrategyResults: React.FC = ({ result, profile, isDa

{c.headroom > 0 && Headroom: {formatCurrency(c.headroom)}} {c.annualCost && c.annualCost > 0 && ( -

IRMAA: {formatCurrency(c.annualCost)}/yr if crossed

+

IRMAA: {formatCurrency(c.annualCost)}/yr if crossed

)}
@@ -340,7 +341,7 @@ const StrategyResults: React.FC = ({ result, profile, isDa stroke={axisColor} tickFormatter={(value) => value.length > 15 ? value.substring(0, 12) + '...' : value} /> - formatCurrency(value)} contentStyle={{ backgroundColor: tooltipBg, borderColor: gridColor, color: tooltipText, fontSize: '12px' }} /> diff --git a/src/components/features/wizard/Steps/Step8Results.tsx b/src/components/features/wizard/Steps/Step8Results.tsx index f819fad..e280f9f 100644 --- a/src/components/features/wizard/Steps/Step8Results.tsx +++ b/src/components/features/wizard/Steps/Step8Results.tsx @@ -35,8 +35,7 @@ const Step8Results: React.FC = ({ data, onComplete, onRestart }) => // at the start of retirement to run the withdrawal strategy correctly. const projectedAssets = projectAssets( baseProfile.assets, - baseProfile.contributions.traditionalIRA + baseProfile.contributions.rothIRA + baseProfile.contributions.brokerage, // Total annual contrib - data.contributionAllocation || { taxDeferred: 50, taxable: 30, taxExempt: 20 }, // Allocation % + baseProfile.contributions, baseProfile.baseAge, // Current Age baseProfile.age, // Retirement Age baseProfile.assumptions