This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/pitch-deck/components/NavigationFAB.tsx
BreakPilot Dev b464366341
Some checks failed
ci/woodpecker/push/integration Pipeline failed
ci/woodpecker/push/main Pipeline failed
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
feat: Add staged funding model, financial compute engine, annex slides and UI enhancements
Restructure financial plan from single 200k SAFE to realistic staged funding
(25k Stammkapital, 25k Angel, 200k Wandeldarlehen, 1M Series A = 1.25M total).
Add 60-month compute engine with CAPEX/OPEX accounting, cash constraints,
hardware financing (30% upfront / 70% leasing), and revenue-based hiring caps.
Rebuild TheAskSlide with 4-event funding timeline, update i18n (DE/EN),
chat agent core messages, and add 15 new annex/technology slides with
supporting UI components (KPICard, RunwayGauge, WaterfallChart, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 21:20:02 +01:00

167 lines
6.2 KiB
TypeScript

'use client'
import { useState, useCallback } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { Menu, X, Maximize, Minimize, Bot } from 'lucide-react'
import { Language } from '@/lib/types'
import { t } from '@/lib/i18n'
interface NavigationFABProps {
currentIndex: number
totalSlides: number
visitedSlides: Set<number>
onGoToSlide: (index: number) => void
lang: Language
onToggleLanguage: () => void
}
export default function NavigationFAB({
currentIndex,
totalSlides,
visitedSlides,
onGoToSlide,
lang,
onToggleLanguage,
}: NavigationFABProps) {
const [isOpen, setIsOpen] = useState(false)
const [isFullscreen, setIsFullscreen] = useState(false)
const i = t(lang)
const toggleFullscreen = useCallback(() => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen()
setIsFullscreen(true)
} else {
document.exitFullscreen()
setIsFullscreen(false)
}
}, [])
return (
<div className="fixed bottom-6 right-6 z-50">
<AnimatePresence mode="wait">
{!isOpen ? (
<motion.button
key="fab"
initial={{ scale: 0 }}
animate={{ scale: 1 }}
exit={{ scale: 0 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
onClick={() => setIsOpen(true)}
className="w-14 h-14 rounded-full bg-indigo-600 hover:bg-indigo-500
flex items-center justify-center shadow-lg shadow-indigo-600/30
transition-colors"
>
<Menu className="w-6 h-6 text-white" />
</motion.button>
) : (
<motion.div
key="panel"
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
transition={{ duration: 0.2 }}
className="w-[300px] max-h-[80vh] rounded-2xl overflow-hidden
bg-black/80 backdrop-blur-xl border border-white/10
shadow-2xl shadow-black/50"
>
{/* Header */}
<div className="flex items-center justify-between px-4 py-3 border-b border-white/10">
<span className="text-sm font-semibold text-white">{i.nav.slides}</span>
<button
onClick={() => setIsOpen(false)}
className="w-7 h-7 rounded-full bg-white/10 flex items-center justify-center
hover:bg-white/20 transition-colors"
>
<X className="w-4 h-4 text-white/60" />
</button>
</div>
{/* Slide List */}
<div className="overflow-y-auto max-h-[55vh] py-2">
{i.slideNames.map((name, idx) => {
const isActive = idx === currentIndex
const isVisited = visitedSlides.has(idx)
const isAI = idx === 13
return (
<div key={idx}>
{idx === 14 && (
<div className="mx-4 my-1 border-t border-white/10 pt-1">
<span className="text-[9px] text-white/20 uppercase tracking-wider">Appendix</span>
</div>
)}
<button
onClick={() => onGoToSlide(idx)}
className={`
w-full flex items-center gap-3 px-4 py-2.5 text-left
transition-all text-sm
${isActive
? 'bg-indigo-500/20 border-l-2 border-indigo-500 text-white'
: 'hover:bg-white/[0.06] text-white/60 hover:text-white border-l-2 border-transparent'
}
`}
>
<span className={`
w-6 h-6 rounded-full flex items-center justify-center text-xs font-mono shrink-0
${isActive
? 'bg-indigo-500 text-white'
: isVisited
? 'bg-white/10 text-white/60'
: 'bg-white/5 text-white/30'
}
`}>
{idx + 1}
</span>
<span className="flex-1 truncate">{name}</span>
{isAI && <Bot className="w-4 h-4 text-indigo-400 shrink-0" />}
{isActive && (
<span className="w-2 h-2 rounded-full bg-indigo-400 shrink-0" />
)}
</button>
</div>
)
})}
</div>
{/* Footer */}
<div className="border-t border-white/10 px-4 py-3 space-y-2">
{/* Language Toggle */}
<button
onClick={onToggleLanguage}
className="w-full flex items-center justify-between px-3 py-2 rounded-lg
bg-white/[0.05] hover:bg-white/[0.1] transition-colors text-sm"
>
<span className="text-white/50">{i.nav.language}</span>
<div className="flex items-center gap-1">
<span className={`px-2 py-0.5 rounded text-xs font-medium ${lang === 'de' ? 'bg-indigo-500 text-white' : 'text-white/40'}`}>
DE
</span>
<span className={`px-2 py-0.5 rounded text-xs font-medium ${lang === 'en' ? 'bg-indigo-500 text-white' : 'text-white/40'}`}>
EN
</span>
</div>
</button>
{/* Fullscreen */}
<button
onClick={toggleFullscreen}
className="w-full flex items-center justify-between px-3 py-2 rounded-lg
bg-white/[0.05] hover:bg-white/[0.1] transition-colors text-sm"
>
<span className="text-white/50">{i.nav.fullscreen}</span>
{isFullscreen ? (
<Minimize className="w-4 h-4 text-white/50" />
) : (
<Maximize className="w-4 h-4 text-white/50" />
)}
</button>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
)
}