Spaces:
Running
Running
File size: 3,881 Bytes
ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 4ab93a6 ee0b401 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
import React from "react";
import { motion } from "framer-motion";
import {
FileSearch,
Cpu,
TableProperties,
CheckCircle2,
Loader2,
} from "lucide-react";
import { cn } from "@/lib/utils";
const steps = [
{ id: "upload", label: "Received", icon: FileSearch },
{ id: "analyze", label: "Analysis", icon: Cpu },
{ id: "extract", label: "Extraction", icon: TableProperties },
{ id: "complete", label: "Done", icon: CheckCircle2 },
];
export default function ProcessingStatus({ isProcessing, isComplete }) {
const getCurrentStep = () => {
if (isComplete) return 4;
if (isProcessing) return 2;
return 0;
};
const currentStep = getCurrentStep();
if (!isProcessing && !isComplete) return null;
return (
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
className="bg-white rounded-xl border border-slate-200 px-4 py-3"
>
<div className="flex items-center justify-between gap-2">
{steps.map((step, index) => {
const isActive = index + 1 === currentStep;
const isCompleted = index + 1 < currentStep || isComplete;
const Icon = step.icon;
return (
<React.Fragment key={step.id}>
<div className="flex items-center gap-2">
<motion.div
initial={false}
animate={{
scale: (isActive && !isComplete) ? 1.05 : 1,
backgroundColor: isCompleted
? "rgb(16 185 129)"
: (isActive && !isComplete)
? "rgb(99 102 241)"
: "rgb(241 245 249)",
}}
className={cn(
"h-8 w-8 rounded-lg flex items-center justify-center transition-colors",
(isCompleted || isActive) && "shadow-md"
)}
style={{
boxShadow: (isActive && !isComplete)
? "0 4px 8px -2px rgba(99, 102, 241, 0.3)"
: isCompleted
? "0 4px 8px -2px rgba(16, 185, 129, 0.3)"
: "none",
}}
>
{(isActive && !isComplete) ? (
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 1.5, repeat: Infinity, ease: "linear" }}
>
<Loader2 className="h-4 w-4 text-white" />
</motion.div>
) : isCompleted ? (
<CheckCircle2 className="h-4 w-4 text-white" />
) : (
<Icon className={cn("h-4 w-4 text-slate-400")} />
)}
</motion.div>
<span
className={cn(
"text-xs font-medium hidden sm:inline",
isActive ? "text-indigo-600" : isCompleted ? "text-emerald-600" : "text-slate-400"
)}
>
{step.label}
</span>
</div>
{index < steps.length - 1 && (
<div className="flex-1 h-0.5 mx-1 relative overflow-hidden rounded-full bg-slate-100">
<motion.div
initial={{ width: 0 }}
animate={{
width: isCompleted ? "100%" : isActive ? "50%" : "0%",
}}
transition={{ duration: 0.5 }}
className={cn(
"absolute inset-y-0 left-0",
isCompleted ? "bg-emerald-500" : "bg-indigo-500"
)}
/>
</div>
)}
</React.Fragment>
);
})}
</div>
</motion.div>
);
}
|