fix(pitch-deck): version-aware financial model + layout fix + COMPLAI spelling
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m2s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 26s
CI / test-python-voice (push) Successful in 25s
CI / test-bqas (push) Successful in 26s

Critical fix: All financial slides now use the version's preferred scenario
instead of always defaulting to Base Case (1M). This ensures the
Wandeldarlehen version shows its own lean financial plan.

- useFinancialModel: add preferredScenarioId parameter
- PitchDeck: extract default scenario from previewData.fm_scenarios
- Pass preferredScenarioId to all 5 financial slides
- FinancialsSlide layout: remove empty right column, full-width charts
- Remove ScenarioSwitcher + unused slider from FinancialsSlide
- Fix COMPLEI → COMPLAI in presenter script (only TTS pronunciation differs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-17 01:02:57 +02:00
parent 98081ae5eb
commit 9005a05bd7
8 changed files with 43 additions and 61 deletions

View File

@@ -69,6 +69,15 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
const [fabOpen, setFabOpen] = useState(false)
const isWandeldarlehen = (data?.funding?.instrument || '').toLowerCase().includes('wandeldarlehen')
// For version previews: use the version's default FM scenario instead of base table default
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fmScenarios = (previewData as any)?.fm_scenarios as Array<{ id: string; is_default?: boolean }> | undefined
const preferredScenarioId = fmScenarios?.[0]?.is_default
? fmScenarios[0].id
: fmScenarios?.length === 1
? fmScenarios[0].id
: null
// Skip cap-table slide for Wandeldarlehen versions
useEffect(() => {
if (nav.currentSlide === 'cap-table' && isWandeldarlehen) {
@@ -151,7 +160,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
/>
)
case 'executive-summary':
return <ExecutiveSummarySlide lang={lang} data={data} investorId={investor?.id || null} />
return <ExecutiveSummarySlide lang={lang} data={data} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} />
case 'cover':
return <CoverSlide lang={lang} onNext={nav.nextSlide} funding={data.funding} />
case 'problem':
@@ -169,7 +178,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'market':
return <MarketSlide lang={lang} market={data.market} />
case 'business-model':
return <BusinessModelSlide lang={lang} products={data.products} investorId={investor?.id || null} />
return <BusinessModelSlide lang={lang} products={data.products} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} />
case 'traction':
return <TractionSlide lang={lang} milestones={data.milestones} metrics={data.metrics} />
case 'competition':
@@ -177,7 +186,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'team':
return <TeamSlide lang={lang} team={data.team} />
case 'financials':
return <FinancialsSlide lang={lang} investorId={investor?.id || null} />
return <FinancialsSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} />
case 'the-ask':
return <TheAskSlide lang={lang} funding={data.funding} />
case 'cap-table':
@@ -188,7 +197,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'ai-qa':
return <AIQASlide lang={lang} />
case 'annex-assumptions':
return <AssumptionsSlide lang={lang} investorId={investor?.id || null} />
return <AssumptionsSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} />
case 'annex-architecture':
return <ArchitectureSlide lang={lang} />
case 'annex-gtm':
@@ -204,7 +213,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'annex-strategy':
return <StrategySlide lang={lang} />
case 'annex-finanzplan':
return <FinanzplanSlide lang={lang} investorId={investor?.id || null} />
return <FinanzplanSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} />
case 'annex-glossary':
return <GlossarySlide lang={lang} />
case 'legal-disclaimer':

View File

@@ -11,6 +11,7 @@ import { useFinancialModel } from '@/lib/hooks/useFinancialModel'
interface AssumptionsSlideProps {
lang: Language
investorId?: string | null
preferredScenarioId?: string | null
}
function fmtArr(v: number, de: boolean): string {
@@ -35,12 +36,12 @@ function breakEvenYear(month: number | null): string {
return String(year)
}
export default function AssumptionsSlide({ lang, investorId }: AssumptionsSlideProps) {
export default function AssumptionsSlide({ lang, investorId, preferredScenarioId }: AssumptionsSlideProps) {
const i = t(lang)
const de = lang === 'de'
// Load computed financial data for Base Case
const fm = useFinancialModel(investorId || null)
const fm = useFinancialModel(investorId || null, preferredScenarioId)
const summary = fm.activeResults?.summary
const results = fm.activeResults?.results || []
const lastResult = results.length > 0 ? results[results.length - 1] : null

View File

@@ -12,12 +12,13 @@ interface BusinessModelSlideProps {
lang: Language
products?: unknown[]
investorId?: string | null
preferredScenarioId?: string | null
}
export default function BusinessModelSlide({ lang, investorId }: BusinessModelSlideProps) {
export default function BusinessModelSlide({ lang, investorId, preferredScenarioId }: BusinessModelSlideProps) {
const i = t(lang)
const de = lang === 'de'
const fm = useFinancialModel(investorId || null)
const fm = useFinancialModel(investorId || null, preferredScenarioId)
const summary = fm.activeResults?.summary
const results = fm.activeResults?.results || []
const lastResult = results[results.length - 1]

View File

@@ -14,15 +14,16 @@ interface ExecutiveSummarySlideProps {
lang: Language
data: PitchData
investorId?: string | null
preferredScenarioId?: string | null
}
export default function ExecutiveSummarySlide({ lang, data, investorId }: ExecutiveSummarySlideProps) {
export default function ExecutiveSummarySlide({ lang, data, investorId, preferredScenarioId }: ExecutiveSummarySlideProps) {
const i = t(lang)
const es = i.executiveSummary
const de = lang === 'de'
// Financial model for Unternehmensentwicklung
const fm = useFinancialModel(investorId || null)
const fm = useFinancialModel(investorId || null, preferredScenarioId)
const annualKPIs = useMemo(
() => computeAnnualKPIs(fm.activeResults?.results || []),
[fm.activeResults],

View File

@@ -22,11 +22,12 @@ type FinTab = 'overview' | 'guv' | 'cashflow'
interface FinancialsSlideProps {
lang: Language
investorId: string | null
preferredScenarioId?: string | null
}
export default function FinancialsSlide({ lang, investorId }: FinancialsSlideProps) {
export default function FinancialsSlide({ lang, investorId, preferredScenarioId }: FinancialsSlideProps) {
const i = t(lang)
const fm = useFinancialModel(investorId)
const fm = useFinancialModel(investorId, preferredScenarioId)
const [activeTab, setActiveTab] = useState<FinTab>('overview')
const de = lang === 'de'
@@ -125,10 +126,8 @@ export default function FinancialsSlide({ lang, investorId }: FinancialsSlidePro
))}
</div>
{/* Main content: 3-column layout */}
<div className="grid md:grid-cols-12 gap-3">
{/* Left: Charts (8 columns) */}
<div className="md:col-span-8 space-y-3">
{/* Main content: full width */}
<div className="space-y-3">
{/* TAB: Overview — monatlicher Chart + Waterfall + Unit Economics */}
{activeTab === 'overview' && (
@@ -222,38 +221,6 @@ export default function FinancialsSlide({ lang, investorId }: FinancialsSlidePro
</div>
</FadeInView>
)}
</div>
{/* Right: Controls (4 columns) */}
<div className="md:col-span-4 space-y-3">
{/* Scenario Switcher */}
<FadeInView delay={0.15}>
<div className="bg-white/[0.05] backdrop-blur-xl border border-white/10 rounded-2xl p-3">
<ScenarioSwitcher
scenarios={fm.scenarios}
activeId={fm.activeScenarioId}
compareMode={fm.compareMode}
onSelect={(id) => {
fm.setActiveScenarioId(id)
}}
onToggleCompare={() => {
if (!fm.compareMode) {
fm.computeAll()
}
fm.setCompareMode(!fm.compareMode)
}}
lang={lang}
/>
</div>
</FadeInView>
{fm.computing && (
<div className="flex items-center gap-2 text-[10px] text-indigo-400">
<div className="w-3 h-3 border border-indigo-400 border-t-transparent rounded-full animate-spin" />
{de ? 'Berechne...' : 'Computing...'}
</div>
)}
</div>
</div>
<ProjectionFooter lang={lang} />
</div>

View File

@@ -14,6 +14,7 @@ import { RefreshCw, Download, ChevronLeft, ChevronRight, BarChart3, Target } fro
interface FinanzplanSlideProps {
lang: Language
investorId?: string | null
preferredScenarioId?: string | null
}
interface SheetMeta {
@@ -60,7 +61,7 @@ function formatCell(v: number | undefined): string {
return Math.round(v).toLocaleString('de-DE', { maximumFractionDigits: 0 })
}
export default function FinanzplanSlide({ lang, investorId }: FinanzplanSlideProps) {
export default function FinanzplanSlide({ lang, investorId, preferredScenarioId }: FinanzplanSlideProps) {
const [sheets, setSheets] = useState<SheetMeta[]>([])
const [activeSheet, setActiveSheet] = useState<string>('personalkosten')
const [rows, setRows] = useState<SheetRow[]>([])
@@ -70,7 +71,7 @@ export default function FinanzplanSlide({ lang, investorId }: FinanzplanSlidePro
const de = lang === 'de'
// Financial model — same source as FinancialsSlide (Slide 15)
const fm = useFinancialModel(investorId || null)
const fm = useFinancialModel(investorId || null, preferredScenarioId)
const annualKPIs = useMemo(
() => computeAnnualKPIs(fm.activeResults?.results || []),
[fm.activeResults],