523 lines
18 KiB
TypeScript
523 lines
18 KiB
TypeScript
"use client";
|
|
import React, { useState, useEffect } from 'react';
|
|
import { motion } from 'framer-motion';
|
|
|
|
const VectorNoCode = () => {
|
|
const [step, setStep] = useState(0);
|
|
|
|
const nodes = [
|
|
{
|
|
icon: (
|
|
<svg className="w-6 h-6 text-purple-200" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
|
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
|
</svg>
|
|
),
|
|
label: "Input"
|
|
},
|
|
{
|
|
icon: (
|
|
<svg className="w-6 h-6 text-purple-200" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
|
d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
|
|
</svg>
|
|
),
|
|
label: "Process"
|
|
},
|
|
{
|
|
icon: (
|
|
<svg className="w-6 h-6 text-purple-200" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
|
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
|
</svg>
|
|
),
|
|
label: "Output"
|
|
}
|
|
];
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => {
|
|
setStep((prev) => (prev + 1) % 3);
|
|
}, 3000);
|
|
return () => clearTimeout(timer);
|
|
}, [step]);
|
|
|
|
return (
|
|
<motion.div className="w-full h-[400px] bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 relative overflow-hidden">
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
{nodes.map((node, i) => (
|
|
<motion.div
|
|
key={i}
|
|
className="absolute"
|
|
initial={{ x: -200 + i * 200 }}
|
|
>
|
|
{/* Node container */}
|
|
<motion.div
|
|
className="relative flex flex-col items-center"
|
|
animate={{
|
|
scale: step >= i ? 1.1 : 1,
|
|
opacity: step >= i ? 1 : 0.5,
|
|
}}
|
|
transition={{
|
|
duration: 0.5,
|
|
type: "spring",
|
|
}}
|
|
>
|
|
{/* Node */}
|
|
<motion.div
|
|
className="w-16 h-16 rounded-xl bg-gradient-to-br from-purple-500/30 to-blue-500/30
|
|
flex items-center justify-center backdrop-blur-sm"
|
|
animate={{
|
|
scale: step === i ? [1, 1.2, 1] : 1,
|
|
backgroundColor: step >= i ? "rgba(139, 92, 246, 0.4)" : "rgba(139, 92, 246, 0.2)"
|
|
}}
|
|
transition={{ duration: 0.5 }}
|
|
>
|
|
{node.icon}
|
|
</motion.div>
|
|
|
|
{/* Label */}
|
|
<motion.span
|
|
className="mt-2 text-sm text-purple-200"
|
|
animate={{
|
|
opacity: step >= i ? 1 : 0.5
|
|
}}
|
|
>
|
|
{node.label}
|
|
</motion.span>
|
|
</motion.div>
|
|
|
|
{/* Connection line */}
|
|
{i < 2 && (
|
|
<motion.div
|
|
className="absolute w-[200px] h-[2px] bg-gradient-to-r from-purple-500/30 to-blue-500/30 left-16 top-8"
|
|
initial={{ scaleX: 0 }}
|
|
animate={{
|
|
scaleX: step > i ? 1 : 0,
|
|
}}
|
|
transition={{
|
|
duration: 1,
|
|
ease: "easeInOut"
|
|
}}
|
|
>
|
|
{/* Moving dot */}
|
|
<motion.div
|
|
className="absolute h-4 w-4 bg-purple-500/50 rounded-full -translate-y-[6px]"
|
|
initial={{ x: 0, opacity: 0 }}
|
|
animate={{
|
|
x: step > i ? [0, 200] : 0,
|
|
opacity: step > i ? [1, 0] : 0,
|
|
scale: step > i ? [1, 1.5, 1] : 1
|
|
}}
|
|
transition={{
|
|
duration: 1,
|
|
ease: "easeInOut"
|
|
}}
|
|
/>
|
|
</motion.div>
|
|
)}
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
const VectorCreativeSuite = () => (
|
|
<motion.div className="w-full h-[400px] bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 relative overflow-hidden">
|
|
<div className="flex h-full gap-4">
|
|
{/* Editor Panel */}
|
|
<div className="flex-1 bg-black/20 rounded-xl p-4">
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<motion.div
|
|
className="w-3 h-3 rounded-full bg-red-500/70"
|
|
animate={{ opacity: [0.5, 1, 0.5] }}
|
|
transition={{ duration: 2, repeat: Infinity }}
|
|
/>
|
|
<motion.div
|
|
className="w-3 h-3 rounded-full bg-yellow-500/70"
|
|
animate={{ opacity: [0.5, 1, 0.5] }}
|
|
transition={{ duration: 2, delay: 0.3, repeat: Infinity }}
|
|
/>
|
|
<motion.div
|
|
className="w-3 h-3 rounded-full bg-green-500/70"
|
|
animate={{ opacity: [0.5, 1, 0.5] }}
|
|
transition={{ duration: 2, delay: 0.6, repeat: Infinity }}
|
|
/>
|
|
</div>
|
|
<motion.div
|
|
className="h-4 w-32 bg-purple-500/30 rounded-md mb-4"
|
|
animate={{ width: ["8rem", "12rem", "8rem"] }}
|
|
transition={{ duration: 3, repeat: Infinity }}
|
|
/>
|
|
<div className="space-y-2">
|
|
{[...Array(5)].map((_, i) => (
|
|
<motion.div
|
|
key={i}
|
|
className="h-3 bg-purple-500/20 rounded"
|
|
initial={{ width: "40%" }}
|
|
animate={{ width: ["40%", "100%", "40%"] }}
|
|
transition={{
|
|
duration: 4,
|
|
delay: i * 0.2,
|
|
repeat: Infinity,
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Preview Panel */}
|
|
<div className="flex-1 bg-black/20 rounded-xl p-4">
|
|
<motion.div
|
|
className="w-full h-full rounded-lg bg-gradient-to-br from-purple-500/20 to-blue-500/20 relative"
|
|
animate={{
|
|
boxShadow: [
|
|
"0 0 0 0 rgba(139, 92, 246, 0)",
|
|
"0 0 20px 2px rgba(139, 92, 246, 0.3)",
|
|
"0 0 0 0 rgba(139, 92, 246, 0)"
|
|
]
|
|
}}
|
|
transition={{ duration: 3, repeat: Infinity }}
|
|
>
|
|
<motion.div
|
|
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-16 h-16 border-4 border-purple-500/30 rounded-full border-t-transparent"
|
|
animate={{ rotate: 360 }}
|
|
transition={{ duration: 2, repeat: Infinity, ease: "linear" }}
|
|
/>
|
|
<motion.div
|
|
className="absolute bottom-4 left-1/2 -translate-x-1/2 h-2 w-24 bg-purple-500/30 rounded-full"
|
|
animate={{ width: ["6rem", "8rem", "6rem"] }}
|
|
transition={{ duration: 2, repeat: Infinity }}
|
|
/>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
|
|
const VectorCommunity = () => {
|
|
// Reduced number of points
|
|
const gridPoints = Array.from({ length: 15 }, (_, i) => ({
|
|
id: i,
|
|
x: (i % 5) * 100 + 80,
|
|
y: Math.floor(i / 5) * 100 + 80,
|
|
}));
|
|
|
|
return (
|
|
<motion.div className="w-full h-[400px] bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 relative overflow-hidden">
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
{/* Connection lines */}
|
|
<svg className="absolute w-full h-full">
|
|
{gridPoints.map((point, i) => (
|
|
gridPoints.slice(i + 1).map((target, j) => {
|
|
const distance = Math.sqrt(
|
|
Math.pow(point.x - target.x, 2) +
|
|
Math.pow(point.y - target.y, 2)
|
|
);
|
|
// Increased connection distance for wider coverage
|
|
if (distance < 240) { // Increased distance to maintain connections
|
|
return (
|
|
<motion.line
|
|
key={`${i}-${j}`}
|
|
x1={point.x}
|
|
y1={point.y}
|
|
x2={target.x}
|
|
y2={target.y}
|
|
stroke="rgba(139, 92, 246, 0.2)"
|
|
strokeWidth="1"
|
|
initial={{ opacity: 0 }}
|
|
animate={{
|
|
opacity: [0.2, 0.5, 0.2],
|
|
strokeWidth: [1, 2, 1]
|
|
}}
|
|
transition={{
|
|
duration: 2,
|
|
delay: (i + j) * 0.1,
|
|
repeat: Infinity
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
return null;
|
|
})
|
|
))}
|
|
</svg>
|
|
|
|
{/* User icons */}
|
|
{gridPoints.map((point, i) => (
|
|
<motion.div
|
|
key={i}
|
|
className="absolute"
|
|
style={{
|
|
left: point.x,
|
|
top: point.y,
|
|
transform: 'translate(-50%, -50%)'
|
|
}}
|
|
initial={{ scale: 0 }}
|
|
animate={{
|
|
scale: [1, 1.2, 1],
|
|
y: [0, -5, 0]
|
|
}}
|
|
transition={{
|
|
duration: 3,
|
|
delay: i * 0.1,
|
|
repeat: Infinity,
|
|
repeatType: "reverse"
|
|
}}
|
|
>
|
|
<div className="w-8 h-8 rounded-full bg-purple-500/30 flex items-center justify-center">
|
|
<svg
|
|
className="w-4 h-4 text-purple-200"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<motion.div
|
|
className="absolute -top-1 -right-1 w-2 h-2 rounded-full bg-green-400"
|
|
animate={{
|
|
scale: [1, 1.5, 1],
|
|
opacity: [0.5, 1, 0.5]
|
|
}}
|
|
transition={{
|
|
duration: 2,
|
|
delay: i * 0.2,
|
|
repeat: Infinity
|
|
}}
|
|
/>
|
|
</motion.div>
|
|
))}
|
|
|
|
{/* Central hub - made larger */}
|
|
<motion.div
|
|
className="absolute w-16 h-16 rounded-full bg-purple-600/40 flex items-center justify-center"
|
|
animate={{
|
|
scale: [1, 1.2, 1],
|
|
boxShadow: [
|
|
"0 0 0 0 rgba(139, 92, 246, 0.4)",
|
|
"0 0 20px 10px rgba(139, 92, 246, 0.2)",
|
|
"0 0 0 0 rgba(139, 92, 246, 0.4)"
|
|
]
|
|
}}
|
|
transition={{
|
|
duration: 3,
|
|
repeat: Infinity
|
|
}}
|
|
>
|
|
<svg
|
|
className="w-8 h-8 text-purple-200"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
|
/>
|
|
</svg>
|
|
</motion.div>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
const VectorMonetization = () => {
|
|
const subscriptionTiers = [
|
|
{ name: "Basic", price: "49", color: "from-blue-500/30 to-purple-500/30" },
|
|
{ name: "Pro", price: "199", color: "from-purple-500/30 to-pink-500/30" },
|
|
{ name: "Enterprise", price: "499", color: "from-pink-500/30 to-orange-500/30" }
|
|
];
|
|
|
|
return (
|
|
<motion.div className="w-full h-[400px] bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 relative overflow-hidden">
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<div className="relative w-full h-full flex items-center justify-center">
|
|
{/* Background rings */}
|
|
{[...Array(3)].map((_, i) => (
|
|
<motion.div
|
|
key={i}
|
|
className="absolute rounded-full border-2 border-purple-500/20"
|
|
style={{
|
|
width: `${(i + 1) * 150}px`,
|
|
height: `${(i + 1) * 150}px`,
|
|
}}
|
|
animate={{
|
|
rotate: 360,
|
|
scale: [1, 1.05, 1],
|
|
}}
|
|
transition={{
|
|
rotate: {
|
|
duration: 10 + i * 5,
|
|
repeat: Infinity,
|
|
ease: "linear",
|
|
},
|
|
scale: {
|
|
duration: 2,
|
|
repeat: Infinity,
|
|
delay: i * 0.3,
|
|
}
|
|
}}
|
|
/>
|
|
))}
|
|
|
|
{/* Subscription tiers */}
|
|
{subscriptionTiers.map((tier, i) => (
|
|
<motion.div
|
|
key={i}
|
|
className={`absolute bg-gradient-to-br ${tier.color} rounded-xl p-4 backdrop-blur-sm
|
|
flex flex-col items-center justify-center w-32 h-32`}
|
|
style={{
|
|
x: i * 140 - 140,
|
|
y: 0,
|
|
}}
|
|
animate={{
|
|
y: [0, -20, 0],
|
|
scale: [1, 1.05, 1],
|
|
}}
|
|
transition={{
|
|
duration: 3,
|
|
delay: i * 0.2,
|
|
repeat: Infinity,
|
|
}}
|
|
whileHover={{ scale: 1.1 }}
|
|
>
|
|
<motion.span
|
|
className="text-sm text-purple-200 mb-2"
|
|
animate={{ opacity: [0.5, 1, 0.5] }}
|
|
transition={{ duration: 2, repeat: Infinity }}
|
|
>
|
|
{tier.name}
|
|
</motion.span>
|
|
<motion.div
|
|
className="text-2xl font-bold text-white mb-1"
|
|
animate={{ scale: [1, 1.1, 1] }}
|
|
transition={{ duration: 2, repeat: Infinity }}
|
|
>
|
|
${tier.price}
|
|
</motion.div>
|
|
<motion.div
|
|
className="text-xs text-purple-200"
|
|
animate={{ opacity: [0.5, 1, 0.5] }}
|
|
transition={{ duration: 2, repeat: Infinity }}
|
|
>
|
|
per month
|
|
</motion.div>
|
|
</motion.div>
|
|
))}
|
|
|
|
{/* Floating elements */}
|
|
{[...Array(5)].map((_, i) => (
|
|
<motion.div
|
|
key={i}
|
|
className="absolute w-3 h-3"
|
|
style={{
|
|
x: Math.random() * 400 - 200,
|
|
y: Math.random() * 400 - 200,
|
|
}}
|
|
animate={{
|
|
y: [0, -100],
|
|
opacity: [0, 1, 0],
|
|
scale: [1, 1.5, 1],
|
|
}}
|
|
transition={{
|
|
duration: 2,
|
|
delay: i * 0.3,
|
|
repeat: Infinity,
|
|
}}
|
|
>
|
|
<div className="w-full h-full rounded-full bg-green-400/30" />
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
const defaultFeaturesData = [
|
|
{
|
|
title: "No-Code AI Builder",
|
|
description: "Design, test, and deploy AI agents effortlessly. Create powerful AI applications without any coding knowledge required.",
|
|
vector: <VectorNoCode />,
|
|
},
|
|
{
|
|
title: "Creative Suite",
|
|
description: "Access powerful forms, video editing, and content creation tools to bring your vision to life. Transform your ideas into polished, professional content.",
|
|
vector: <VectorCreativeSuite />,
|
|
},
|
|
{
|
|
title: "Community & Marketplace",
|
|
description: "Grow your audience on your own platform or join our marketplace to reach thousands of SMBs. Build and nurture your community while expanding your reach.",
|
|
vector: <VectorCommunity />,
|
|
},
|
|
{
|
|
title: "Subscription-Based Monetization",
|
|
description: "Generate recurring revenue with our seamless subscription integration. Turn your AI solutions into a sustainable business model.",
|
|
vector: <VectorMonetization />,
|
|
},
|
|
];
|
|
|
|
interface Feature {
|
|
title: string;
|
|
description: string;
|
|
vector: React.ReactNode;
|
|
}
|
|
|
|
export default function Features({ featuresData }: { featuresData?: Feature[] }) {
|
|
const dataToUse = featuresData || defaultFeaturesData;
|
|
|
|
return (
|
|
<div className="container mx-auto p-6 py-40 text-white">
|
|
<motion.h2
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.5 }}
|
|
viewport={{ once: true }}
|
|
className="text-4xl md:text-5xl text-center mb-16"
|
|
>
|
|
Everything You Need to Create, Manage, and Monetize Your AI Offerings
|
|
</motion.h2>
|
|
|
|
<div className="space-y-32"> {/* Increased spacing between features */}
|
|
{dataToUse.map((feature, index) => (
|
|
<motion.div
|
|
key={index}
|
|
initial={{ opacity: 0, x: index % 2 === 0 ? -100 : 100 }}
|
|
whileInView={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.5 }}
|
|
viewport={{ once: true }}
|
|
className={`flex flex-col md:flex-row items-center gap-8 ${index % 2 === 0 ? '' : 'md:flex-row-reverse'}`}
|
|
>
|
|
<div className={`flex-1 ${index % 2 === 0 ? 'md:pr-8' : 'md:pl-8'}`}>
|
|
<div className={`space-y-6 ${index % 2 === 0 ? '' : 'text-right'}`}>
|
|
<h3 className="text-3xl md:text-5xl">{feature.title}</h3>
|
|
<p className="text-gray-400 text-lg">{feature.description}</p>
|
|
<motion.button
|
|
className="bg-purple-600 px-6 py-3 rounded-full hover:bg-purple-700 transition-colors"
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
>
|
|
Learn More
|
|
</motion.button>
|
|
</div>
|
|
</div>
|
|
<div className="w-full md:w-1/2">
|
|
{feature.vector}
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|