'use client' import { useCallback, 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 { RefreshCw, Download, ChevronLeft, ChevronRight } from 'lucide-react' interface FinanzplanSlideProps { lang: Language } interface SheetMeta { name: string label_de: string label_en: string rows: number } interface SheetRow { id: number row_label?: string person_name?: string item_name?: string category?: string section?: string is_editable?: boolean is_sum_row?: boolean values?: Record values_total?: Record values_brutto?: Record brutto_monthly?: number position?: string start_date?: string purchase_amount?: number } const MONTH_LABELS = [ 'Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez', ] function getLabel(row: SheetRow): string { return row.row_label || row.person_name || row.item_name || '—' } function getValues(row: SheetRow): Record { return row.values || row.values_total || row.values_brutto || {} } function formatCell(v: number | undefined): string { if (v === undefined || v === null) return '' if (v === 0) return '—' if (Math.abs(v) >= 1000) return v.toLocaleString('de-DE', { maximumFractionDigits: 0 }) return v.toLocaleString('de-DE', { maximumFractionDigits: 2 }) } export default function FinanzplanSlide({ lang }: FinanzplanSlideProps) { const [sheets, setSheets] = useState([]) const [activeSheet, setActiveSheet] = useState('personalkosten') const [rows, setRows] = useState([]) const [loading, setLoading] = useState(false) const [computing, setComputing] = useState(false) const [yearOffset, setYearOffset] = useState(0) // 0=2026, 1=2027, ... const de = lang === 'de' // Load sheet list useEffect(() => { fetch('/api/finanzplan') .then(r => r.json()) .then(data => setSheets(data.sheets || [])) .catch(() => {}) }, []) // Load sheet data const loadSheet = useCallback(async (name: string) => { setLoading(true) try { const r = await fetch(`/api/finanzplan/${name}`) const data = await r.json() setRows(data.rows || []) } catch { /* ignore */ } setLoading(false) }, []) useEffect(() => { loadSheet(activeSheet) }, [activeSheet, loadSheet]) // Compute const handleCompute = async () => { setComputing(true) try { await fetch('/api/finanzplan/compute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' }) await loadSheet(activeSheet) } catch { /* ignore */ } setComputing(false) } // Cell edit const handleCellEdit = async (rowId: number, monthKey: string, newValue: string) => { const numVal = parseFloat(newValue.replace(/[^\d.-]/g, '')) if (isNaN(numVal)) return try { await fetch(`/api/finanzplan/${activeSheet}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ rowId, updates: { [monthKey]: numVal } }), }) await loadSheet(activeSheet) } catch { /* ignore */ } } const currentYear = 2026 + yearOffset const monthStart = yearOffset * 12 + 1 const monthEnd = monthStart + 11 return (

{de ? 'Finanzplan' : 'Financial Plan'}

{de ? '2026–2030 · Monatliche Granularitaet · Editierbar' : '2026–2030 · Monthly Granularity · Editable'}

{/* Tab Bar */}
{sheets.map(s => ( ))}
{/* Year Navigation */}
{currentYear}
{/* Data Grid */} {loading ? (
{de ? 'Lade...' : 'Loading...'}
) : ( {MONTH_LABELS.map((label, idx) => ( ))} {rows.map(row => { const values = getValues(row) const label = getLabel(row) const isSumRow = row.is_sum_row || label.includes('GESAMT') || label.includes('Summe') || label.includes('UEBERSCHUSS') || label.includes('LIQUIDITAET') const isEditable = row.is_editable // Annual sum for visible year let annual = 0 for (let m = monthStart; m <= monthEnd; m++) annual += values[`m${m}`] || 0 return ( {Array.from({ length: 12 }, (_, idx) => { const mKey = `m${monthStart + idx}` const v = values[mKey] || 0 return ( ) })} ) })}
{de ? 'Position' : 'Item'} {currentYear} {label}
{isEditable && } {label} {row.position && ({row.position})} {row.section && [{row.section}]}
{formatCell(annual)} 0 ? (isSumRow ? 'text-white/70' : 'text-white/50') : 'text-white/15' } ${isEditable ? 'cursor-pointer hover:bg-indigo-500/10' : ''}`} onDoubleClick={() => { if (!isEditable) return const input = prompt(`${label} — ${MONTH_LABELS[idx]} ${currentYear}`, String(v)) if (input !== null) handleCellEdit(row.id, mKey, input) }} > {formatCell(v)}
)}

{de ? 'Doppelklick auf blaue Zellen zum Bearbeiten · Gruendung: 01.08.2026' : 'Double-click blue cells to edit · Founding: 01.08.2026'}

) }