"use client"; import { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { Loader2, Save, RefreshCw, AudioLines } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { updateScriptAction, regenerateAction, regenerateSectionAction, } from "@/app/(app)/episodes/actions"; interface Turn { speakerKey: string; text: string; } interface Section { id: string; title: string; turns: Turn[]; } interface Script { title: string; sections: Section[]; } export function ScriptEditor({ episodeId, script, speakerNames, }: { episodeId: string; script: Script; speakerNames: Record; }) { const router = useRouter(); const [sections, setSections] = useState(script.sections); const [dirty, setDirty] = useState(false); const [saving, startSave] = useTransition(); const [busySection, setBusySection] = useState(null); const [rerecording, setRerecording] = useState(false); function updateTurn(si: number, ti: number, text: string) { setSections((prev) => prev.map((s, i) => i === si ? { ...s, turns: s.turns.map((t, j) => (j === ti ? { ...t, text } : t)) } : s ) ); setDirty(true); } function save() { startSave(async () => { const res = await updateScriptAction(episodeId, { title: script.title, sections }); if (res.ok) { toast.success("Script saved"); setDirty(false); } else { toast.error(res.error ?? "Could not save"); } }); } async function regenSection(id: string) { setBusySection(id); const res = await regenerateSectionAction(episodeId, id); setBusySection(null); if (!res.ok || !res.section) { toast.error(res.error ?? "Could not regenerate"); return; } setSections((prev) => prev.map((s) => (s.id === id ? res.section! : s))); setDirty(false); toast.success("Section regenerated"); } async function rerecord() { setRerecording(true); if (dirty) { const saved = await updateScriptAction(episodeId, { title: script.title, sections }); if (!saved.ok) { toast.error(saved.error ?? "Save failed"); setRerecording(false); return; } setDirty(false); } const res = await regenerateAction(episodeId, "audio"); if (res.ok) { toast.success("Re-recording audio…"); router.refresh(); } else { toast.error(res.error ?? "Could not re-record"); setRerecording(false); } } return (

Script

{sections.map((section, si) => ( {section.title} {section.turns.map((turn, ti) => (
{speakerNames[turn.speakerKey] ?? turn.speakerKey}