ado3-front-prototype/components/ProcessTracker.tsx

81 lines
3.2 KiB
TypeScript

import React from 'react';
import { ProcessingStep, VideoJob } from '../types';
import { Loader2, CheckCircle2, Music, Video, FileText, UploadCloud } from 'lucide-react';
interface ProcessTrackerProps {
job: VideoJob;
}
const steps = [
{ id: ProcessingStep.UPLOAD, label: "Upload", icon: UploadCloud },
{ id: ProcessingStep.LYRICS, label: "Lyrics", icon: FileText },
{ id: ProcessingStep.MUSIC, label: "Music", icon: Music },
{ id: ProcessingStep.VIDEO, label: "Video", icon: Video },
];
export const ProcessTracker: React.FC<ProcessTrackerProps> = ({ job }) => {
const getCurrentStepIndex = () => {
if (job.currentStep === ProcessingStep.DONE) return steps.length;
return steps.findIndex(s => s.id === job.currentStep);
};
const currentIndex = getCurrentStepIndex();
return (
<div className="w-full max-w-2xl mx-auto p-6 bg-glass backdrop-blur-xl border border-glassBorder rounded-2xl shadow-2xl">
<h3 className="text-xl font-serif font-bold text-center mb-6 text-white">
Creating Magic for {job.data.customer_name}
</h3>
<div className="relative flex justify-between items-center mb-8">
{/* Connecting Line */}
<div className="absolute top-1/2 left-0 w-full h-1 bg-gray-700 -z-10 transform -translate-y-1/2 rounded-full overflow-hidden">
<div
className="h-full bg-gradient-to-r from-blue-500 to-accent transition-all duration-700 ease-out"
style={{ width: `${(currentIndex / (steps.length - 1)) * 100}%` }}
/>
</div>
{steps.map((step, index) => {
const isActive = index === currentIndex;
const isCompleted = index < currentIndex;
const Icon = step.icon;
return (
<div key={step.id} className="flex flex-col items-center gap-2">
<div
className={`
w-12 h-12 rounded-full flex items-center justify-center border-2 transition-all duration-500
${isCompleted
? 'bg-accent border-accent text-white scale-110'
: isActive
? 'bg-gray-900 border-blue-400 text-blue-400 shadow-[0_0_15px_rgba(59,130,246,0.5)]'
: 'bg-gray-900 border-gray-600 text-gray-400'
}
`}
>
{isCompleted ? <CheckCircle2 size={24} /> : isActive ? <Loader2 size={24} className="animate-spin" /> : <Icon size={20} />}
</div>
<span className={`
text-xs uppercase tracking-wider transition-colors duration-300 text-center
${isActive ? 'text-blue-300 font-bold drop-shadow-[0_0_5px_rgba(147,197,253,0.5)]' : ''}
${isCompleted ? 'text-white font-semibold' : ''}
${!isActive && !isCompleted ? 'text-gray-400 font-medium' : ''}
`}>
{step.label}
</span>
</div>
);
})}
</div>
<div className="text-center h-8">
<p className="text-blue-200 animate-pulse text-sm font-medium">
{job.currentStep !== ProcessingStep.DONE ? `Current Step: ${job.currentStep}` : 'Finalizing output...'}
</p>
</div>
</div>
);
};