Problem-Text: Neuer Wortlaut (US-KI-Anbieter, 30.000+ Unternehmen, egal ob 10 oder 5.000 MA, Datenmissbrauch-Risiko) USP: "auf deutscher oder franzoesischer Cloud" KPI-Kacheln: 170+ Originaldokumente entfernt, 40.000→25.000+ Sicherheitskontrollen, 84→110 Gesetze & Regularien (nur EU+DACH), 761K→500K+ Lines of Code Konsistent in: i18n (DE+EN), Executive Summary (Slide+PDF), Competition, AI Pipeline, SDK Demo, Regulatory Landscape, Presenter Script, FAQ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
205 lines
9.3 KiB
TypeScript
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 — 25.000+ Sicherheitskontrollen', en: 'Legal RAG — 25,000+ Security 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>
|
|
)
|
|
}
|