'use client' import { useEffect, useState } from 'react' import { Language } from '@/lib/types' import { t } from '@/lib/i18n' import GradientText from '../ui/GradientText' import FadeInView from '../ui/FadeInView' import GlassCard from '../ui/GlassCard' import { TrendingUp, TrendingDown, Minus } from 'lucide-react' interface AssumptionsSlideProps { lang: Language investorId?: string | null preferredScenarioId?: string | null isWandeldarlehen?: boolean } interface SheetRow { row_label?: string values?: Record values_total?: Record } interface ScenarioKPIs { arr: number customers: number headcount: number cash: number breakEvenYear: string } function fmtArr(v: number, de: boolean): string { if (v >= 1_000_000) return de ? `~${(v / 1_000_000).toFixed(1).replace('.', ',')} Mio. EUR` : `~EUR ${(v / 1_000_000).toFixed(1)}M` if (v >= 1000) return de ? `~${Math.round(v / 1000)}k EUR` : `~EUR ${Math.round(v / 1000)}k` return de ? `~${v} EUR` : `~EUR ${v}` } function fmtCash(v: number, de: boolean): string { if (Math.abs(v) >= 1_000_000) return de ? `~${(v / 1_000_000).toFixed(1).replace('.', ',')} Mio. EUR` : `~EUR ${(v / 1_000_000).toFixed(1)}M` return de ? `~${Math.round(v / 1000)}k EUR` : `~EUR ${Math.round(v / 1000)}k` } async function loadScenarioKPIs(scenarioId: string | null): Promise { const param = scenarioId ? `?scenarioId=${scenarioId}` : '' try { const [guvRes, liqRes, persRes, kundenRes] = await Promise.all([ fetch(`/api/finanzplan/guv${param}`, { cache: 'no-store' }), fetch(`/api/finanzplan/liquiditaet${param}`, { cache: 'no-store' }), fetch(`/api/finanzplan/personalkosten${param}`, { cache: 'no-store' }), fetch(`/api/finanzplan/kunden${param}`, { cache: 'no-store' }), ]) const [guv, liq, pers, kunden] = await Promise.all([guvRes.json(), liqRes.json(), persRes.json(), kundenRes.json()]) const findGuv = (label: string) => (guv.rows || []).find((r: SheetRow) => (r.row_label || '').includes(label)) const findLiq = (label: string) => (liq.rows || []).find((r: SheetRow) => (r.row_label || '').includes(label)) const kundenGesamt = (kunden.rows || []).find((r: SheetRow) => r.row_label === 'Bestandskunden gesamt') const ebit = findGuv('EBIT')?.values || {} let breakEvenYear = '—' for (const y of [2026, 2027, 2028, 2029, 2030]) { if ((ebit[`y${y}`] || 0) > 0) { breakEvenYear = String(y); break } } return { arr: findGuv('Umsatzerlöse')?.values?.y2030 || 0, customers: kundenGesamt?.values?.m60 || 0, headcount: (pers.rows || []).filter((r: SheetRow) => ((r.values_total || r.values)?.m60 || 0) > 0).length, cash: findLiq('LIQUIDIT')?.values?.m60 || findLiq('LIQUIDITAET')?.values?.m60 || 0, breakEvenYear, } } catch { return { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' } } } export default function AssumptionsSlide({ lang, isWandeldarlehen }: AssumptionsSlideProps) { const i = t(lang) const de = lang === 'de' const [scenarioData, setScenarioData] = useState<{ bear: ScenarioKPIs; base: ScenarioKPIs; bull: ScenarioKPIs } | null>(null) useEffect(() => { async function load() { const baseId = isWandeldarlehen ? 'c0000000-0000-0000-0000-000000000200' : null const bearId = isWandeldarlehen ? 'd0000000-0000-0000-0000-000000000201' : 'd0000000-0000-0000-0000-000000000301' const bullId = isWandeldarlehen ? 'd0000000-0000-0000-0000-000000000202' : 'd0000000-0000-0000-0000-000000000302' const [bear, base, bull] = await Promise.all([loadScenarioKPIs(bearId), loadScenarioKPIs(baseId), loadScenarioKPIs(bullId)]) setScenarioData({ bear, base, bull }) } load() }, [isWandeldarlehen]) const bear = scenarioData?.bear || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' } const base = scenarioData?.base || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' } const bull = scenarioData?.bull || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' } const baseAssumptions = isWandeldarlehen ? (de ? [ 'Kundenwachstum: 8% monatlich, ab m32: 15%', 'Mix: 60% Starter, 25% Professional, 15% Enterprise', `Personalaufbau: 3→${base.headcount} Personen (lean)`, 'Serverkosten: 50€/Kunde + 300€ Basis', ] : [ 'Customer growth: 8% monthly, from m32: 15%', 'Mix: 60% Starter, 25% Professional, 15% Enterprise', `Hiring: 3→${base.headcount} people (lean)`, 'Server costs: €50/customer + €300 base', ]) : (de ? [ 'Kundenwachstum wie geplant (5→1.200+)', 'Mix: 60% Starter, 25% Professional, 15% Enterprise', 'Personalaufbau 5→10→17→25→35', 'Serverkosten 100€ pro Kunde + 2.000€ Basis', ] : [ 'Customer growth as planned (5→1,200+)', 'Mix: 60% Starter, 25% Professional, 15% Enterprise', 'Hiring 5→10→17→25→35', 'Server costs €100 per customer + €2,000 base', ]) const cases = [ { name: 'Bear Case', icon: TrendingDown, color: 'text-red-400', bg: 'bg-red-500/10 border-red-500/20', desc: de ? 'Langsames Wachstum, höhere Churn' : 'Slow growth, higher churn', assumptions: de ? ['Kundenwachstum 40% langsamer', 'Churn Rate 50% höher', 'Personalaufbau wie Base Case'] : ['Customer growth 40% slower', 'Churn rate 50% higher', 'Hiring same as base case'], kpis: bear, }, { name: 'Base Case', icon: Minus, color: 'text-indigo-400', bg: 'bg-indigo-500/10 border-indigo-500/20', desc: de ? 'Aktueller Finanzplan' : 'Current financial plan', assumptions: baseAssumptions, kpis: base, }, { name: 'Bull Case', icon: TrendingUp, color: 'text-emerald-400', bg: 'bg-emerald-500/10 border-emerald-500/20', desc: de ? 'Beschleunigtes Wachstum' : 'Accelerated growth', assumptions: de ? ['Kundenwachstum 30-50% schneller', 'Churn Rate 30% niedriger', 'Personalaufbau wie Base Case'] : ['Customer growth 30-50% faster', 'Churn rate 30% lower', 'Hiring same as base case'], kpis: bull, }, ] return (

{i.annex.assumptions.title}

{i.annex.assumptions.subtitle}

{cases.map((c, idx) => { const Icon = c.icon return (

{c.name}

{c.desc}

{c.assumptions.map((a, i) => (

{a}

))}
{[ { label: de ? 'Kunden 2030' : 'Customers 2030', value: `~${c.kpis.customers.toLocaleString('de-DE')}` }, { label: 'ARR 2030', value: fmtArr(c.kpis.arr, de) }, { label: de ? 'Mitarbeiter' : 'Employees', value: String(c.kpis.headcount) }, { label: 'Break-Even', value: c.kpis.breakEvenYear }, { label: 'Cash 2030', value: fmtCash(c.kpis.cash, de) }, ].map((kpi, i) => (
{kpi.label} {kpi.value}
))}
) })}

{de ? 'Szenario-Vergleich 2030' : 'Scenario Comparison 2030'}

{[ { label: de ? 'Kunden' : 'Customers', bear: `~${bear.customers.toLocaleString('de-DE')}`, base: `~${base.customers.toLocaleString('de-DE')}`, bull: `~${bull.customers.toLocaleString('de-DE')}` }, { label: 'ARR', bear: fmtArr(bear.arr, de), base: fmtArr(base.arr, de), bull: fmtArr(bull.arr, de) }, { label: de ? 'Mitarbeiter' : 'Employees', bear: String(bear.headcount), base: String(base.headcount), bull: String(bull.headcount) }, { label: 'Break-Even', bear: bear.breakEvenYear, base: base.breakEvenYear, bull: bull.breakEvenYear }, { label: 'Cash', bear: fmtCash(bear.cash, de), base: fmtCash(base.cash, de), bull: fmtCash(bull.cash, de) }, ].map((row, idx) => ( ))}
Bear Base Bull
{row.label} {row.bear} {row.base} {row.bull}
) }