Skip to content
9 changes: 7 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import AccumulationStrategy from './components/features/AccumulationStrategy';
import TaxReference from './components/features/TaxReference';
import FireAnalysis from './components/features/FireAnalysis';
import { calculateStrategy, calculateLongevity } from './services/calculationEngine';
import { TrendingUp, Calculator, AlertTriangle, BookOpen, Sun, Moon, PiggyBank, Settings, Flame } from 'lucide-react';
import { TrendingUp, Calculator, AlertTriangle, BookOpen, Sun, Moon, PiggyBank, Settings, Flame, RefreshCw } from 'lucide-react';
import Footer from './components/layout/Footer';
import WizardModal from './components/features/wizard/WizardModal';
import SettingsModal from './components/features/SettingsModal';
import { db } from './services/db';
import { projectAssets } from './services/projection';
import WhatIfAnalysis from './components/features/WhatIfAnalysis';

const INITIAL_PROFILE: UserProfile = {
age: 65, // Retirement Start Age
Expand All @@ -35,7 +36,7 @@ const App: React.FC = () => {
const [profile, setProfile] = useState<UserProfile>(INITIAL_PROFILE);
const [strategyResult, setStrategyResult] = useState<StrategyResult | null>(null);
const [longevityResult, setLongevityResult] = useState<LongevityResult | null>(null);
const [activeTab, setActiveTab] = useState<'withdrawal' | 'accumulation' | 'longevity' | 'reference' | 'fire'>('accumulation');
const [activeTab, setActiveTab] = useState<'withdrawal' | 'accumulation' | 'longevity' | 'reference' | 'fire' | 'scenarios'>('accumulation');
const [isDarkMode, setIsDarkMode] = useState(false);
const [isWizardOpen, setIsWizardOpen] = useState(false);
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
Expand Down Expand Up @@ -254,6 +255,7 @@ const App: React.FC = () => {
{ id: 'fire', icon: Flame, label: 'FIRE Analysis' },
{ id: 'withdrawal', icon: Calculator, label: 'Withdrawal' },
{ id: 'longevity', icon: TrendingUp, label: 'Longevity' },
{ id: 'scenarios', icon: RefreshCw, label: 'Scenarios' },
{ id: 'reference', icon: BookOpen, label: 'Reference' }
].map(tab => (
<button
Expand Down Expand Up @@ -297,6 +299,9 @@ const App: React.FC = () => {
<div className={activeTab === 'fire' ? 'block' : 'hidden'}>
<FireAnalysis profile={profile} isDarkMode={isDarkMode} />
</div>
<div className={activeTab === 'scenarios' ? 'block' : 'hidden'}>
<WhatIfAnalysis profile={profile} isDarkMode={isDarkMode} />
</div>
<div className={activeTab === 'reference' ? 'block' : 'hidden'}>
<TaxReference />
</div>
Expand Down
19 changes: 18 additions & 1 deletion src/components/features/StrategyResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ const StrategyResults: React.FC<StrategyResultsProps> = ({ result, profile, isDa
</div>

{/* High Level Summary Cards */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div className={`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 ${result.totalWithdrawal - (result.nominalSpendingNeeded + result.estimatedFederalTax) > 100 ? 'lg:grid-cols-5' : 'lg:grid-cols-4'} gap-4`}>
<div className="bg-white dark:bg-slate-900 p-4 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm transition-colors">
<h3 className="text-slate-500 dark:text-slate-400 text-xs font-bold uppercase">Spending (Net)</h3>
<p className="text-xl font-bold text-slate-900 dark:text-white">{formatCurrency(result.nominalSpendingNeeded)}</p>
Expand All @@ -168,6 +168,23 @@ const StrategyResults: React.FC<StrategyResultsProps> = ({ result, profile, isDa
<p className="text-[10px] text-slate-500 mt-1">Portfolio + Benefits Needed</p>
</div>

{/* Calculated Surplus (e.g. from 72t or RMDs) */}
{result.totalWithdrawal - (result.nominalSpendingNeeded + result.estimatedFederalTax) > 100 && (
<div className="bg-white dark:bg-slate-900 p-4 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm transition-colors border-l-4 border-l-emerald-500 group relative">
<div className="flex items-center gap-1.5 mb-0.5">
<h3 className="text-slate-500 dark:text-slate-400 text-xs font-bold uppercase">Reinvested Surplus</h3>
<div className="group-hover:block hidden absolute bottom-full left-0 mb-2 w-48 p-2 bg-slate-800 text-white text-[10px] rounded shadow-xl z-10 border border-slate-700">
Mandatory rules (like 72t or RMDs) require withdrawing more than you need. This excess is automatically reinvested in your brokerage account.
</div>
<Info className="w-3 h-3 text-slate-300 cursor-help" />
</div>
<p className="text-xl font-bold text-emerald-600 dark:text-emerald-400">
{formatCurrency(result.totalWithdrawal - (result.nominalSpendingNeeded + result.estimatedFederalTax))}
</p>
<p className="text-[10px] text-slate-500 mt-1">Excess Mandatory Cash</p>
</div>
)}

<div className={`p-4 rounded-xl border shadow-sm transition-colors ${feasibilityStyles[feasibility]}`}>
<h3 className="text-xs font-bold uppercase">Feasibility</h3>
<div className="flex items-center gap-2 mt-1">
Expand Down
Loading