forked from 77media/video-flow
147 lines
5.4 KiB
TypeScript
147 lines
5.4 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from 'react';
|
|
import { Card, CardContent } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Progress } from '@/components/ui/progress';
|
|
import { Separator } from '@/components/ui/separator';
|
|
import {
|
|
ArrowLeft,
|
|
ArrowRight,
|
|
FileText,
|
|
Users,
|
|
Film,
|
|
Music,
|
|
Video,
|
|
CheckCircle,
|
|
} from 'lucide-react';
|
|
import { InputScriptStep } from '@/components/workflow/input-script-step';
|
|
import { GenerateChaptersStep } from '@/components/workflow/generate-chapters-step';
|
|
import { GenerateShotsStep } from '@/components/workflow/generate-shots-step';
|
|
import { AddMusicStep } from '@/components/workflow/add-music-step';
|
|
import { FinalCompositionStep } from '@/components/workflow/final-composition-step';
|
|
|
|
const steps = [
|
|
{ id: 1, name: 'Input Script', icon: FileText, description: 'Enter your script and settings' },
|
|
{ id: 2, name: 'Generate Chapters', icon: Users, description: 'AI splits script and assigns actors' },
|
|
{ id: 3, name: 'Generate Shots', icon: Film, description: 'Create storyboard and scenes' },
|
|
{ id: 4, name: 'Add Music', icon: Music, description: 'Background music and audio' },
|
|
{ id: 5, name: 'Final Video', icon: Video, description: 'Compose and export video' },
|
|
];
|
|
|
|
export function CreateVideoWorkflow() {
|
|
const [currentStep, setCurrentStep] = useState(1);
|
|
const [completedSteps, setCompletedSteps] = useState<number[]>([]);
|
|
|
|
const handleNext = () => {
|
|
if (currentStep < steps.length) {
|
|
setCompletedSteps([...completedSteps, currentStep]);
|
|
setCurrentStep(currentStep + 1);
|
|
}
|
|
};
|
|
|
|
const handlePrevious = () => {
|
|
if (currentStep > 1) {
|
|
setCurrentStep(currentStep - 1);
|
|
}
|
|
};
|
|
|
|
const handleStepClick = (stepId: number) => {
|
|
if (stepId <= currentStep || completedSteps.includes(stepId)) {
|
|
setCurrentStep(stepId);
|
|
}
|
|
};
|
|
|
|
const renderStepContent = () => {
|
|
switch (currentStep) {
|
|
case 1:
|
|
return <InputScriptStep onNext={handleNext} />;
|
|
case 2:
|
|
return <GenerateChaptersStep onNext={handleNext} onPrevious={handlePrevious} />;
|
|
case 3:
|
|
return <GenerateShotsStep onNext={handleNext} onPrevious={handlePrevious} />;
|
|
case 4:
|
|
return <AddMusicStep onNext={handleNext} onPrevious={handlePrevious} />;
|
|
case 5:
|
|
return <FinalCompositionStep onPrevious={handlePrevious} />;
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const progress = ((currentStep - 1) / (steps.length - 1)) * 100;
|
|
|
|
return (
|
|
<div className="max-w-6xl mx-auto space-y-8">
|
|
{/* Header */}
|
|
<div className="space-y-4">
|
|
<div className="flex items-center space-x-4">
|
|
<Button variant="ghost" size="sm" onClick={() => window.history.back()}>
|
|
<ArrowLeft className="mr-2 h-4 w-4" />
|
|
Back to Home
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<h1 className="text-3xl font-bold">Create AI Video</h1>
|
|
<p className="text-muted-foreground">
|
|
Follow these steps to create your AI-powered video. You can navigate back and forth to make changes.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Steps Navigation */}
|
|
<Card>
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between">
|
|
{steps.map((step, index) => (
|
|
<div key={step.id} className="flex items-center">
|
|
<div
|
|
className={`flex items-center space-x-2 cursor-pointer p-2 rounded-lg transition-colors ${
|
|
step.id === currentStep
|
|
? 'bg-primary/10 text-primary'
|
|
: completedSteps.includes(step.id)
|
|
? 'text-green-600 hover:bg-green-50 dark:hover:bg-green-950'
|
|
: step.id < currentStep
|
|
? 'text-muted-foreground hover:bg-muted'
|
|
: 'text-muted-foreground/50'
|
|
}`}
|
|
onClick={() => handleStepClick(step.id)}
|
|
>
|
|
<div className={`w-8 h-8 rounded-full flex items-center justify-center border-2 ${
|
|
step.id === currentStep
|
|
? 'border-primary bg-primary text-primary-foreground'
|
|
: completedSteps.includes(step.id)
|
|
? 'border-green-600 bg-green-600 text-white'
|
|
: step.id < currentStep
|
|
? 'border-muted-foreground bg-background'
|
|
: 'border-muted-foreground/30 bg-background'
|
|
}`}>
|
|
{completedSteps.includes(step.id) ? (
|
|
<CheckCircle className="h-4 w-4" />
|
|
) : (
|
|
<step.icon className="h-4 w-4" />
|
|
)}
|
|
</div>
|
|
<div className="hidden md:block">
|
|
<div className="font-medium text-sm">{step.name}</div>
|
|
<div className="text-xs text-muted-foreground">{step.description}</div>
|
|
</div>
|
|
</div>
|
|
{index < steps.length - 1 && (
|
|
<Separator orientation="horizontal" className="w-8 mx-2" />
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Step Content */}
|
|
<div>
|
|
{renderStepContent()}
|
|
</div>
|
|
</div>
|
|
);
|
|
} |