'use client' import { useState, useEffect } from 'react' import { createPortal } from 'react-dom' import { motion } from 'framer-motion' import { Maximize2 } from 'lucide-react' import { FMResult } from '@/lib/types' import { AnnualPLTableProps, AnnualRow, MonthlyRow, AccountingStandard, } from './AnnualPLTable.types' import { AnnualTable, FullscreenOverlay } from './AnnualPLTable.parts' export default function AnnualPLTable({ results, lang }: AnnualPLTableProps) { const [isFullscreen, setIsFullscreen] = useState(false) const [expandedYear, setExpandedYear] = useState(null) const [standard, setStandard] = useState('hgb') const [portalRoot, setPortalRoot] = useState(null) const de = lang === 'de' // Portal mount point useEffect(() => { setPortalRoot(document.body) }, []) // Aggregate monthly results into annual const annualMap = new Map() for (const r of results) { if (!annualMap.has(r.year)) annualMap.set(r.year, []) annualMap.get(r.year)!.push(r) } const rows: AnnualRow[] = Array.from(annualMap.entries()).map(([year, months]) => { const revenue = months.reduce((s, m) => s + m.revenue_eur, 0) const cogs = months.reduce((s, m) => s + m.cogs_eur, 0) const grossProfit = revenue - cogs const personnel = months.reduce((s, m) => s + m.personnel_eur, 0) const marketing = months.reduce((s, m) => s + m.marketing_eur, 0) const infra = months.reduce((s, m) => s + m.infra_eur, 0) const totalOpex = personnel + marketing + infra const ebitda = grossProfit - totalOpex const lastMonth = months[months.length - 1] return { year, revenue, cogs, grossProfit, grossMarginPct: revenue > 0 ? (grossProfit / revenue) * 100 : 0, personnel, marketing, infra, totalOpex, ebitda, ebitdaMarginPct: revenue > 0 ? (ebitda / revenue) * 100 : 0, customers: lastMonth.total_customers, employees: lastMonth.employees_count, } }) // Build monthly data for drill-down const monthlyData = new Map() for (const [year, months] of annualMap.entries()) { monthlyData.set(year, months.map(m => { const grossProfit = m.revenue_eur - m.cogs_eur const totalCosts = m.personnel_eur + m.marketing_eur + m.infra_eur const ebitda = grossProfit - totalCosts return { month: m.month, monthInYear: m.month_in_year, revenue: m.revenue_eur, cogs: m.cogs_eur, grossProfit, grossMarginPct: m.revenue_eur > 0 ? (grossProfit / m.revenue_eur) * 100 : 0, personnel: m.personnel_eur, marketing: m.marketing_eur, infra: m.infra_eur, totalCosts, ebitda, ebitdaMarginPct: m.revenue_eur > 0 ? (ebitda / m.revenue_eur) * 100 : 0, customers: m.total_customers, employees: m.employees_count, mrr: m.mrr_eur, cashBalance: m.cash_balance_eur, } })) } const handleToggleYear = (year: number) => { setExpandedYear(prev => prev === year ? null : year) } const tableContent = ( ) return ( <>
{/* HGB / US GAAP Toggle (inline) */}
{tableContent}

{de ? 'Klicke auf ein Jahr fuer Monatsdetails' : 'Click on a year for monthly details'}

{/* Fullscreen via Portal — escapes parent stacking context */} {isFullscreen && portalRoot && createPortal( setIsFullscreen(false)} lang={lang} standard={standard} onStandardChange={setStandard} > , portalRoot )} ) }