'use client';
import { useState, useCallback, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Upload, Download, X, Video, Film } from 'lucide-react';
import { useRouter } from 'next/navigation';
import dynamic from 'next/dynamic';
const VideoEditor = dynamic(
() => import('@distralabs/media-editor').then(mod => ({ default: mod.VideoEditor })),
{ ssr: false }
);
const videoTheme = {
'background.primary': '#0f172a',
'background.secondary': '#1e293b',
'background.tertiary': '#334155',
'text.primary': '#ffffff',
'text.secondary': '#cbd5e0',
'accent.primary': '#3b82f6',
'accent.secondary': '#06b6d4',
'accent.hover': '#60a5fa',
'border.default': '#334155',
'border.subtle': '#1e293b',
};
export default function VideoStudioPage() {
const router = useRouter();
const fileInputRef = useRef<HTMLInputElement>(null);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [showEditor, setShowEditor] = useState(false);
const [exportedVideo, setExportedVideo] = useState<string | null>(null);
const [showExportModal, setShowExportModal] = useState(false);
const [isExporting, setIsExporting] = useState(false);
const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file && file.type.startsWith('video/')) {
setSelectedFile(file);
setShowEditor(true);
}
};
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
const file = e.dataTransfer.files?.[0];
if (file && file.type.startsWith('video/')) {
setSelectedFile(file);
setShowEditor(true);
}
};
const handleExport = useCallback((result: any) => {
console.log('Video export result:', result);
setIsExporting(false);
if (result.videoUrl || result.base64) {
setExportedVideo(result.videoUrl || result.base64);
setShowExportModal(true);
setShowEditor(false);
}
}, []);
const handleClose = () => {
setShowEditor(false);
setSelectedFile(null);
};
const handleDownload = () => {
if (exportedVideo) {
const link = document.createElement('a');
link.href = exportedVideo;
link.download = `edited-video-${Date.now()}.mp4`;
link.click();
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-blue-950 to-slate-950">
{/* Upload Interface */}
<AnimatePresence>
{!showEditor && !showExportModal && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="flex flex-col items-center justify-center min-h-screen p-6"
>
<div className="text-center mb-8">
<div className="flex items-center justify-center gap-3 mb-4">
<Video className="w-12 h-12 text-blue-400" />
<h1 className="text-5xl font-black text-white">
Video Studio
</h1>
</div>
<p className="text-xl text-slate-300">
Professional video editing with powerful effects
</p>
</div>
<div
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
onClick={() => fileInputRef.current?.click()}
className="relative w-full max-w-2xl cursor-pointer group"
>
<div className="bg-white/10 backdrop-blur-md border-2 border-dashed border-white/30 rounded-3xl p-16 text-center hover:border-blue-400 transition-all">
<Film className="w-20 h-20 mx-auto mb-6 text-blue-400 group-hover:scale-110 transition-transform" />
<h3 className="text-2xl font-bold text-white mb-3">
Drop your video here
</h3>
<p className="text-slate-300 mb-6">
or click to browse your files
</p>
</div>
<input
ref={fileInputRef}
type="file"
accept="video/*"
onChange={handleFileSelect}
className="hidden"
/>
</div>
</motion.div>
)}
</AnimatePresence>
{/* Video Editor */}
{showEditor && selectedFile && (
<div className="fixed inset-0 z-40">
<VideoEditor
licenseKey="YOUR_LICENSE_KEY_HERE"
apiUrl="https://localhost:3030/social"
defaultVideo={selectedFile}
onClose={handleClose}
onExport={handleExport}
theme={videoTheme}
showThemeCreator={false}
/>
</div>
)}
{/* Export Modal */}
<AnimatePresence>
{showExportModal && exportedVideo && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/80"
onClick={() => setShowExportModal(false)}
>
<motion.div
initial={{ scale: 0.8, y: 20 }}
animate={{ scale: 1, y: 0 }}
exit={{ scale: 0.8, y: 20 }}
onClick={(e) => e.stopPropagation()}
className="bg-slate-800 rounded-2xl p-8 max-w-4xl w-full"
>
<div className="flex justify-between items-center mb-6">
<h2 className="text-3xl font-bold text-white">
Video Ready!
</h2>
<button
onClick={() => setShowExportModal(false)}
className="p-2 hover:bg-white/10 rounded-lg"
>
<X className="w-6 h-6 text-white" />
</button>
</div>
<div className="mb-6 rounded-xl overflow-hidden bg-slate-900">
<video
src={exportedVideo}
controls
className="w-full h-auto"
/>
</div>
<div className="flex gap-4">
<button
onClick={handleDownload}
className="flex-1 flex items-center justify-center gap-2 px-6 py-4 bg-gradient-to-r from-blue-500 to-cyan-500 rounded-xl text-white font-bold"
>
<Download className="w-5 h-5" />
Download Video
</button>
<button
onClick={() => {
setShowExportModal(false);
setSelectedFile(null);
setExportedVideo(null);
}}
className="flex-1 px-6 py-4 bg-white/10 rounded-xl text-white font-bold"
>
Create Another
</button>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
{/* Loading overlay during export */}
{isExporting && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/90">
<div className="text-center">
<div className="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" />
<p className="text-white text-xl font-bold">Exporting your video...</p>
<p className="text-slate-400 mt-2">This may take a moment</p>
</div>
</div>
)}
</div>
);
}