103 lines
4.5 KiB
TypeScript
103 lines
4.5 KiB
TypeScript
|
|
import { motion } from "framer-motion";
|
||
|
|
|
||
|
|
export const ProjectTimelineVector = () => {
|
||
|
|
const phases = [
|
||
|
|
{ name: "Planning", icon: "📋", color: "from-blue-500 to-blue-600", duration: "Week 1-2" },
|
||
|
|
{ name: "Design", icon: "🎨", color: "from-purple-500 to-purple-600", duration: "Week 3-4" },
|
||
|
|
{ name: "Development", icon: "⚡", color: "from-green-500 to-green-600", duration: "Week 5-12" },
|
||
|
|
{ name: "Testing", icon: "🔍", color: "from-orange-500 to-orange-600", duration: "Week 13-14" },
|
||
|
|
{ name: "Launch", icon: "🚀", color: "from-red-500 to-red-600", duration: "Week 15-16" }
|
||
|
|
];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="relative w-full h-80 bg-gradient-to-br from-gray-900/50 to-gray-800/50 rounded-2xl border border-white/10 p-8">
|
||
|
|
{/* Timeline Line */}
|
||
|
|
<div className="absolute left-8 top-16 bottom-16 w-1 bg-gradient-to-b from-accent to-purple-600"></div>
|
||
|
|
|
||
|
|
{/* Project Phases */}
|
||
|
|
<div className="space-y-8 ml-12">
|
||
|
|
{phases.map((phase, index) => (
|
||
|
|
<motion.div
|
||
|
|
key={phase.name}
|
||
|
|
initial={{ opacity: 0, x: -30 }}
|
||
|
|
animate={{ opacity: 1, x: 0 }}
|
||
|
|
transition={{ duration: 0.6, delay: index * 0.2 }}
|
||
|
|
className="relative flex items-center space-x-4"
|
||
|
|
>
|
||
|
|
{/* Timeline Dot */}
|
||
|
|
<motion.div
|
||
|
|
initial={{ scale: 0 }}
|
||
|
|
animate={{ scale: 1 }}
|
||
|
|
transition={{ duration: 0.4, delay: index * 0.2 + 0.3 }}
|
||
|
|
className={`absolute -left-16 w-4 h-4 bg-gradient-to-br ${phase.color} rounded-full border-2 border-white shadow-lg`}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{/* Phase Card */}
|
||
|
|
<motion.div
|
||
|
|
whileHover={{ scale: 1.02, y: -2 }}
|
||
|
|
className="flex-1 bg-white/5 border border-white/10 rounded-lg p-4 backdrop-blur-sm hover:bg-white/10 transition-all duration-300"
|
||
|
|
>
|
||
|
|
<div className="flex items-center justify-between">
|
||
|
|
<div className="flex items-center space-x-3">
|
||
|
|
<span className="text-2xl">{phase.icon}</span>
|
||
|
|
<div>
|
||
|
|
<h3 className="text-white font-semibold font-manrope">{phase.name}</h3>
|
||
|
|
<p className="text-white/60 text-sm font-manrope">{phase.duration}</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Progress Indicator */}
|
||
|
|
<motion.div
|
||
|
|
initial={{ width: 0 }}
|
||
|
|
animate={{ width: "100%" }}
|
||
|
|
transition={{ duration: 1, delay: index * 0.3 + 1 }}
|
||
|
|
className="w-16 h-2 bg-gray-700 rounded-full overflow-hidden"
|
||
|
|
>
|
||
|
|
<motion.div
|
||
|
|
initial={{ width: 0 }}
|
||
|
|
animate={{ width: `${(index + 1) * 20}%` }}
|
||
|
|
transition={{ duration: 1, delay: index * 0.3 + 1.5 }}
|
||
|
|
className={`h-full bg-gradient-to-r ${phase.color} rounded-full`}
|
||
|
|
/>
|
||
|
|
</motion.div>
|
||
|
|
</div>
|
||
|
|
</motion.div>
|
||
|
|
|
||
|
|
{/* Connecting Arrow */}
|
||
|
|
{index < phases.length - 1 && (
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0, scale: 0 }}
|
||
|
|
animate={{ opacity: 1, scale: 1 }}
|
||
|
|
transition={{ duration: 0.4, delay: index * 0.2 + 0.8 }}
|
||
|
|
className="absolute -bottom-4 left-8 text-white/40"
|
||
|
|
>
|
||
|
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 14l-7 7m0 0l-7-7m7 7V3" />
|
||
|
|
</svg>
|
||
|
|
</motion.div>
|
||
|
|
)}
|
||
|
|
</motion.div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Success Metrics */}
|
||
|
|
<motion.div
|
||
|
|
initial={{ opacity: 0, y: 20 }}
|
||
|
|
animate={{ opacity: 1, y: 0 }}
|
||
|
|
transition={{ duration: 0.8, delay: 2 }}
|
||
|
|
className="absolute bottom-4 right-4 flex space-x-4"
|
||
|
|
>
|
||
|
|
{[
|
||
|
|
{ label: "On Time", value: "95%", color: "text-green-400" },
|
||
|
|
{ label: "Quality", value: "5★", color: "text-yellow-400" },
|
||
|
|
{ label: "Satisfaction", value: "98%", color: "text-blue-400" }
|
||
|
|
].map((metric, index) => (
|
||
|
|
<div key={metric.label} className="text-center">
|
||
|
|
<div className={`text-lg font-bold ${metric.color} font-manrope`}>{metric.value}</div>
|
||
|
|
<div className="text-white/60 text-xs font-manrope">{metric.label}</div>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</motion.div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|