video-flow-b/components/pages/create-video-workflow.tsx
2025-06-19 17:15:03 +08:00

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>
);
}