Some checks failed
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 32s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 32s
CI / Deploy (push) Failing after 4s
Build pitch-deck / build-and-push (push) Failing after 59s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
Replaces raw JSON textarea in version editor with proper form UIs: - Company: single-record form with side-by-side DE/EN tagline + mission - Team: expandable card list with bilingual role/bio, expertise tags - Financials: year-by-year table with numeric inputs - Market: TAM/SAM/SOM row table - Competitors: card list with strengths/weaknesses tag arrays - Features: card list with DE/EN names + checkbox matrix - Milestones: card list with DE/EN title/description + status dropdown - Metrics: card list with DE/EN labels - Funding: form + nested use_of_funds table - Products: card list with DE/EN capabilities + feature tag arrays - FM Scenarios: card list with color picker - FM Assumptions: row table Shared editor primitives (components/pitch-admin/editors/): BilingualField, FormField, ArrayField, RowTable, CardList "Edit as JSON" toggle preserved as escape hatch on every tab. Preview: admin clicks "Preview" on version editor → opens /pitch-preview/[versionId] in new tab showing the full pitch deck with that version's data. Admin-cookie gated (no investor auth). Yellow "PREVIEW MODE" banner at top. Also fixes the [object Object] inline table type cast in FM editor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState, useCallback } from 'react'
|
|
import { useParams } from 'next/navigation'
|
|
import { Language, PitchData } from '@/lib/types'
|
|
import PitchDeck from '@/components/PitchDeck'
|
|
|
|
export default function PreviewPage() {
|
|
const { versionId } = useParams<{ versionId: string }>()
|
|
const [data, setData] = useState<PitchData | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const [lang, setLang] = useState<Language>('de')
|
|
|
|
const toggleLanguage = useCallback(() => {
|
|
setLang(prev => prev === 'de' ? 'en' : 'de')
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (!versionId) return
|
|
setLoading(true)
|
|
fetch(`/api/preview-data/${versionId}`)
|
|
.then(async r => {
|
|
if (!r.ok) throw new Error((await r.json().catch(() => ({}))).error || 'Failed to load')
|
|
return r.json()
|
|
})
|
|
.then(setData)
|
|
.catch(e => setError(e.message))
|
|
.finally(() => setLoading(false))
|
|
}, [versionId])
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="h-screen flex items-center justify-center bg-[#0a0a1a]">
|
|
<div className="text-center">
|
|
<div className="w-12 h-12 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" />
|
|
<p className="text-white/40 text-sm">Loading preview...</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (error || !data) {
|
|
return (
|
|
<div className="h-screen flex items-center justify-center bg-[#0a0a1a]">
|
|
<div className="text-center max-w-md px-6">
|
|
<p className="text-rose-400 mb-2">Preview Error</p>
|
|
<p className="text-white/40 text-sm">{error || 'No data found for this version'}</p>
|
|
<p className="text-white/30 text-xs mt-4">Make sure you are logged in as an admin.</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// Render PitchDeck with no investor (no watermark, no audit) — admin preview only
|
|
// The banner at the top indicates this is a preview
|
|
return (
|
|
<div className="relative">
|
|
{/* Preview banner */}
|
|
<div className="fixed top-0 left-0 right-0 z-[100] bg-amber-500/90 text-black text-center py-1.5 text-xs font-semibold">
|
|
PREVIEW MODE — This is how investors will see this version
|
|
</div>
|
|
<PitchDeck
|
|
lang={lang}
|
|
onToggleLanguage={toggleLanguage}
|
|
investor={null}
|
|
onLogout={() => {}}
|
|
previewData={data}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|