import React, { useState, useRef, useCallback } from 'react'; import { Upload, Film, Globe, X, Plus, Loader } from 'lucide-react'; import { Button } from '../ui'; import MultiLangPicker from './MultiLangPicker'; import { PRESETS } from '../utils/constants'; import './BatchAddDialog.css'; /** * BatchAddDialog — multi-file drop zone + shared settings for batch dubbing. * * Users drop N video files, pick languages + voice, then click "Add to Queue". * Each file is POSTed as a separate job to the batch endpoint. */ export default function BatchAddDialog({ open, onClose, profiles = [], onEnqueue, // async (files, settings) => void }) { const [files, setFiles] = useState([]); const [langs, setLangs] = useState([{ lang: 'Spanish', code: 'es' }]); const [voiceId, setVoiceId] = useState(''); const [preserveBg, setPreserveBg] = useState(true); const [submitting, setSubmitting] = useState(false); const fileInputRef = useRef(null); const handleDrop = useCallback((e) => { e.preventDefault(); const dropped = Array.from(e.dataTransfer.files).filter(f => f.type.startsWith('video/')); if (dropped.length) setFiles(prev => [...prev, ...dropped]); }, []); const removeFile = (idx) => { setFiles(prev => prev.filter((_, i) => i !== idx)); }; const handleSubmit = async () => { if (!files.length || !langs.length) return; setSubmitting(true); try { await onEnqueue?.(files, { langs, voiceId, preserveBg }); setFiles([]); onClose?.(); } finally { setSubmitting(false); } }; if (!open) return null; return (
e.stopPropagation()}>
Add Videos to Queue
{/* Drop zone */}
{ e.preventDefault(); e.currentTarget.classList.add('is-over'); }} onDragLeave={e => e.currentTarget.classList.remove('is-over')} onDrop={e => { e.currentTarget.classList.remove('is-over'); handleDrop(e); }} onClick={() => fileInputRef.current?.click()} > Drop video files here or click to browse MP4 · MOV · MKV · WEBM
{ const added = Array.from(e.target.files); if (added.length) setFiles(prev => [...prev, ...added]); e.target.value = ''; }} /> {/* File list */} {files.length > 0 && (
FILES ({files.length}) {files.map((f, i) => (
{f.name} {(f.size / 1024 / 1024).toFixed(1)} MB
))}
)} {/* Settings */}
TARGET LANGUAGES
VOICE
{files.length > 0 && langs.length > 0 ? `${files.length} video${files.length > 1 ? 's' : ''} × ${langs.length} lang${langs.length > 1 ? 's' : ''} = ${files.length * langs.length} job${files.length * langs.length > 1 ? 's' : ''}` : 'Select files and languages'}
); }