feat(pitch-deck): larger chart labels + 2 new charts (Liquidität + Revenue vs Costs)
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m6s
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 33s
CI / test-python-voice (push) Successful in 34s
CI / test-bqas (push) Successful in 28s

Charts tab:
- All bar labels increased from 7-8px to 11px (readable)
- New: Liquidität (Jahresende) bar chart — shows cash position per year
- New: Umsatz vs. Gesamtkosten — side-by-side bars per year
- All charts read from fpKPIs (fp_* source of truth)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-20 10:14:39 +02:00
parent 9513675d85
commit 6ec27fdbf2

View File

@@ -357,7 +357,7 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
<div className="flex items-end gap-1 w-full justify-center" style={{ height: '160px' }}> <div className="flex items-end gap-1 w-full justify-center" style={{ height: '160px' }}>
{/* MRR bar */} {/* MRR bar */}
<div className="w-8 bg-indigo-500/60 rounded-t transition-all" style={{ height: `${(d.mrr / d.max_mrr) * 150}px` }}> <div className="w-8 bg-indigo-500/60 rounded-t transition-all" style={{ height: `${(d.mrr / d.max_mrr) * 150}px` }}>
<div className="text-[7px] text-white/70 text-center -mt-3 whitespace-nowrap"> <div className="text-[11px] text-white/80 text-center -mt-4 whitespace-nowrap font-semibold">
{d.mrr >= 100000 ? `${Math.round(d.mrr/1000)}k` : d.mrr.toLocaleString('de-DE')} {d.mrr >= 100000 ? `${Math.round(d.mrr/1000)}k` : d.mrr.toLocaleString('de-DE')}
</div> </div>
</div> </div>
@@ -392,12 +392,12 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
<div className="w-10 flex flex-col justify-end" style={{ height: '110px' }}> <div className="w-10 flex flex-col justify-end" style={{ height: '110px' }}>
{k.ebit >= 0 ? ( {k.ebit >= 0 ? (
<div className="bg-emerald-500/60 rounded-t w-full" style={{ height: `${h}px` }}> <div className="bg-emerald-500/60 rounded-t w-full" style={{ height: `${h}px` }}>
<div className="text-[7px] text-emerald-300 text-center -mt-3 whitespace-nowrap">{Math.round(k.ebit/1000)}k</div> <div className="text-[11px] text-emerald-300 text-center -mt-4 whitespace-nowrap font-semibold">{Math.round(k.ebit/1000)}k</div>
</div> </div>
) : ( ) : (
<div className="flex flex-col justify-end h-full"> <div className="flex flex-col justify-end h-full">
<div className="bg-red-500/60 rounded-b w-full" style={{ height: `${h}px` }}> <div className="bg-red-500/60 rounded-b w-full" style={{ height: `${h}px` }}>
<div className="text-[7px] text-red-300 text-center mt-1 whitespace-nowrap">{Math.round(k.ebit/1000)}k</div> <div className="text-[11px] text-red-300 text-center mt-1 whitespace-nowrap font-semibold">{Math.round(k.ebit/1000)}k</div>
</div> </div>
</div> </div>
)} )}
@@ -421,7 +421,7 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
<div key={idx} className="flex flex-col items-center"> <div key={idx} className="flex flex-col items-center">
<div className="w-10 flex flex-col justify-end" style={{ height: '110px' }}> <div className="w-10 flex flex-col justify-end" style={{ height: '110px' }}>
<div className="bg-amber-500/60 rounded-t w-full" style={{ height: `${(d.val / maxEmp) * 100}px` }}> <div className="bg-amber-500/60 rounded-t w-full" style={{ height: `${(d.val / maxEmp) * 100}px` }}>
<div className="text-[8px] text-amber-300 text-center -mt-3 font-bold">{d.val}</div> <div className="text-[11px] text-amber-300 text-center -mt-4 font-bold">{d.val}</div>
</div> </div>
</div> </div>
<span className="text-[10px] text-white/40 mt-1">{d.year}</span> <span className="text-[10px] text-white/40 mt-1">{d.year}</span>
@@ -431,6 +431,71 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
</div> </div>
</GlassCard> </GlassCard>
</div> </div>
{/* Liquidität Chart */}
<GlassCard hover={false} className="p-4">
<h3 className="text-xs font-bold text-cyan-400 uppercase tracking-wider mb-3">{de ? 'Liquidität (Jahresende)' : 'Cash Position (Year-End)'}</h3>
<div className="grid grid-cols-5 gap-1 items-end h-36">
{(() => {
const years = ['y2026','y2027','y2028','y2029','y2030']
const data = years.map(y => ({ year: y.slice(1), val: fpKPIs[y]?.liquiditaet || 0 }))
const maxAbs = Math.max(...data.map(d => Math.abs(d.val)), 1)
return data.map((d, idx) => {
const h = Math.abs(d.val) / maxAbs * 100
const label = Math.abs(d.val) >= 1000000 ? `${(d.val/1000000).toFixed(1)}M` : `${Math.round(d.val/1000)}k`
return (
<div key={idx} className="flex flex-col items-center">
<div className="w-10 flex flex-col justify-end" style={{ height: '110px' }}>
<div className={`${d.val >= 0 ? 'bg-cyan-500/60 rounded-t' : 'bg-red-500/60 rounded-b'} w-full`} style={{ height: `${Math.max(h, 4)}px` }}>
<div className={`text-[11px] ${d.val >= 0 ? 'text-cyan-300 -mt-4' : 'text-red-300 mt-1'} text-center whitespace-nowrap font-semibold`}>{label}</div>
</div>
</div>
<span className="text-[10px] text-white/40 mt-1">{d.year}</span>
</div>
)
})
})()}
</div>
</GlassCard>
{/* Umsatz vs. Kosten Chart */}
<GlassCard hover={false} className="p-4">
<h3 className="text-xs font-bold text-indigo-400 uppercase tracking-wider mb-3">{de ? 'Umsatz vs. Gesamtkosten' : 'Revenue vs. Total Costs'}</h3>
<div className="grid grid-cols-5 gap-1 items-end h-36">
{(() => {
const years = ['y2026','y2027','y2028','y2029','y2030']
const data = years.map(y => ({
year: y.slice(1),
rev: fpKPIs[y]?.revenue || 0,
costs: (fpKPIs[y]?.personal || 0) + Math.abs(fpKPIs[y]?.ebit || 0) + (fpKPIs[y]?.revenue || 0) - (fpKPIs[y]?.ebit || 0) - (fpKPIs[y]?.revenue || 0),
}))
// Simpler: costs = revenue - ebit
const data2 = years.map(y => ({
year: y.slice(1),
rev: fpKPIs[y]?.revenue || 0,
costs: (fpKPIs[y]?.revenue || 0) - (fpKPIs[y]?.ebit || 0),
}))
const maxVal = Math.max(...data2.map(d => Math.max(d.rev, d.costs)), 1)
return data2.map((d, idx) => (
<div key={idx} className="flex flex-col items-center gap-1">
<div className="flex items-end gap-1 w-full justify-center" style={{ height: '100px' }}>
<div className="w-6 bg-indigo-500/60 rounded-t" style={{ height: `${(d.rev / maxVal) * 90}px` }}>
<div className="text-[10px] text-indigo-300 text-center -mt-3 whitespace-nowrap font-semibold">{d.rev >= 1000000 ? `${(d.rev/1000000).toFixed(1)}M` : `${Math.round(d.rev/1000)}k`}</div>
</div>
<div className="w-6 bg-red-500/40 rounded-t" style={{ height: `${(d.costs / maxVal) * 90}px` }}>
<div className="text-[10px] text-red-300 text-center -mt-3 whitespace-nowrap font-semibold">{d.costs >= 1000000 ? `${(d.costs/1000000).toFixed(1)}M` : `${Math.round(d.costs/1000)}k`}</div>
</div>
</div>
<span className="text-[10px] text-white/40">{d.year}</span>
</div>
))
})()}
</div>
<div className="flex justify-center gap-6 mt-2 text-[10px]">
<span className="flex items-center gap-1"><span className="w-3 h-2 bg-indigo-500/60 rounded inline-block" /> {de ? 'Umsatz' : 'Revenue'}</span>
<span className="flex items-center gap-1"><span className="w-3 h-2 bg-red-500/40 rounded inline-block" /> {de ? 'Kosten' : 'Costs'}</span>
</div>
</GlassCard>
</div> </div>
)} )}