import React, { useState } from 'react'; import { ProjectStructure, StructureItem, ProjectType } from '../types'; import { Film, Edit2, Trash2, Plus, Save, Eye, Dices, X, Sparkles, Clock, Zap, Terminal, ChevronDown, ChevronRight } from 'lucide-react'; import { optimizeVisualPrompt } from '../services/geminiService'; interface StructurePlannerProps { structure: ProjectStructure; type: ProjectType; onSelectEpisode: (item: StructureItem) => void; onUpdateStructure: (newStructure: ProjectStructure) => void; onReroll: () => void; isGenerating: boolean; producingItemId: string | null; modelSettings: any; // Using any to avoid circular type ref, should be ModelSettings } const StructurePlanner: React.FC = ({ structure, type, onSelectEpisode, onUpdateStructure, onReroll, isGenerating, producingItemId, modelSettings }) => { const [editingId, setEditingId] = useState(null); const [editForm, setEditForm] = useState(null); const [editMode, setEditMode] = useState<'auto' | 'pro'>('auto'); // New: Auto vs Pro mode const [isOptimizing, setIsOptimizing] = useState(false); const getHeaderIcon = () => { switch (type) { case ProjectType.MUSIC_VIDEO: return ; case ProjectType.VIRTUAL_INFLUENCER: return ; default: return ; } }; const getItemLabel = () => { switch (type) { case ProjectType.MUSIC_VIDEO: return "段落 (Beat)"; case ProjectType.VIRTUAL_INFLUENCER: return "貼文 (Post)"; default: return "集數 (Episode)"; } }; const handleEditClick = (item: StructureItem) => { setEditingId(item.id); setEditForm({ ...item }); setEditMode('auto'); // Default to auto mode on open }; const handleSaveEdit = () => { if (editForm) { const newItems = structure.items.map(i => i.id === editForm.id ? editForm : i); onUpdateStructure({ ...structure, items: newItems }); setEditingId(null); setEditForm(null); } }; const handleDelete = (id: string) => { if (confirm('確定要刪除這個項目嗎?')) { const newItems = structure.items.filter(i => i.id !== id); onUpdateStructure({ ...structure, items: newItems }); } }; const handleAdd = () => { const newItem: StructureItem = { id: `custom-${Date.now()}`, title: '新項目', summary: '', visualConcept: '', estimatedDuration: '1 min' }; onUpdateStructure({ ...structure, items: [...structure.items, newItem] }); setEditingId(newItem.id); setEditForm(newItem); setEditMode('auto'); }; const handleOptimizePrompt = async () => { if (!editForm) return; if (!modelSettings.googleApiKey) { alert("請輸入 Google API Key"); return; } setIsOptimizing(true); try { const refined = await optimizeVisualPrompt(editForm.summary, editForm.visualConcept, modelSettings.textModel, modelSettings.googleApiKey); setEditForm({ ...editForm, visualConcept: refined }); } catch (e) { console.error(e); } finally { setIsOptimizing(false); } }; // Helper to parse duration string "45 min" -> ["45", "min"] const parseDuration = (dur: string = '1 min') => { const match = dur.match(/(\d+)\s*(min|sec)/); if (match) return { val: match[1], unit: match[2] }; return { val: '1', unit: 'min' }; }; const updateDuration = (val: string, unit: string) => { if (!editForm) return; setEditForm({ ...editForm, estimatedDuration: `${val} ${unit}` }); }; return (
{/* Series Header */}

{structure.title}

{structure.logline}

{getHeaderIcon()} {type === ProjectType.NETFLIX_SERIES ? '季/集規劃 (Season Breakdown)' : '內容規劃 (Content Plan)'}

{structure.items.map((item, index) => { const isEditing = editingId === item.id; const isProducing = producingItemId === item.id; return (
{isEditing && editForm ? ( // EDIT MODE
setEditForm({...editForm, title: e.target.value})} className="glass-input w-full rounded-lg px-3 py-2 text-sm font-bold min-w-0" placeholder="例如:第一集:暗巷之戰" />
updateDuration(e.target.value, parseDuration(editForm.estimatedDuration).unit)} className="glass-input w-full rounded-l-lg px-2 py-2 text-sm text-center border-r-0" />