import { useEffect, useState } from 'react'
import { api } from '../api'
import { useJob, ProgressBox, ErrorBox } from '../hooks'
import PromptPanel from '../components/PromptPanel'
export default function ScriptStep({ reelData, refreshReel, reelId, projectId, setStep }) {
const reel = reelData?.reel
const script = reelData?.script
const base = `/api/projects/${projectId}/reels/${reelId}`
const [local, setLocal] = useState(script)
const [dirty, setDirty] = useState(false)
const [topic, setTopic] = useState(reel?.topic || '')
const [targetSec, setTargetSec] = useState(0) // 0 = auto (default 30–45s)
const [prompt, setPrompt] = useState(null)
const [scenePrompts, setScenePrompts] = useState({}) // {sceneNo: prompt override}
const [error, setError] = useState('')
const genJob = useJob()
const sceneJob = useJob()
useEffect(() => { setLocal(reelData?.script); setDirty(false) }, [reelData?.script])
useEffect(() => { setTopic(reel?.topic || '') }, [reel?.topic])
if (!reelId) {
return (
Script
Select or create a reel first (left sidebar), or pick a topic on the Topics step.
)
}
const mutate = (fn) => { const next = structuredClone(local); fn(next); setLocal(next); setDirty(true) }
const save = async () => {
try {
await api.patch(`${base}/script`, local)
await refreshReel()
setError('')
} catch (e) { setError(e.message) }
}
const generate = async () => {
if (!topic.trim()) { setError('Enter a topic for this reel first.'); return }
try {
await genJob.start(`${base}/script/generate`, { topic: topic.trim(), prompt, target_sec: targetSec || null })
await refreshReel()
} catch { /* shown */ }
}
const regenerateScene = async (sceneNo) => {
try {
await sceneJob.start(`${base}/script/regenerate-scene`, { scene: sceneNo, prompt: scenePrompts[sceneNo] ?? null })
await refreshReel()
} catch { /* shown */ }
}
const goMedia = async () => { if (dirty) await save(); setStep(4) }
// --- No script yet: topic + generate (with editable prompt) ---
if (!local) {
return (
Script
Write the scene-structured script for this reel, in your references' style.
)
}
// --- Script exists: editable scenes ---
return (
Script
Topic: {local.topic || local.title}
{local.clone_source && <> · cloned structure from source (fresh wording)>}
{(genJob.running || sceneJob.running) &&
}
Hook — pick one of 3 (spoken in the first 2 seconds)
{local.hook_options.map((h, i) => (
))}
{local.scenes.map((scene, i) => (
))}
{/* Regenerate whole script — with editable prompt */}
(await api.post(`${base}/script/prompt`, { topic: local.topic || local.title })).prompt}
/>
{dirty &&
}
)
}