Remove standalone services (ai-compliance-sdk root, developer-portal, dsms-gateway, dsms-node, night-scheduler) and legacy compliance/dsgvo pages. Add new SDK pipeline modules (academy, document-crawler, dsb-portal, incidents, whistleblower, reporting, sso, multi-tenant, industry-templates). Add drafting engine, legal corpus files (AT/CH/DE), pitch-deck, blog and Förderantrag pages. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
92 lines
3.4 KiB
TypeScript
92 lines
3.4 KiB
TypeScript
'use client'
|
|
|
|
import { motion } from 'framer-motion'
|
|
import { Language, PitchMarket } from '@/lib/types'
|
|
import { t, formatEur } from '@/lib/i18n'
|
|
import GradientText from '../ui/GradientText'
|
|
import FadeInView from '../ui/FadeInView'
|
|
import AnimatedCounter from '../ui/AnimatedCounter'
|
|
|
|
interface MarketSlideProps {
|
|
lang: Language
|
|
market: PitchMarket[]
|
|
}
|
|
|
|
const sizes = [280, 200, 130]
|
|
const colors = ['border-indigo-500/30 bg-indigo-500/5', 'border-purple-500/30 bg-purple-500/5', 'border-blue-500/30 bg-blue-500/5']
|
|
const textColors = ['text-indigo-400', 'text-purple-400', 'text-blue-400']
|
|
|
|
export default function MarketSlide({ lang, market }: MarketSlideProps) {
|
|
const i = t(lang)
|
|
const labels = [i.market.tamLabel, i.market.samLabel, i.market.somLabel]
|
|
const segments = [i.market.tam, i.market.sam, i.market.som]
|
|
|
|
return (
|
|
<div>
|
|
<FadeInView className="text-center mb-12">
|
|
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
|
<GradientText>{i.market.title}</GradientText>
|
|
</h2>
|
|
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.market.subtitle}</p>
|
|
</FadeInView>
|
|
|
|
<div className="flex flex-col md:flex-row items-center justify-center gap-12">
|
|
{/* Circles */}
|
|
<div className="relative flex items-center justify-center" style={{ width: 300, height: 300 }}>
|
|
{market.map((m, idx) => (
|
|
<motion.div
|
|
key={m.id}
|
|
initial={{ scale: 0, opacity: 0 }}
|
|
animate={{ scale: 1, opacity: 1 }}
|
|
transition={{ delay: 0.3 + idx * 0.2, type: 'spring', stiffness: 200 }}
|
|
className={`absolute rounded-full border-2 ${colors[idx]} flex items-center justify-center`}
|
|
style={{
|
|
width: sizes[idx],
|
|
height: sizes[idx],
|
|
}}
|
|
>
|
|
{idx === market.length - 1 && (
|
|
<div className="text-center">
|
|
<span className={`text-xs font-mono ${textColors[idx]}`}>{segments[idx]}</span>
|
|
</div>
|
|
)}
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Labels */}
|
|
<div className="space-y-6">
|
|
{market.map((m, idx) => (
|
|
<motion.div
|
|
key={m.id}
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ delay: 0.5 + idx * 0.15 }}
|
|
className="flex items-center gap-4"
|
|
>
|
|
<div className={`w-3 h-3 rounded-full ${textColors[idx]} bg-current`} />
|
|
<div>
|
|
<div className="flex items-center gap-2">
|
|
<span className={`text-sm font-bold ${textColors[idx]}`}>{segments[idx]}</span>
|
|
<span className="text-xs text-white/30">{labels[idx]}</span>
|
|
</div>
|
|
<div className="text-2xl font-bold text-white">
|
|
<AnimatedCounter
|
|
target={m.value_eur / 1_000_000_000}
|
|
suffix={lang === 'de' ? ' Mrd. EUR' : 'B EUR'}
|
|
decimals={1}
|
|
duration={1500}
|
|
/>
|
|
</div>
|
|
<div className="text-xs text-white/40">
|
|
{i.market.growth}: {m.growth_rate_pct}% · {i.market.source}: {m.source}
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|