Files
breakpilot-core/pitch-deck/components/slides/SDKDemoSlide.tsx
Benjamin Admin 32616504a6 feat: RAG-Zahlen korrigiert + Branchen-Regulierungs-Matrix
- Alle Zahlen aktualisiert: 170+ Originaldokumente, 40.000+ Controls,
  84 Regularien, 9 Branchen (statt 57 Module / 19 Regularien / 2.274 Texte)
- Neue Folie: Regulatorische Landschaft mit Branchen-Regulierungs-Matrix
- Konsistent in: Solution, Executive Summary (Slide+PDF), Competition,
  AI Pipeline, SDK Demo, Presenter Script, FAQ

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:40:44 +01:00

205 lines
9.3 KiB
TypeScript

'use client'
import { useState, useEffect, useCallback } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import Image from 'next/image'
import { Language } from '@/lib/types'
import GradientText from '../ui/GradientText'
import FadeInView from '../ui/FadeInView'
import { ChevronLeft, ChevronRight, Maximize2 } from 'lucide-react'
interface SDKDemoSlideProps {
lang: Language
}
const SCREENSHOTS = [
{ file: '01-dashboard.png', de: 'SDK Dashboard', en: 'SDK Dashboard', category: 'overview' },
{ file: '21-sdk-flow.png', de: 'SDK Flow — 36 Steps', en: 'SDK Flow — 36 Steps', category: 'overview' },
{ file: '02-company-profile.png', de: 'Unternehmensprofil', en: 'Company Profile', category: 'setup' },
{ file: '03-compliance-scope.png', de: 'Compliance-Scope', en: 'Compliance Scope', category: 'setup' },
{ file: '04-vvt.png', de: 'Verarbeitungsverzeichnis (Art. 30)', en: 'Processing Register (Art. 30)', category: 'docs' },
{ file: '05-tom.png', de: 'TOM — Maßnahmen (Art. 32)', en: 'TOM — Measures (Art. 32)', category: 'docs' },
{ file: '06-dsfa.png', de: 'Datenschutz-Folgenabschätzung', en: 'Data Protection Impact Assessment', category: 'docs' },
{ file: '07-risks.png', de: 'Risikomatrix', en: 'Risk Matrix', category: 'analysis' },
{ file: '08-obligations.png', de: 'Pflichtenübersicht', en: 'Obligations Overview', category: 'docs' },
{ file: '09-loeschfristen.png', de: 'Löschfristen', en: 'Retention Policies', category: 'docs' },
{ file: '10-controls.png', de: 'Controls', en: 'Controls', category: 'analysis' },
{ file: '11-ai-act.png', de: 'AI Act Compliance', en: 'AI Act Compliance', category: 'analysis' },
{ file: '12-requirements.png', de: 'Anforderungen', en: 'Requirements', category: 'analysis' },
{ file: '13-evidence.png', de: 'Nachweise', en: 'Evidence', category: 'analysis' },
{ file: '14-audit-report.png', de: 'Audit-Report', en: 'Audit Report', category: 'analysis' },
{ file: '15-document-generator.png', de: 'Dokumenten-Generator', en: 'Document Generator', category: 'docs' },
{ file: '16-einwilligungen.png', de: 'Einwilligungsmanagement', en: 'Consent Management', category: 'legal' },
{ file: '22-iace.png', de: 'CE-Compliance (IACE)', en: 'CE Compliance (IACE)', category: 'analysis' },
{ file: '20-rag.png', de: 'Legal RAG — 170+ Dokumente, 40.000+ Controls', en: 'Legal RAG — 170+ Documents, 40,000+ Controls', category: 'ai' },
{ file: '19-training.png', de: 'Compliance-Schulungen', en: 'Compliance Training', category: 'ops' },
{ file: '23-incidents.png', de: 'Incident Response', en: 'Incident Response', category: 'ops' },
{ file: '24-reporting.png', de: 'Reporting', en: 'Reporting', category: 'ops' },
]
export default function SDKDemoSlide({ lang }: SDKDemoSlideProps) {
const de = lang === 'de'
const [current, setCurrent] = useState(0)
const [fullscreen, setFullscreen] = useState(false)
const [autoPlay, setAutoPlay] = useState(true)
const next = useCallback(() => {
setCurrent(i => (i + 1) % SCREENSHOTS.length)
}, [])
const prev = useCallback(() => {
setCurrent(i => (i - 1 + SCREENSHOTS.length) % SCREENSHOTS.length)
}, [])
// Auto-advance every 3s when not in fullscreen
useEffect(() => {
if (!autoPlay || fullscreen) return
const timer = setInterval(next, 3000)
return () => clearInterval(timer)
}, [autoPlay, fullscreen, next])
const shot = SCREENSHOTS[current]
return (
<div>
<FadeInView className="text-center mb-6">
<p className="text-xs font-mono text-indigo-400/60 uppercase tracking-widest mb-2">
{de ? 'Anhang' : 'Appendix'}
</p>
<h2 className="text-4xl md:text-5xl font-bold mb-2">
<GradientText>{de ? 'SDK Live-Demo' : 'SDK Live Demo'}</GradientText>
</h2>
<p className="text-base text-white/50 max-w-2xl mx-auto">
{de
? 'Echte Screenshots aus dem Compliance SDK — Kundenprojekt: Müller Maschinenbau GmbH'
: 'Real screenshots from the Compliance SDK — Customer project: Müller Maschinenbau GmbH'}
</p>
</FadeInView>
<FadeInView delay={0.15}>
<div className="max-w-5xl mx-auto">
{/* Main screenshot viewer */}
<div className="relative group">
<div className="relative rounded-xl overflow-hidden border border-white/10 bg-black/30 shadow-2xl shadow-indigo-500/10">
{/* Browser chrome mockup */}
<div className="flex items-center gap-2 px-4 py-2 bg-white/[0.04] border-b border-white/10">
<div className="flex gap-1.5">
<div className="w-2.5 h-2.5 rounded-full bg-red-500/60" />
<div className="w-2.5 h-2.5 rounded-full bg-yellow-500/60" />
<div className="w-2.5 h-2.5 rounded-full bg-green-500/60" />
</div>
<div className="flex-1 ml-3">
<div className="bg-white/[0.06] rounded-md px-3 py-1 text-xs text-white/30 font-mono max-w-md">
admin.breakpilot.ai/sdk/{shot.file.replace(/^\d+-/, '').replace('.png', '')}
</div>
</div>
<button
onClick={() => setFullscreen(true)}
className="text-white/30 hover:text-white/60 transition"
>
<Maximize2 className="w-4 h-4" />
</button>
</div>
{/* Screenshot */}
<AnimatePresence mode="wait">
<motion.div
key={current}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
>
<Image
src={`/screenshots/${shot.file}`}
alt={de ? shot.de : shot.en}
width={1920}
height={1080}
className="w-full h-auto"
priority={current < 3}
/>
</motion.div>
</AnimatePresence>
</div>
{/* Navigation arrows */}
<button
onClick={() => { prev(); setAutoPlay(false) }}
className="absolute left-3 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-black/60 border border-white/10 flex items-center justify-center text-white/60 hover:text-white hover:bg-black/80 transition opacity-0 group-hover:opacity-100"
>
<ChevronLeft className="w-5 h-5" />
</button>
<button
onClick={() => { next(); setAutoPlay(false) }}
className="absolute right-3 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-black/60 border border-white/10 flex items-center justify-center text-white/60 hover:text-white hover:bg-black/80 transition opacity-0 group-hover:opacity-100"
>
<ChevronRight className="w-5 h-5" />
</button>
</div>
{/* Caption + Progress */}
<div className="flex items-center justify-between mt-4">
<div>
<p className="text-white font-medium">{de ? shot.de : shot.en}</p>
<p className="text-xs text-white/30 font-mono">{current + 1} / {SCREENSHOTS.length}</p>
</div>
<button
onClick={() => setAutoPlay(!autoPlay)}
className="text-xs text-white/40 hover:text-white/60 transition font-mono"
>
{autoPlay ? (de ? '⏸ Pause' : '⏸ Pause') : (de ? '▶ Auto' : '▶ Auto')}
</button>
</div>
{/* Thumbnail strip */}
<div className="flex gap-1.5 mt-3 overflow-x-auto pb-2 scrollbar-thin">
{SCREENSHOTS.map((s, idx) => (
<button
key={idx}
onClick={() => { setCurrent(idx); setAutoPlay(false) }}
className={`shrink-0 w-16 h-9 rounded overflow-hidden border transition ${
idx === current
? 'border-indigo-500 ring-1 ring-indigo-500/50'
: 'border-white/10 opacity-50 hover:opacity-80'
}`}
>
<Image
src={`/screenshots/${s.file}`}
alt=""
width={64}
height={36}
className="w-full h-full object-cover"
/>
</button>
))}
</div>
</div>
</FadeInView>
{/* Fullscreen overlay */}
<AnimatePresence>
{fullscreen && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-50 bg-black/95 flex items-center justify-center cursor-pointer"
onClick={() => setFullscreen(false)}
>
<Image
src={`/screenshots/${shot.file}`}
alt={de ? shot.de : shot.en}
width={1920}
height={1080}
className="max-w-[95vw] max-h-[90vh] object-contain"
/>
<p className="absolute bottom-6 text-white/50 text-sm">
{de ? shot.de : shot.en} {de ? 'Klicken zum Schließen' : 'Click to close'}
</p>
</motion.div>
)}
</AnimatePresence>
</div>
)
}