'use client' import { useState } from 'react' import { Language } from '@/lib/types' import { t } from '@/lib/i18n' import ProjectionFooter from '../ui/ProjectionFooter' import { useFinancialModel } from '@/lib/hooks/useFinancialModel' import { useFpKPIs } from '@/lib/hooks/useFpKPIs' import GradientText from '../ui/GradientText' import FadeInView from '../ui/FadeInView' import FinancialChart from '../ui/FinancialChart' import FinancialSliders from '../ui/FinancialSliders' import KPICard from '../ui/KPICard' import RunwayGauge from '../ui/RunwayGauge' import WaterfallChart from '../ui/WaterfallChart' import UnitEconomicsCards from '../ui/UnitEconomicsCards' import ScenarioSwitcher from '../ui/ScenarioSwitcher' import AnnualPLTable from '../ui/AnnualPLTable' import AnnualCashflowChart from '../ui/AnnualCashflowChart' type FinTab = 'overview' | 'guv' | 'cashflow' interface FinancialsSlideProps { lang: Language investorId: string | null preferredScenarioId?: string | null isWandeldarlehen?: boolean } export default function FinancialsSlide({ lang, investorId, preferredScenarioId, isWandeldarlehen }: FinancialsSlideProps) { const i = t(lang) const fm = useFinancialModel(investorId, preferredScenarioId) const [activeTab, setActiveTab] = useState('overview') const de = lang === 'de' const activeResults = fm.activeResults const summary = activeResults?.summary const lastResult = activeResults?.results[activeResults.results.length - 1] // KPI cards from fp_* tables (source of truth) const { last: fpLast, kpis: fpKPIs } = useFpKPIs(isWandeldarlehen) const kpiArr = fpLast?.arr || summary?.final_arr || 0 const kpiCustomers = fpLast?.customers || summary?.final_customers || 0 const kpiEbit = fpKPIs?.y2029?.ebit // First profitable year const kpiBreakEven = (() => { for (const y of [2026, 2027, 2028, 2029, 2030]) { if ((fpKPIs[`y${y}`]?.ebit || 0) > 0) return y } return 0 })() // Build scenario color map const scenarioColors: Record = {} fm.scenarios.forEach(s => { scenarioColors[s.id] = s.color }) // Build compare results (exclude active scenario) const compareResults = new Map( Array.from(fm.results.entries()).filter(([id]) => id !== fm.activeScenarioId) ) // Initial funding from assumptions const initialFunding = (fm.activeScenario?.assumptions.find(a => a.key === 'initial_funding')?.value as number) || 200000 const tabs: { id: FinTab; label: string }[] = [ { id: 'overview', label: de ? 'Übersicht' : 'Overview' }, { id: 'guv', label: de ? 'GuV (Jahres)' : 'P&L (Annual)' }, { id: 'cashflow', label: de ? 'Cashflow & Finanzbedarf' : 'Cashflow & Funding' }, ] if (fm.loading) { return (
) } return (

{i.financials.title}

{i.financials.subtitle}

{/* Hero KPI Cards */}
= 1_000_000 ? Math.round(kpiArr / 1_000_000 * 10) / 10 : Math.round(kpiArr / 1000)} suffix={kpiArr >= 1_000_000 ? ' Mio.' : 'k'} decimals={kpiArr >= 1_000_000 ? 1 : 0} trend="up" color="#6366f1" delay={0.1} subLabel="EUR" />

Break-Even

{kpiBreakEven || '—'}

{kpiBreakEven && kpiBreakEven <= 2029 ? '↑' : kpiBreakEven ? '↓' : ''}
0 ? 'up' : 'down'} color="#a855f7" delay={0.25} subLabel="EUR" />
{/* Tab Navigation */}
{tabs.map((tab) => ( ))}
{/* Main content: full width */}
{/* TAB: Overview — monatlicher Chart + Waterfall + Unit Economics */} {activeTab === 'overview' && ( <>

{de ? 'Umsatz vs. Kosten (60 Monate)' : 'Revenue vs. Costs (60 months)'}

{de ? 'Umsatz' : 'Revenue'} {de ? 'Kosten' : 'Costs'} {de ? 'Kunden' : 'Customers'}

{de ? 'Cash-Flow (Quartal)' : 'Cash Flow (Quarterly)'}

{activeResults && }
{lastResult && ( a.key === 'churn_rate_monthly')?.value as number || 3} lang={lang} /> )}
)} {/* TAB: GuV — from fp_guv */} {activeTab === 'guv' && (

{de ? 'Gewinn- und Verlustrechnung (5 Jahre)' : 'Profit & Loss Statement (5 Years)'}

{de ? 'Alle Werte in EUR · Quelle: Finanzplan' : 'All values in EUR · Source: Financial Plan'}

{[2026,2027,2028,2029,2030].map(y => )} {[ { label: de ? 'Umsatzerlöse' : 'Revenue', key: 'revenue', bold: true }, { label: de ? 'Personalkosten' : 'Personnel', key: 'personal', bold: false }, { label: 'EBIT', key: 'ebit', bold: true }, { label: de ? 'Steuern' : 'Taxes', key: 'steuern', bold: false }, { label: de ? 'Jahresüberschuss' : 'Net Income', key: 'netIncome', bold: true }, ].map((row, idx) => ( {[2026,2027,2028,2029,2030].map(y => { const v = fpKPIs[`y${y}`]?.[row.key as keyof typeof fpKPIs['y2026']] || 0 const num = typeof v === 'number' ? v : 0 return ( ) })} ))}
{y}
{row.label} {num === 0 ? '—' : (num >= 1000000 || num <= -1000000) ? `${(num/1000000).toFixed(1)}M` : `${Math.round(num/1000)}k`}
)} {/* TAB: Cashflow — from fp_* */} {activeTab === 'cashflow' && (

{de ? 'Liquidität & Cashflow (5 Jahre) · Quelle: Finanzplan' : 'Liquidity & Cash Flow (5 Years) · Source: Financial Plan'}

{[2026,2027,2028,2029,2030].map((y, idx) => { const liq = fpKPIs[`y${y}`]?.liquiditaet || 0 const ebit = fpKPIs[`y${y}`]?.ebit || 0 const maxAbs = Math.max(...[2026,2027,2028,2029,2030].map(yr => Math.abs(fpKPIs[`y${yr}`]?.liquiditaet || 0)), 1) const h = Math.abs(liq) / maxAbs * 140 return (
{liq >= 1000000 ? `${(liq/1000000).toFixed(1)}M` : liq <= -1000000 ? `${(liq/1000000).toFixed(1)}M` : `${Math.round(liq/1000)}k`}
= 0 ? 'bg-emerald-500/60 rounded-t' : 'bg-red-500/60 rounded-b'} w-full`} style={{ height: `${Math.max(h, 4)}px` }} />
{y} = 0 ? 'text-emerald-400/60' : 'text-red-400/60'}`}> EBIT: {ebit >= 1000000 ? `${(ebit/1000000).toFixed(1)}M` : `${Math.round(ebit/1000)}k`}
) })}
{de ? 'Liquidität (positiv)' : 'Cash (positive)'} {de ? 'Liquidität (negativ)' : 'Cash (negative)'}
)}
) }