First commit
This commit is contained in:
429
components/views/Home/Features.tsx
Normal file
429
components/views/Home/Features.tsx
Normal file
@@ -0,0 +1,429 @@
|
||||
'use client';
|
||||
import { useScrollAnimation } from '@/hooks/useScrollAnimation';
|
||||
import {
|
||||
MessageSquare,
|
||||
Brain,
|
||||
Shield,
|
||||
BarChart3,
|
||||
Bell,
|
||||
Lock,
|
||||
Sparkles,
|
||||
Link,
|
||||
Zap,
|
||||
Check,
|
||||
TrendingUp
|
||||
} from 'lucide-react';
|
||||
|
||||
// Feature Card Component
|
||||
interface FeatureCardProps {
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ElementType;
|
||||
gradient: string;
|
||||
size?: 'normal' | 'large' | 'wide';
|
||||
children?: React.ReactNode;
|
||||
delay?: number;
|
||||
}
|
||||
|
||||
function FeatureCard({
|
||||
title,
|
||||
description,
|
||||
icon: Icon,
|
||||
gradient,
|
||||
size = 'normal',
|
||||
children,
|
||||
delay = 0
|
||||
}: FeatureCardProps) {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({ threshold: 0.2 });
|
||||
|
||||
const sizeClasses = {
|
||||
normal: 'md:col-span-1 aspect-square',
|
||||
large: 'md:col-span-2 md:row-span-2',
|
||||
wide: 'md:col-span-2',
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={`relative group ${sizeClasses[size]} rounded-3xl overflow-hidden cursor-pointer hover-lift`}
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? 'translateY(0)' : 'translateY(30px)',
|
||||
transition: `all 0.6s ease-out ${delay}s`,
|
||||
}}
|
||||
>
|
||||
<div className={`absolute inset-0 ${gradient} backdrop-blur-xl`} />
|
||||
<div className="absolute inset-0 bg-white/40 dark:bg-slate-900/40 backdrop-blur-xl" />
|
||||
<div className="absolute inset-0 border border-slate-200/50 dark:border-slate-700/50 rounded-3xl group-hover:border-blue-500/30 dark:group-hover:border-blue-400/30 transition-colors duration-300" />
|
||||
|
||||
<div className="relative h-full p-6 md:p-8 flex flex-col">
|
||||
{/* Icon */}
|
||||
<div className="mb-4">
|
||||
<div className="relative inline-flex p-3 rounded-2xl bg-gradient-to-br from-white/50 to-white/20 dark:from-slate-800/50 dark:to-slate-800/20 shadow-lg group-hover:shadow-xl transition-shadow duration-300">
|
||||
<Icon className="w-8 h-8 text-blue-600 dark:text-blue-400" />
|
||||
<div className="absolute inset-0 bg-blue-500/20 blur-xl rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<h3 className="text-xl md:text-2xl font-bold text-slate-800 dark:text-slate-200 mb-3">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-slate-600 dark:text-slate-400 text-sm md:text-base leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{/* Custom Content */}
|
||||
{children && (
|
||||
<div className="mt-auto pt-4">
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Hover Glow */}
|
||||
<div className="absolute -inset-px bg-gradient-to-r from-blue-500/0 via-violet-500/0 to-teal-500/0 group-hover:from-blue-500/20 group-hover:via-violet-500/20 group-hover:to-teal-500/20 rounded-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 blur-xl" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Animated Chat Messages
|
||||
function ChatAnimation() {
|
||||
const messages = [
|
||||
{ text: "What's the liability cap?", isUser: true },
|
||||
{ text: "The liability cap is $5M per Section 8.3", isUser: false },
|
||||
{ text: "When does this contract expire?", isUser: true },
|
||||
{ text: "December 31, 2024 - 45 days remaining", isUser: false },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-3">
|
||||
{messages.map((msg, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`flex ${msg.isUser ? 'justify-end' : 'justify-start'}`}
|
||||
style={{
|
||||
animation: `slide-up 0.4s ease-out forwards`,
|
||||
animationDelay: `${i * 0.8 + 1}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`max-w-[85%] px-4 py-2.5 rounded-2xl text-sm ${
|
||||
msg.isUser
|
||||
? 'bg-blue-600 text-white rounded-tr-sm'
|
||||
: 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm'
|
||||
}`}
|
||||
>
|
||||
{msg.text}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{/* Typing Indicator */}
|
||||
<div
|
||||
className="flex justify-start"
|
||||
style={{
|
||||
animation: `fade-in 0.3s ease-out forwards`,
|
||||
animationDelay: '4.5s',
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<div className="bg-slate-100 dark:bg-slate-800 rounded-2xl rounded-tl-sm px-4 py-3">
|
||||
<div className="flex gap-1">
|
||||
<span className="w-2 h-2 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: '0s' }} />
|
||||
<span className="w-2 h-2 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }} />
|
||||
<span className="w-2 h-2 bg-slate-400 rounded-full animate-bounce" style={{ animationDelay: '0.4s' }} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Document Extraction Animation
|
||||
function ExtractionAnimation() {
|
||||
const fields = [
|
||||
{ label: 'Contract Type', value: 'Service Agreement', status: 'done' },
|
||||
{ label: 'Parties', value: '3 identified', status: 'done' },
|
||||
{ label: 'Effective Date', value: 'Jan 1, 2024', status: 'done' },
|
||||
{ label: 'Term', value: '24 months', status: 'processing' },
|
||||
{ label: 'Value', value: 'Analyzing...', status: 'pending' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-2">
|
||||
{fields.map((field, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center justify-between p-3 rounded-xl bg-white/50 dark:bg-slate-800/50"
|
||||
style={{
|
||||
animation: `slide-up 0.4s ease-out forwards`,
|
||||
animationDelay: `${i * 0.3 + 0.5}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<span className="text-xs text-slate-500 dark:text-slate-400">{field.label}</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">{field.value}</span>
|
||||
{field.status === 'done' && <Check className="w-4 h-4 text-emerald-500" />}
|
||||
{field.status === 'processing' && (
|
||||
<div className="w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
|
||||
)}
|
||||
{field.status === 'pending' && (
|
||||
<div className="w-4 h-4 rounded-full bg-slate-300 dark:bg-slate-600" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Blockchain Animation
|
||||
function BlockchainAnimation() {
|
||||
return (
|
||||
<div className="mt-6 relative h-32">
|
||||
{/* Nodes */}
|
||||
{[0, 1, 2, 3].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute w-10 h-10 rounded-full bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center shadow-lg"
|
||||
style={{
|
||||
left: `${i * 25}%`,
|
||||
top: i % 2 === 0 ? '20%' : '50%',
|
||||
animation: `float 3s ease-in-out infinite`,
|
||||
animationDelay: `${i * 0.3}s`,
|
||||
}}
|
||||
>
|
||||
<Link className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Connection Lines */}
|
||||
<svg className="absolute inset-0 w-full h-full" style={{ zIndex: -1 }}>
|
||||
<defs>
|
||||
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stopColor="#8b5cf6" stopOpacity="0.5" />
|
||||
<stop offset="100%" stopColor="#a855f7" stopOpacity="0.5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
{[0, 1, 2].map((i) => (
|
||||
<line
|
||||
key={i}
|
||||
x1={`${i * 25 + 12}%`}
|
||||
y1={i % 2 === 0 ? '35%' : '65%'}
|
||||
x2={`${(i + 1) * 25 + 12}%`}
|
||||
y2={i % 2 === 0 ? '65%' : '35%'}
|
||||
stroke="url(#lineGradient)"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="5,5"
|
||||
className="animate-pulse"
|
||||
style={{ animationDelay: `${i * 0.2}s` }}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
|
||||
{/* Transaction Hash */}
|
||||
<div
|
||||
className="absolute bottom-0 left-1/2 -translate-x-1/2 px-3 py-1.5 rounded-full bg-violet-500/10 dark:bg-violet-500/20"
|
||||
style={{
|
||||
animation: `slide-up 0.5s ease-out forwards`,
|
||||
animationDelay: '1.5s',
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<span className="text-xs font-mono text-violet-600 dark:text-violet-400">
|
||||
0x7f8a...9b2c ✓
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Dashboard Mini Preview
|
||||
function DashboardPreview() {
|
||||
return (
|
||||
<div className="mt-6 grid grid-cols-3 gap-3">
|
||||
{/* Mini Chart */}
|
||||
<div className="col-span-2 glass rounded-xl p-3">
|
||||
<div className="flex items-end gap-1 h-16">
|
||||
{[30, 50, 40, 70, 55, 80, 65, 90, 75, 85].map((h, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex-1 bg-gradient-to-t from-blue-500 to-violet-500 rounded-t-sm"
|
||||
style={{ height: `${h}%` }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
<div className="space-y-2">
|
||||
<div className="glass rounded-lg p-2 text-center">
|
||||
<TrendingUp className="w-4 h-4 mx-auto text-emerald-500 mb-1" />
|
||||
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">+24%</span>
|
||||
</div>
|
||||
<div className="glass rounded-lg p-2 text-center">
|
||||
<Zap className="w-4 h-4 mx-auto text-amber-500 mb-1" />
|
||||
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">98.9%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Notification Animation
|
||||
function NotificationAnimation() {
|
||||
const notifications = [
|
||||
{ icon: Bell, text: 'Contract renewal in 7 days', color: 'text-amber-500' },
|
||||
{ icon: Check, text: 'Document verified', color: 'text-emerald-500' },
|
||||
{ icon: Sparkles, text: 'AI analysis complete', color: 'text-blue-500' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-2">
|
||||
{notifications.map((notif, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center gap-3 p-3 rounded-xl bg-white/50 dark:bg-slate-800/50"
|
||||
style={{
|
||||
animation: `slide-up 0.4s ease-out forwards`,
|
||||
animationDelay: `${i * 0.5 + 0.8}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<notif.icon className={`w-5 h-5 ${notif.color}`} />
|
||||
<span className="text-sm text-slate-700 dark:text-slate-300">{notif.text}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Security Animation
|
||||
function SecurityAnimation() {
|
||||
return (
|
||||
<div className="mt-6 flex flex-col items-center">
|
||||
<div className="relative">
|
||||
<div className="w-20 h-20 rounded-full bg-gradient-to-br from-emerald-500 to-green-600 flex items-center justify-center shadow-lg animate-pulse-glow">
|
||||
<Lock className="w-10 h-10 text-white" />
|
||||
</div>
|
||||
<div className="absolute -top-1 -right-1 w-6 h-6 rounded-full bg-emerald-500 flex items-center justify-center">
|
||||
<Check className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex gap-2 flex-wrap justify-center">
|
||||
{['AES-256', 'GDPR', 'ISO 27001'].map((badge, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="px-3 py-1 rounded-full text-xs font-medium bg-emerald-500/10 text-emerald-600 dark:text-emerald-400"
|
||||
>
|
||||
{badge}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Features() {
|
||||
const { ref: headerRef, isVisible: headerVisible } = useScrollAnimation<HTMLDivElement>();
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: 'AI-Powered Conversational Assistant',
|
||||
description: 'Ask any question about your contracts. Our AI understands legal context and responds in seconds with precise answers.',
|
||||
icon: MessageSquare,
|
||||
gradient: 'card-gradient-blue',
|
||||
size: 'large' as const,
|
||||
content: <ChatAnimation />,
|
||||
},
|
||||
{
|
||||
title: 'Intelligent Document Extraction',
|
||||
description: 'Advanced OCR + AI automatically extracts and structures all information from your PDF documents.',
|
||||
icon: Brain,
|
||||
gradient: 'card-gradient-teal',
|
||||
content: <ExtractionAnimation />,
|
||||
},
|
||||
{
|
||||
title: 'Blockchain Proof of Submission',
|
||||
description: 'Immutable timestamping on Polygon. Cryptographic proof that\'s legally valid and instantly verifiable.',
|
||||
icon: Shield,
|
||||
gradient: 'card-gradient-violet',
|
||||
content: <BlockchainAnimation />,
|
||||
},
|
||||
{
|
||||
title: 'Comprehensive Dashboard & Analytics',
|
||||
description: 'Visualize all contracts, renewal alerts, and detailed analytics in one beautiful interface.',
|
||||
icon: BarChart3,
|
||||
gradient: 'from-blue-500/10 via-violet-500/10 to-teal-500/10',
|
||||
size: 'wide' as const,
|
||||
content: <DashboardPreview />,
|
||||
},
|
||||
{
|
||||
title: 'Smart Notifications',
|
||||
description: 'Automated alerts for renewals, deadlines, and important contract events. Never miss a date.',
|
||||
icon: Bell,
|
||||
gradient: 'card-gradient-amber',
|
||||
content: <NotificationAnimation />,
|
||||
},
|
||||
{
|
||||
title: 'Enterprise Security',
|
||||
description: 'AES-256 encryption, GDPR compliant, secure hosting. Your data is protected at every level.',
|
||||
icon: Lock,
|
||||
gradient: 'card-gradient-emerald',
|
||||
content: <SecurityAnimation />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="features" className="relative py-24 px-4 sm:px-6 lg:px-8 overflow-hidden">
|
||||
{/* Background */}
|
||||
<div className="absolute inset-0 gradient-bg-mesh opacity-50" />
|
||||
|
||||
<div className="relative max-w-7xl mx-auto">
|
||||
{/* Section Header */}
|
||||
<div
|
||||
ref={headerRef}
|
||||
className="text-center mb-16"
|
||||
style={{
|
||||
opacity: headerVisible ? 1 : 0,
|
||||
transform: headerVisible ? 'translateY(0)' : 'translateY(30px)',
|
||||
transition: 'all 0.6s ease-out',
|
||||
}}
|
||||
>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-6">
|
||||
<Sparkles className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">Features</span>
|
||||
</div>
|
||||
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-slate-900 dark:text-white mb-4">
|
||||
Everything You Need to{' '}
|
||||
<span className="gradient-text">Manage Contracts</span>
|
||||
</h2>
|
||||
|
||||
<p className="text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
|
||||
Powerful AI combined with blockchain security. Built for professionals.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Bento Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{features.map((feature, index) => (
|
||||
<FeatureCard
|
||||
key={feature.title}
|
||||
title={feature.title}
|
||||
description={feature.description}
|
||||
icon={feature.icon}
|
||||
gradient={feature.gradient}
|
||||
size={feature.size}
|
||||
delay={index * 0.1}
|
||||
>
|
||||
{feature.content}
|
||||
</FeatureCard>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
247
components/views/Home/Footer.tsx
Normal file
247
components/views/Home/Footer.tsx
Normal file
@@ -0,0 +1,247 @@
|
||||
"use client";
|
||||
|
||||
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||
import { useTheme } from "@/hooks/useTheme";
|
||||
import {
|
||||
Sparkles,
|
||||
Github,
|
||||
Twitter,
|
||||
Linkedin,
|
||||
Mail,
|
||||
ArrowRight,
|
||||
Sun,
|
||||
Moon,
|
||||
} from "lucide-react";
|
||||
|
||||
// Footer Link Component
|
||||
function FooterLink({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
className="group flex items-center gap-1 text-sm text-slate-400 hover:text-white transition-colors duration-200"
|
||||
>
|
||||
<span>{children}</span>
|
||||
<ArrowRight className="w-3 h-3 opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200" />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
// Social Icon Component
|
||||
function SocialIcon({
|
||||
icon: Icon,
|
||||
href,
|
||||
label,
|
||||
}: {
|
||||
icon: React.ElementType;
|
||||
href: string;
|
||||
label: string;
|
||||
}) {
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={label}
|
||||
className="w-10 h-10 rounded-full bg-white/5 backdrop-blur-sm border border-white/10 flex items-center justify-center text-white/70 hover:bg-white/10 hover:text-white hover:scale-110 transition-all duration-200"
|
||||
>
|
||||
<Icon className="w-5 h-5" />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function Footer() {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLElement>({
|
||||
threshold: 0.1,
|
||||
});
|
||||
const { theme, toggleTheme, mounted } = useTheme();
|
||||
|
||||
const productLinks = [
|
||||
{ label: "Features", href: "#features" },
|
||||
{ label: "How It Works", href: "#how-it-works" },
|
||||
{ label: "Documentation", href: "#" },
|
||||
{ label: "API Access", href: "#" },
|
||||
{ label: "Updates", href: "#" },
|
||||
];
|
||||
|
||||
const resourceLinks = [
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Guides", href: "#" },
|
||||
{ label: "FAQ", href: "#" },
|
||||
{ label: "Support", href: "#" },
|
||||
{ label: "Contact", href: "#" },
|
||||
];
|
||||
|
||||
const legalLinks = [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Cookie Policy", href: "#" },
|
||||
{ label: "Security", href: "#" },
|
||||
{ label: "GDPR", href: "#" },
|
||||
];
|
||||
|
||||
return (
|
||||
<footer
|
||||
id="footer"
|
||||
ref={ref}
|
||||
className="relative bg-slate-900 dark:bg-slate-950 pt-16 pb-8 px-4 sm:px-6 lg:px-8"
|
||||
>
|
||||
{/* Top Gradient Line */}
|
||||
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-blue-500/50 to-transparent" />
|
||||
|
||||
<div
|
||||
className="max-w-7xl mx-auto"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
||||
transition: "all 0.6s ease-out",
|
||||
}}
|
||||
>
|
||||
{/* Main Footer Content */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-12 lg:gap-8 mb-12">
|
||||
{/* Brand Column */}
|
||||
<div className="lg:col-span-4">
|
||||
{/* Logo */}
|
||||
<a href="#" className="inline-flex items-center gap-2 group mb-4">
|
||||
<div className="relative">
|
||||
<Sparkles className="w-8 h-8 text-blue-500 transition-transform duration-300 group-hover:rotate-12" />
|
||||
<div className="absolute inset-0 bg-blue-500/30 blur-lg rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
</div>
|
||||
<span className="text-2xl font-bold gradient-text">
|
||||
Smart-Admin Copilot
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<p className="text-sm text-slate-400 mb-2">
|
||||
AI-powered contract intelligence
|
||||
</p>
|
||||
<p className="text-sm text-slate-500 leading-relaxed max-w-xs mb-6">
|
||||
Transform your contract management with cutting-edge AI and
|
||||
blockchain technology. Built for banking, financial services, and
|
||||
insurance.
|
||||
</p>
|
||||
|
||||
{/* Social Icons */}
|
||||
<div className="flex items-center gap-3">
|
||||
<SocialIcon
|
||||
icon={Github}
|
||||
href="https://github.com"
|
||||
label="GitHub"
|
||||
/>
|
||||
<SocialIcon
|
||||
icon={Twitter}
|
||||
href="https://twitter.com"
|
||||
label="Twitter"
|
||||
/>
|
||||
<SocialIcon
|
||||
icon={Linkedin}
|
||||
href="https://linkedin.com"
|
||||
label="LinkedIn"
|
||||
/>
|
||||
<SocialIcon
|
||||
icon={Mail}
|
||||
href="mailto:contact@smartadmin.com"
|
||||
label="Email"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Links */}
|
||||
<div className="lg:col-span-2 lg:col-start-6">
|
||||
<h3 className="text-white font-semibold mb-4">Product</h3>
|
||||
<ul className="space-y-3">
|
||||
{productLinks.map((link) => (
|
||||
<li key={link.label}>
|
||||
<FooterLink href={link.href}>{link.label}</FooterLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Resources Links */}
|
||||
<div className="lg:col-span-2">
|
||||
<h3 className="text-white font-semibold mb-4">Resources</h3>
|
||||
<ul className="space-y-3">
|
||||
{resourceLinks.map((link) => (
|
||||
<li key={link.label}>
|
||||
<FooterLink href={link.href}>{link.label}</FooterLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Legal Links */}
|
||||
<div className="lg:col-span-2">
|
||||
<h3 className="text-white font-semibold mb-4">Legal</h3>
|
||||
<ul className="space-y-3">
|
||||
{legalLinks.map((link) => (
|
||||
<li key={link.label}>
|
||||
<FooterLink href={link.href}>{link.label}</FooterLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="h-px bg-slate-800 mb-8" />
|
||||
|
||||
{/* Bottom Bar */}
|
||||
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
{/* Copyright */}
|
||||
<p className="text-sm text-slate-500">
|
||||
© 2024 Smart-Admin Copilot. All rights reserved.
|
||||
</p>
|
||||
|
||||
{/* Right Side */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Selector */}
|
||||
<button className="flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/5 border border-white/10 text-sm text-slate-400 hover:text-white hover:bg-white/10 transition-all duration-200">
|
||||
<span className="text-lg">🇬🇧</span>
|
||||
<span>English</span>
|
||||
</button>
|
||||
|
||||
{/* Theme Toggle */}
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/5 border border-white/10 text-sm text-slate-400 hover:text-white hover:bg-white/10 transition-all duration-200"
|
||||
aria-label="Toggle theme"
|
||||
>
|
||||
{mounted ? (
|
||||
theme === "light" ? (
|
||||
<>
|
||||
<Sun className="w-4 h-4" />
|
||||
<span>Light</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Moon className="w-4 h-4" />
|
||||
<span>Dark</span>
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
<Sun className="w-4 h-4" />
|
||||
<span>Theme</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Made With Love */}
|
||||
<div className="mt-8 text-center">
|
||||
<p className="text-xs text-slate-600">
|
||||
Made with <span className="text-red-500">♥</span> for your PFE
|
||||
project
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
589
components/views/Home/Hero.tsx
Normal file
589
components/views/Home/Hero.tsx
Normal file
@@ -0,0 +1,589 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState, useRef, useMemo } from "react";
|
||||
import {
|
||||
Sparkles,
|
||||
Rocket,
|
||||
Play,
|
||||
Lock,
|
||||
Check,
|
||||
Zap,
|
||||
Link,
|
||||
FileText,
|
||||
MessageSquare,
|
||||
Shield,
|
||||
TrendingUp,
|
||||
Bell,
|
||||
} from "lucide-react";
|
||||
|
||||
// Floating Orb Component
|
||||
function FloatingOrb({
|
||||
size,
|
||||
color,
|
||||
delay,
|
||||
duration,
|
||||
left,
|
||||
top,
|
||||
}: {
|
||||
size: number;
|
||||
color: string;
|
||||
delay: number;
|
||||
duration: number;
|
||||
left: string;
|
||||
top: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className="absolute rounded-full blur-3xl pointer-events-none"
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
backgroundColor: color,
|
||||
left,
|
||||
top,
|
||||
animation: `float-slow ${duration}s ease-in-out infinite`,
|
||||
animationDelay: `${delay}s`,
|
||||
opacity: 0.4,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Particle Component
|
||||
function Particle({
|
||||
delay,
|
||||
left,
|
||||
size,
|
||||
duration,
|
||||
}: {
|
||||
delay: number;
|
||||
left: string;
|
||||
size: number;
|
||||
duration: number;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className="absolute rounded-full bg-blue-500/30 dark:bg-blue-400/30 pointer-events-none"
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
left,
|
||||
bottom: "-10px",
|
||||
animation: `particle-float ${duration}s ease-in-out infinite`,
|
||||
animationDelay: `${delay}s`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Mockup Card Component
|
||||
function MockupCard({
|
||||
icon: Icon,
|
||||
title,
|
||||
value,
|
||||
trend,
|
||||
delay,
|
||||
}: {
|
||||
icon: React.ElementType;
|
||||
title: string;
|
||||
value: string;
|
||||
trend: string;
|
||||
delay: number;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className="glass rounded-xl p-4 hover-lift cursor-pointer"
|
||||
style={{
|
||||
animation: `slide-up 0.6s ease-out forwards`,
|
||||
animationDelay: `${delay}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="p-2 rounded-lg bg-blue-500/10 dark:bg-blue-500/20">
|
||||
<Icon className="w-5 h-5 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<span className="text-xs text-slate-500 dark:text-slate-400">
|
||||
{title}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-end justify-between">
|
||||
<span className="text-2xl font-bold text-slate-800 dark:text-slate-200">
|
||||
{value}
|
||||
</span>
|
||||
<span className="text-xs text-emerald-500 font-medium">{trend}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Chat Message Component
|
||||
function ChatMessage({
|
||||
message,
|
||||
isAI,
|
||||
delay,
|
||||
}: {
|
||||
message: string;
|
||||
isAI: boolean;
|
||||
delay: number;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={`flex ${isAI ? "justify-start" : "justify-end"} mb-3`}
|
||||
style={{
|
||||
animation: `slide-up 0.4s ease-out forwards`,
|
||||
animationDelay: `${delay}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`max-w-[80%] px-4 py-2 rounded-2xl text-sm ${
|
||||
isAI
|
||||
? "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm"
|
||||
: "bg-blue-600 text-white rounded-tr-sm"
|
||||
}`}
|
||||
>
|
||||
{message}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Hero() {
|
||||
const [isLoaded] = useState(true);
|
||||
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
|
||||
const heroRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const particles = useMemo(
|
||||
() => [
|
||||
{ left: "8%", size: 3, duration: 9 },
|
||||
{ left: "18%", size: 4, duration: 10 },
|
||||
{ left: "28%", size: 2, duration: 8 },
|
||||
{ left: "38%", size: 5, duration: 11 },
|
||||
{ left: "48%", size: 3, duration: 9 },
|
||||
{ left: "58%", size: 4, duration: 10 },
|
||||
{ left: "68%", size: 2, duration: 8 },
|
||||
{ left: "78%", size: 5, duration: 11 },
|
||||
{ left: "88%", size: 3, duration: 9 },
|
||||
{ left: "12%", size: 4, duration: 10 },
|
||||
{ left: "22%", size: 2, duration: 8 },
|
||||
{ left: "32%", size: 5, duration: 11 },
|
||||
{ left: "52%", size: 3, duration: 9 },
|
||||
{ left: "72%", size: 4, duration: 10 },
|
||||
{ left: "92%", size: 2, duration: 8 },
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!heroRef.current) return;
|
||||
const rect = heroRef.current.getBoundingClientRect();
|
||||
const x = (e.clientX - rect.left - rect.width / 2) / rect.width;
|
||||
const y = (e.clientY - rect.top - rect.height / 2) / rect.height;
|
||||
setMousePosition({ x: x * 10, y: y * 10 });
|
||||
};
|
||||
|
||||
const heroElement = heroRef.current;
|
||||
if (heroElement) {
|
||||
heroElement.addEventListener("mousemove", handleMouseMove);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (heroElement) {
|
||||
heroElement.removeEventListener("mousemove", handleMouseMove);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const trustBadges = [
|
||||
{ icon: Lock, label: "Bank-Level Security" },
|
||||
{ icon: Check, label: "GDPR Certified" },
|
||||
{ icon: Zap, label: "Real-Time AI" },
|
||||
{ icon: Link, label: "Blockchain Verified" },
|
||||
];
|
||||
|
||||
return (
|
||||
<section
|
||||
ref={heroRef}
|
||||
className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16 px-4 sm:px-6 lg:px-8"
|
||||
>
|
||||
{/* Background Layer 1 - Animated Gradient Mesh */}
|
||||
<div className="absolute inset-0 gradient-bg-mesh animate-gradient-shift" />
|
||||
|
||||
{/* Background Layer 2 - Grid Pattern */}
|
||||
<div
|
||||
className="absolute inset-0 grid-pattern"
|
||||
style={{
|
||||
maskImage:
|
||||
"radial-gradient(ellipse at center, black 0%, transparent 70%)",
|
||||
WebkitMaskImage:
|
||||
"radial-gradient(ellipse at center, black 0%, transparent 70%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Background Layer 3 - Floating Orbs */}
|
||||
<FloatingOrb
|
||||
size={200}
|
||||
color="rgba(59, 130, 246, 0.3)"
|
||||
delay={0}
|
||||
duration={8}
|
||||
left="10%"
|
||||
top="20%"
|
||||
/>
|
||||
<FloatingOrb
|
||||
size={150}
|
||||
color="rgba(139, 92, 246, 0.3)"
|
||||
delay={2}
|
||||
duration={10}
|
||||
left="70%"
|
||||
top="15%"
|
||||
/>
|
||||
<FloatingOrb
|
||||
size={180}
|
||||
color="rgba(20, 184, 166, 0.3)"
|
||||
delay={1}
|
||||
duration={9}
|
||||
left="80%"
|
||||
top="60%"
|
||||
/>
|
||||
<FloatingOrb
|
||||
size={120}
|
||||
color="rgba(59, 130, 246, 0.25)"
|
||||
delay={3}
|
||||
duration={7}
|
||||
left="15%"
|
||||
top="70%"
|
||||
/>
|
||||
<FloatingOrb
|
||||
size={100}
|
||||
color="rgba(139, 92, 246, 0.2)"
|
||||
delay={4}
|
||||
duration={11}
|
||||
left="50%"
|
||||
top="80%"
|
||||
/>
|
||||
|
||||
{/* Background Layer 4 - Spotlight Effect */}
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none opacity-30 dark:opacity-20"
|
||||
style={{
|
||||
background: `radial-gradient(600px circle at ${50 + mousePosition.x}% ${50 + mousePosition.y}%, rgba(59, 130, 246, 0.15), transparent 40%)`,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Particles */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
{particles.map((particle, i) => (
|
||||
<Particle
|
||||
key={`${particle.left}-${particle.size}-${i}`}
|
||||
delay={i * 0.5}
|
||||
left={particle.left}
|
||||
size={particle.size}
|
||||
duration={particle.duration}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="relative z-10 max-w-7xl mx-auto text-center">
|
||||
{/* Announcement Badge */}
|
||||
<div
|
||||
className={`inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-8 transition-all duration-700 ${
|
||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-4"
|
||||
}`}
|
||||
>
|
||||
<Sparkles className="w-4 h-4 text-blue-600 dark:text-blue-400 animate-spin-slow" />
|
||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
New: GPT-4 Turbo + Blockchain Integration
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Main Headline */}
|
||||
<h1
|
||||
className={`text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-black leading-[1.1] tracking-tight max-w-6xl mx-auto transition-all duration-700 delay-100 ${
|
||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
|
||||
}`}
|
||||
>
|
||||
<span className="block text-slate-900 dark:text-white">
|
||||
Transform Your Contracts
|
||||
</span>
|
||||
<span className="block mt-2 gradient-text">
|
||||
Into Actionable Intelligence
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
{/* Subheadline */}
|
||||
<p
|
||||
className={`mt-6 text-lg md:text-xl lg:text-2xl text-slate-600 dark:text-slate-400 max-w-3xl mx-auto leading-relaxed transition-all duration-700 delay-200 ${
|
||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
|
||||
}`}
|
||||
>
|
||||
AI-Powered contract analysis meets blockchain verification. The only
|
||||
platform that truly understands your banking and insurance documents.
|
||||
<span className="text-blue-600 dark:text-blue-400 font-medium">
|
||||
Secure, transparent, instant.
|
||||
</span>
|
||||
</p>
|
||||
|
||||
{/* CTA Buttons */}
|
||||
<div
|
||||
className={`flex flex-wrap items-center justify-center gap-4 mt-10 transition-all duration-700 delay-300 ${
|
||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
|
||||
}`}
|
||||
>
|
||||
{/* Primary CTA */}
|
||||
<button className="group relative px-8 py-4 text-base md:text-lg font-bold text-white btn-gradient rounded-2xl overflow-hidden">
|
||||
<span className="relative z-10 flex items-center gap-2">
|
||||
Start Free Trial
|
||||
<Rocket className="w-5 h-5 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
</span>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-500 via-violet-500 to-teal-500 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
<div className="absolute inset-0 animate-shimmer opacity-30" />
|
||||
</button>
|
||||
|
||||
{/* Secondary CTA */}
|
||||
<button className="group flex items-center gap-2 px-8 py-4 text-base md:text-lg font-semibold text-slate-900 dark:text-white bg-white/10 dark:bg-white/5 backdrop-blur-sm border border-white/20 rounded-2xl hover:bg-white/20 transition-all duration-300 hover:scale-105">
|
||||
<div className="p-2 rounded-full bg-blue-500/10 dark:bg-blue-500/20 group-hover:bg-blue-500/20 transition-colors">
|
||||
<Play className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
Watch Demo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Trust Indicators */}
|
||||
<div
|
||||
className={`flex flex-wrap items-center justify-center gap-3 mt-12 transition-all duration-700 delay-400 ${
|
||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 translate-y-8"
|
||||
}`}
|
||||
>
|
||||
{trustBadges.map((badge, index) => (
|
||||
<div
|
||||
key={badge.label}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full glass hover-lift cursor-default"
|
||||
style={{
|
||||
animation: isLoaded
|
||||
? `slide-up 0.5s ease-out forwards`
|
||||
: "none",
|
||||
animationDelay: `${0.5 + index * 0.1}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<badge.icon className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
{badge.label}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Hero Visual - Dashboard Mockup */}
|
||||
<div
|
||||
className={`mt-16 lg:mt-20 perspective-1000 transition-all duration-1000 delay-500 ${
|
||||
isLoaded ? "opacity-100 translate-y-0" : "opacity-0 translate-y-16"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="relative max-w-5xl mx-auto transform-3d"
|
||||
style={{
|
||||
transform: `rotateX(-5deg) rotateY(${mousePosition.x * 0.3}deg)`,
|
||||
transition: "transform 0.1s ease-out",
|
||||
}}
|
||||
>
|
||||
{/* Main Dashboard Container */}
|
||||
<div className="relative rounded-3xl overflow-hidden shadow-[0_60px_120px_rgba(0,0,0,0.25)] border border-slate-200/50 dark:border-slate-700/50">
|
||||
{/* Dashboard Header */}
|
||||
<div className="bg-slate-50 dark:bg-slate-900/90 backdrop-blur-xl px-6 py-4 border-b border-slate-200/50 dark:border-slate-700/50">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex gap-2">
|
||||
<div className="w-3 h-3 rounded-full bg-red-400" />
|
||||
<div className="w-3 h-3 rounded-full bg-amber-400" />
|
||||
<div className="w-3 h-3 rounded-full bg-emerald-400" />
|
||||
</div>
|
||||
<div className="h-6 w-px bg-slate-300 dark:bg-slate-700" />
|
||||
<span className="text-sm font-medium text-slate-600 dark:text-slate-400">
|
||||
Dashboard
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-blue-500 to-violet-500" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dashboard Content */}
|
||||
<div className="bg-white/80 dark:bg-slate-900/80 backdrop-blur-xl p-6 grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Left Column - Stats */}
|
||||
<div className="space-y-4">
|
||||
<MockupCard
|
||||
icon={FileText}
|
||||
title="Total Contracts"
|
||||
value="1,247"
|
||||
trend="+12%"
|
||||
delay={0.6}
|
||||
/>
|
||||
<MockupCard
|
||||
icon={Shield}
|
||||
title="Verified"
|
||||
value="98.5%"
|
||||
trend="+2.1%"
|
||||
delay={0.7}
|
||||
/>
|
||||
<MockupCard
|
||||
icon={TrendingUp}
|
||||
title="Processing"
|
||||
value="24ms"
|
||||
trend="-15%"
|
||||
delay={0.8}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Center Column - Chat Interface */}
|
||||
<div className="md:col-span-1 glass rounded-xl p-4 flex flex-col">
|
||||
<div className="flex items-center gap-2 mb-4 pb-3 border-b border-slate-200/50 dark:border-slate-700/50">
|
||||
<div className="p-2 rounded-lg bg-violet-500/10 dark:bg-violet-500/20">
|
||||
<MessageSquare className="w-4 h-4 text-violet-600 dark:text-violet-400" />
|
||||
</div>
|
||||
<span className="text-sm font-semibold text-slate-700 dark:text-slate-300">
|
||||
AI Assistant
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-1 space-y-1">
|
||||
<ChatMessage
|
||||
message="What are the key clauses in Contract #4521?"
|
||||
isAI={false}
|
||||
delay={0.9}
|
||||
/>
|
||||
<ChatMessage
|
||||
message="I've analyzed the contract. Key clauses include: Termination (Section 4.2), Liability Cap ($2M), and Governing Law (Delaware)."
|
||||
isAI={true}
|
||||
delay={1.1}
|
||||
/>
|
||||
<ChatMessage
|
||||
message="When does it expire?"
|
||||
isAI={false}
|
||||
delay={1.3}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column - Notifications */}
|
||||
<div className="space-y-4">
|
||||
<div
|
||||
className="glass rounded-xl p-4"
|
||||
style={{
|
||||
animation: `slide-up 0.6s ease-out forwards`,
|
||||
animationDelay: `1s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Bell className="w-4 h-4 text-amber-500" />
|
||||
<span className="text-sm font-semibold text-slate-700 dark:text-slate-300">
|
||||
Recent Activity
|
||||
</span>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{[
|
||||
{
|
||||
text: "Contract #4521 verified",
|
||||
time: "2m ago",
|
||||
color: "bg-emerald-500",
|
||||
},
|
||||
{
|
||||
text: "New AI analysis complete",
|
||||
time: "5m ago",
|
||||
color: "bg-blue-500",
|
||||
},
|
||||
{
|
||||
text: "Blockchain timestamp added",
|
||||
time: "12m ago",
|
||||
color: "bg-violet-500",
|
||||
},
|
||||
].map((item, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center gap-2 text-xs"
|
||||
>
|
||||
<div
|
||||
className={`w-2 h-2 rounded-full ${item.color}`}
|
||||
/>
|
||||
<span className="text-slate-600 dark:text-slate-400 flex-1">
|
||||
{item.text}
|
||||
</span>
|
||||
<span className="text-slate-400 dark:text-slate-500">
|
||||
{item.time}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mini Chart */}
|
||||
<div
|
||||
className="glass rounded-xl p-4"
|
||||
style={{
|
||||
animation: `slide-up 0.6s ease-out forwards`,
|
||||
animationDelay: `1.2s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
>
|
||||
<span className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3 block">
|
||||
Processing Volume
|
||||
</span>
|
||||
<div className="flex items-end gap-1 h-16">
|
||||
{[40, 65, 45, 80, 55, 90, 70, 85, 60, 95, 75, 88].map(
|
||||
(height, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex-1 bg-gradient-to-t from-blue-500 to-violet-500 rounded-t-sm transition-all duration-300 hover:opacity-80"
|
||||
style={{
|
||||
height: `${height}%`,
|
||||
animation: `slide-up 0.4s ease-out forwards`,
|
||||
animationDelay: `${1.3 + i * 0.05}s`,
|
||||
opacity: 0,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Gradient Overlay */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-20 bg-gradient-to-t from-white/50 dark:from-slate-900/50 to-transparent pointer-events-none" />
|
||||
</div>
|
||||
|
||||
{/* Floating Elements Around Mockup */}
|
||||
<div
|
||||
className="absolute -top-4 -right-4 glass rounded-lg px-3 py-2 shadow-lg animate-float"
|
||||
style={{ animationDelay: "0.5s" }}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Check className="w-4 h-4 text-emerald-500" />
|
||||
<span className="text-xs font-medium text-slate-700 dark:text-slate-300">
|
||||
Contract Verified!
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute -bottom-4 -left-4 glass rounded-lg px-3 py-2 shadow-lg animate-float-delayed">
|
||||
<div className="flex items-center gap-2">
|
||||
<FileText className="w-4 h-4 text-blue-500" />
|
||||
<span className="text-xs font-medium text-slate-700 dark:text-slate-300">
|
||||
+1 Document
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute top-1/2 -right-8 glass rounded-full p-3 shadow-lg animate-bounce-subtle">
|
||||
<Lock className="w-5 h-5 text-violet-500" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
594
components/views/Home/HowItWorks.tsx
Normal file
594
components/views/Home/HowItWorks.tsx
Normal file
@@ -0,0 +1,594 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
Upload,
|
||||
Cpu,
|
||||
MessageSquare,
|
||||
Shield,
|
||||
FileText,
|
||||
Check,
|
||||
Sparkles,
|
||||
Zap,
|
||||
Link,
|
||||
Target,
|
||||
} from "lucide-react";
|
||||
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||
|
||||
// Step Card Component
|
||||
interface StepCardProps {
|
||||
number: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ElementType;
|
||||
gradient: string;
|
||||
delay: number;
|
||||
isLast?: boolean;
|
||||
}
|
||||
|
||||
function StepCard({
|
||||
number,
|
||||
title,
|
||||
description,
|
||||
icon: Icon,
|
||||
gradient,
|
||||
delay,
|
||||
isLast = false,
|
||||
}: StepCardProps) {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.3,
|
||||
});
|
||||
|
||||
return (
|
||||
<div ref={ref} className="relative flex-1">
|
||||
{/* Connector Line - Desktop */}
|
||||
{!isLast && (
|
||||
<>
|
||||
{/* Horizontal connector for desktop */}
|
||||
<div className="hidden md:block absolute top-12 left-[60%] w-[80%] h-0.5">
|
||||
<div className="relative w-full h-full overflow-hidden">
|
||||
<div
|
||||
className="absolute inset-0 bg-gradient-to-r from-blue-500 via-violet-500 to-teal-500"
|
||||
style={{
|
||||
transform: isVisible ? "translateX(0)" : "translateX(-100%)",
|
||||
transition: `transform 1s ease-out ${delay + 0.3}s`,
|
||||
}}
|
||||
/>
|
||||
{/* Animated dots */}
|
||||
<div
|
||||
className="absolute top-1/2 -translate-y-1/2 w-2 h-2 rounded-full bg-violet-500"
|
||||
style={{
|
||||
animationName: isVisible ? "move-right" : "none",
|
||||
animationDuration: isVisible ? "2s" : undefined,
|
||||
animationTimingFunction: isVisible ? "linear" : undefined,
|
||||
animationIterationCount: isVisible ? "infinite" : undefined,
|
||||
animationFillMode: "forwards",
|
||||
animationDelay: isVisible ? `${delay + 0.5}s` : undefined,
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transition: `opacity 0.3s ease-out ${delay + 0.5}s`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Vertical connector for mobile */}
|
||||
<div className="md:hidden absolute top-20 left-8 w-0.5 h-[calc(100%-40px)]">
|
||||
<div
|
||||
className="w-full h-full bg-gradient-to-b from-blue-500 via-violet-500 to-teal-500"
|
||||
style={{
|
||||
transform: isVisible ? "scaleY(1)" : "scaleY(0)",
|
||||
transformOrigin: "top",
|
||||
transition: `transform 1s ease-out ${delay + 0.3}s`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Card */}
|
||||
<div
|
||||
className="relative"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
||||
transition: `all 0.6s ease-out ${delay}s`,
|
||||
}}
|
||||
>
|
||||
{/* Icon with Number */}
|
||||
<div className="relative inline-block mb-6">
|
||||
<div
|
||||
className={`w-24 h-24 rounded-full ${gradient} flex items-center justify-center shadow-lg`}
|
||||
>
|
||||
<Icon className="w-10 h-10 text-white" />
|
||||
</div>
|
||||
|
||||
{/* Number Badge */}
|
||||
<div
|
||||
className="absolute -top-2 -right-2 w-10 h-10 rounded-full bg-slate-800 dark:bg-slate-700 flex items-center justify-center shadow-lg"
|
||||
style={{
|
||||
animationName: isVisible ? "bounce-subtle" : "none",
|
||||
animationDuration: isVisible ? "0.5s" : undefined,
|
||||
animationTimingFunction: isVisible ? "ease-out" : undefined,
|
||||
animationDelay: `${delay + 0.2}s`,
|
||||
}}
|
||||
>
|
||||
<span className="text-lg font-bold text-white">{number}</span>
|
||||
</div>
|
||||
|
||||
{/* Glow Effect */}
|
||||
<div
|
||||
className={`absolute inset-0 rounded-full ${gradient} blur-xl opacity-50`}
|
||||
style={{
|
||||
animationName: isVisible ? "pulse-glow" : "none",
|
||||
animationDuration: isVisible ? "3s" : undefined,
|
||||
animationTimingFunction: isVisible ? "ease-in-out" : undefined,
|
||||
animationIterationCount: isVisible ? "infinite" : undefined,
|
||||
animationFillMode: "forwards",
|
||||
animationDelay: isVisible ? `${delay + 0.5}s` : undefined,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="glass rounded-2xl p-6 hover-lift">
|
||||
<h3 className="text-xl font-bold text-slate-800 dark:text-slate-200 mb-2">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Upload Animation
|
||||
function UploadAnimation() {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.3,
|
||||
});
|
||||
|
||||
return (
|
||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
||||
{/* Drop Zone */}
|
||||
<div
|
||||
className="border-2 border-dashed border-blue-300 dark:border-blue-700 rounded-lg p-6 text-center"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "scale(1)" : "scale(0.95)",
|
||||
transition: "all 0.5s ease-out 0.3s",
|
||||
}}
|
||||
>
|
||||
<Upload
|
||||
className="w-8 h-8 mx-auto text-blue-500 mb-2"
|
||||
style={{
|
||||
animation: isVisible
|
||||
? "bounce-subtle 2s ease-in-out infinite"
|
||||
: "none",
|
||||
}}
|
||||
/>
|
||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
||||
Drop files here or click to browse
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* File List */}
|
||||
<div className="mt-4 space-y-2">
|
||||
{[
|
||||
{ name: "contract_v2.pdf", size: "2.4 MB", progress: 100 },
|
||||
{ name: "agreement_scan.jpg", size: "1.8 MB", progress: 75 },
|
||||
].map((file, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center gap-3 p-2 rounded-lg bg-white/50 dark:bg-slate-800/50"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateX(0)" : "translateX(-20px)",
|
||||
transition: `all 0.4s ease-out ${0.5 + i * 0.2}s`,
|
||||
}}
|
||||
>
|
||||
<FileText className="w-5 h-5 text-blue-500" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium text-slate-700 dark:text-slate-300 truncate">
|
||||
{file.name}
|
||||
</p>
|
||||
<div className="h-1.5 bg-slate-200 dark:bg-slate-700 rounded-full mt-1 overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-gradient-to-r from-blue-500 to-violet-500 rounded-full transition-all duration-1000"
|
||||
style={{
|
||||
width: isVisible ? `${file.progress}%` : "0%",
|
||||
transitionDelay: `${0.8 + i * 0.2}s`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-xs text-slate-500">{file.size}</span>
|
||||
{file.progress === 100 && (
|
||||
<Check className="w-4 h-4 text-emerald-500" />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Format Badges */}
|
||||
<div className="mt-4 flex gap-2 justify-center">
|
||||
{["PDF", "JPG", "PNG"].map((format, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="px-2 py-1 text-xs font-medium rounded-full bg-blue-500/10 text-blue-600 dark:text-blue-400"
|
||||
>
|
||||
{format}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// AI Analysis Animation
|
||||
function AIAnalysisAnimation() {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.3,
|
||||
});
|
||||
|
||||
const scanHeights = useMemo(
|
||||
() => [
|
||||
22, 38, 55, 40, 62, 30, 70, 45, 58, 35, 66, 28, 52, 48, 60, 33, 57, 41,
|
||||
64, 36,
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
const analysisPoints = [
|
||||
{ label: "Clauses detected", value: "47", icon: Target },
|
||||
{
|
||||
label: "Risk assessment",
|
||||
value: "Low",
|
||||
icon: Shield,
|
||||
color: "text-emerald-500",
|
||||
},
|
||||
{
|
||||
label: "Processing time",
|
||||
value: "2.3s",
|
||||
icon: Zap,
|
||||
color: "text-amber-500",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
||||
{/* AI Brain */}
|
||||
<div className="flex justify-center mb-4">
|
||||
<div
|
||||
className="relative"
|
||||
style={{
|
||||
animation: isVisible
|
||||
? "pulse-glow 2s ease-in-out infinite"
|
||||
: "none",
|
||||
}}
|
||||
>
|
||||
<div className="w-16 h-16 rounded-full bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center">
|
||||
<Cpu className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div className="absolute -top-1 -right-1">
|
||||
<Sparkles className="w-5 h-5 text-amber-400 animate-pulse" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Analysis Progress */}
|
||||
<div className="space-y-3">
|
||||
{analysisPoints.map((point, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center justify-between p-2 rounded-lg bg-white/50 dark:bg-slate-800/50"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
||||
transition: `all 0.4s ease-out ${0.3 + i * 0.15}s`,
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<point.icon
|
||||
className={`w-4 h-4 ${point.color || "text-blue-500"}`}
|
||||
/>
|
||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||
{point.label}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-sm font-bold text-slate-800 dark:text-slate-200">
|
||||
{point.value}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Scanning Effect */}
|
||||
<div className="mt-4 relative h-20 rounded-lg bg-slate-100 dark:bg-slate-800 overflow-hidden">
|
||||
<div className="absolute inset-0 flex items-center justify-center gap-1 opacity-30">
|
||||
{scanHeights.map((height, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="w-1 bg-slate-400 dark:bg-slate-600 rounded-full"
|
||||
style={{ height: `${height}%` }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
className="absolute top-0 bottom-0 w-1 bg-gradient-to-b from-blue-500 via-violet-500 to-transparent"
|
||||
style={{
|
||||
left: isVisible ? "100%" : "0%",
|
||||
transition: "left 2s ease-in-out 0.5s",
|
||||
boxShadow: "0 0 20px rgba(59, 130, 246, 0.5)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Chat Animation
|
||||
function ChatStepAnimation() {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.3,
|
||||
});
|
||||
|
||||
const messages = [
|
||||
{ text: "Explain the termination clause", isUser: true },
|
||||
{
|
||||
text: "Section 12.3: Either party may terminate with 30 days written notice...",
|
||||
isUser: false,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
||||
<div className="space-y-3">
|
||||
{messages.map((msg, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`flex ${msg.isUser ? "justify-end" : "justify-start"}`}
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
||||
transition: `all 0.4s ease-out ${0.3 + i * 0.4}s`,
|
||||
}}
|
||||
>
|
||||
{!msg.isUser && (
|
||||
<div className="w-8 h-8 rounded-full bg-gradient-to-br from-teal-500 to-cyan-600 flex items-center justify-center mr-2 flex-shrink-0">
|
||||
<Sparkles className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`max-w-[80%] px-4 py-2 rounded-2xl text-sm ${
|
||||
msg.isUser
|
||||
? "bg-blue-600 text-white rounded-tr-sm"
|
||||
: "bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-tl-sm"
|
||||
}`}
|
||||
>
|
||||
{msg.text}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* RAG Indicator */}
|
||||
<div
|
||||
className="mt-4 flex items-center justify-center gap-2 text-xs text-slate-500"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transition: "opacity 0.4s ease-out 1.2s",
|
||||
}}
|
||||
>
|
||||
<div className="flex gap-1">
|
||||
<span
|
||||
className="w-2 h-2 rounded-full bg-teal-500 animate-pulse"
|
||||
style={{ animationDelay: "0s" }}
|
||||
/>
|
||||
<span
|
||||
className="w-2 h-2 rounded-full bg-teal-500 animate-pulse"
|
||||
style={{ animationDelay: "0.2s" }}
|
||||
/>
|
||||
<span
|
||||
className="w-2 h-2 rounded-full bg-teal-500 animate-pulse"
|
||||
style={{ animationDelay: "0.4s" }}
|
||||
/>
|
||||
</div>
|
||||
<span>Powered by RAG</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Blockchain Animation
|
||||
function BlockchainStepAnimation() {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.3,
|
||||
});
|
||||
|
||||
return (
|
||||
<div ref={ref} className="mt-6 glass rounded-xl p-4">
|
||||
{/* Blockchain Visual */}
|
||||
<div className="relative h-24 mb-4">
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
{[0, 1, 2].map((i) => (
|
||||
<div key={i} className="relative">
|
||||
<div
|
||||
className="w-12 h-12 rounded-lg bg-gradient-to-br from-emerald-500 to-green-600 flex items-center justify-center shadow-lg"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "scale(1)" : "scale(0.8)",
|
||||
transition: `all 0.4s ease-out ${0.2 + i * 0.2}s`,
|
||||
}}
|
||||
>
|
||||
<Link className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
{i < 2 && (
|
||||
<div
|
||||
className="absolute top-1/2 -right-4 w-8 h-0.5 bg-emerald-500/50"
|
||||
style={{
|
||||
transform: isVisible ? "scaleX(1)" : "scaleX(0)",
|
||||
transformOrigin: "left",
|
||||
transition: `transform 0.3s ease-out ${0.4 + i * 0.2}s`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Certificate */}
|
||||
<div
|
||||
className="glass rounded-lg p-3 border border-emerald-500/30"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(10px)",
|
||||
transition: "all 0.5s ease-out 0.8s",
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-emerald-500/20 flex items-center justify-center">
|
||||
<Shield className="w-5 h-5 text-emerald-500" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-semibold text-slate-800 dark:text-slate-200">
|
||||
Verified on Polygon
|
||||
</p>
|
||||
<p className="text-xs font-mono text-slate-500">0x3f7a...9e2d</p>
|
||||
</div>
|
||||
<Check className="w-5 h-5 text-emerald-500" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timestamp */}
|
||||
<div
|
||||
className="mt-3 text-center text-xs text-slate-500"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transition: "opacity 0.4s ease-out 1.2s",
|
||||
}}
|
||||
>
|
||||
Timestamped: {new Date().toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function HowItWorks() {
|
||||
const { ref: headerRef, isVisible: headerVisible } =
|
||||
useScrollAnimation<HTMLDivElement>();
|
||||
|
||||
const steps = [
|
||||
{
|
||||
number: "01",
|
||||
title: "Upload Your Contract",
|
||||
description:
|
||||
"PDF, images, or scanned documents. Simply drag and drop or click to browse.",
|
||||
icon: Upload,
|
||||
gradient: "bg-gradient-to-br from-blue-500 to-blue-600",
|
||||
animation: <UploadAnimation />,
|
||||
},
|
||||
{
|
||||
number: "02",
|
||||
title: "AI Extracts & Analyzes",
|
||||
description:
|
||||
"GPT-4 Turbo understands your contract deeply. Automatic extraction of all important clauses and terms.",
|
||||
icon: Cpu,
|
||||
gradient: "bg-gradient-to-br from-violet-500 to-purple-600",
|
||||
animation: <AIAnalysisAnimation />,
|
||||
},
|
||||
{
|
||||
number: "03",
|
||||
title: "Chat with AI Assistant",
|
||||
description:
|
||||
"Get instant answers to any questions. Powered by RAG for precise, context-aware responses.",
|
||||
icon: MessageSquare,
|
||||
gradient: "bg-gradient-to-br from-teal-500 to-cyan-600",
|
||||
animation: <ChatStepAnimation />,
|
||||
},
|
||||
{
|
||||
number: "04",
|
||||
title: "Immutable Certification",
|
||||
description:
|
||||
"Registered on Polygon blockchain. Legally valid timestamped proof of submission.",
|
||||
icon: Shield,
|
||||
gradient: "bg-gradient-to-br from-emerald-500 to-green-600",
|
||||
animation: <BlockchainStepAnimation />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section
|
||||
id="how-it-works"
|
||||
className="relative py-24 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
||||
>
|
||||
{/* Background */}
|
||||
<div className="absolute inset-0 bg-slate-50 dark:bg-slate-900/50">
|
||||
<div className="absolute inset-0 grid-pattern opacity-50" />
|
||||
</div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto">
|
||||
{/* Section Header */}
|
||||
<div
|
||||
ref={headerRef}
|
||||
className="text-center mb-16"
|
||||
style={{
|
||||
opacity: headerVisible ? 1 : 0,
|
||||
transform: headerVisible ? "translateY(0)" : "translateY(30px)",
|
||||
transition: "all 0.6s ease-out",
|
||||
}}
|
||||
>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full glass mb-6">
|
||||
<Target className="w-4 h-4 text-blue-600 dark:text-blue-400" />
|
||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||
Simple Process
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-slate-900 dark:text-white mb-4">
|
||||
From Upload to Certification in{" "}
|
||||
<span className="gradient-text">4 Steps</span>
|
||||
</h2>
|
||||
|
||||
<p className="text-xl text-slate-600 dark:text-slate-400 max-w-2xl mx-auto">
|
||||
Our intelligent system handles everything automatically
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Steps Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-6">
|
||||
{steps.map((step, index) => (
|
||||
<div key={step.number} className="relative">
|
||||
<StepCard
|
||||
number={step.number}
|
||||
title={step.title}
|
||||
description={step.description}
|
||||
icon={step.icon}
|
||||
gradient={step.gradient}
|
||||
delay={index * 0.15}
|
||||
isLast={index === steps.length - 1}
|
||||
/>
|
||||
{step.animation}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Custom Animation Keyframes */}
|
||||
<style>{`
|
||||
@keyframes move-right {
|
||||
0% {
|
||||
left: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
261
components/views/Home/Navbar.tsx
Normal file
261
components/views/Home/Navbar.tsx
Normal file
@@ -0,0 +1,261 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTheme } from "@/hooks/useTheme";
|
||||
import { Sparkles, Sun, Moon, X, ArrowRight } from "lucide-react";
|
||||
|
||||
const navLinks = [
|
||||
{ label: "Features", href: "#features" },
|
||||
{ label: "How It Works", href: "#how-it-works" },
|
||||
{ label: "About", href: "#stats" },
|
||||
{ label: "Contact", href: "#footer" },
|
||||
];
|
||||
|
||||
export function Navbar() {
|
||||
const { theme, toggleTheme, mounted } = useTheme();
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
const [activeLink, setActiveLink] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setIsScrolled(window.scrollY > 20);
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||
return () => window.removeEventListener("scroll", handleScroll);
|
||||
}, []);
|
||||
|
||||
const handleLinkClick = (
|
||||
e: React.MouseEvent<HTMLAnchorElement>,
|
||||
href: string,
|
||||
) => {
|
||||
e.preventDefault();
|
||||
const targetId = href.replace("#", "");
|
||||
const element = document.getElementById(targetId);
|
||||
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: "smooth" });
|
||||
setActiveLink(href);
|
||||
setIsMobileMenuOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!mounted) {
|
||||
return (
|
||||
<nav className="fixed top-0 left-0 right-0 z-50 mt-6 px-4">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="glass rounded-full px-8 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Sparkles className="w-6 h-6 text-blue-600" />
|
||||
<span className="text-xl font-bold gradient-text">
|
||||
Smart-Admin Copilot
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav
|
||||
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-500 ${
|
||||
isScrolled ? "mt-0 px-0" : "mt-6 px-4"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`mx-auto transition-all duration-500 ${
|
||||
isScrolled ? "max-w-full" : "max-w-6xl"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`glass rounded-full px-4 md:px-8 py-3 md:py-4 transition-all duration-500 ${
|
||||
isScrolled
|
||||
? "rounded-none shadow-lg backdrop-blur-2xl"
|
||||
: "shadow-xl hover:shadow-2xl"
|
||||
} ${
|
||||
isScrolled
|
||||
? "border-b border-slate-200/50 dark:border-slate-700/50"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Logo */}
|
||||
<a
|
||||
href="#"
|
||||
className="flex items-center gap-2 group"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}}
|
||||
>
|
||||
<div className="relative">
|
||||
<Sparkles className="w-6 h-6 text-blue-600 dark:text-blue-400 transition-transform duration-300 group-hover:rotate-12" />
|
||||
<div className="absolute inset-0 bg-blue-500/20 blur-lg rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
|
||||
</div>
|
||||
<span className="text-lg md:text-xl font-bold gradient-text hidden sm:inline">
|
||||
Smart-Admin Copilot
|
||||
</span>
|
||||
<span className="text-lg font-bold gradient-text sm:hidden">
|
||||
SAC
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden lg:flex items-center gap-8">
|
||||
{navLinks.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
onClick={(e) => handleLinkClick(e, link.href)}
|
||||
className={`relative px-4 py-2 text-sm font-medium transition-all duration-200 rounded-full ${
|
||||
activeLink === link.href
|
||||
? "text-blue-600 dark:text-blue-400"
|
||||
: "text-slate-700 dark:text-slate-300 hover:bg-slate-100/50 dark:hover:bg-slate-800/50"
|
||||
}`}
|
||||
>
|
||||
{link.label}
|
||||
{activeLink === link.href && (
|
||||
<span className="absolute bottom-0 left-1/2 -translate-x-1/2 w-1 h-1 bg-blue-600 dark:bg-blue-400 rounded-full" />
|
||||
)}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Right Section */}
|
||||
<div className="flex items-center gap-2 md:gap-3">
|
||||
{/* Theme Toggle */}
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="relative p-1 rounded-full bg-slate-100 dark:bg-slate-800 transition-colors duration-300"
|
||||
aria-label="Toggle theme"
|
||||
>
|
||||
<div className="flex items-center gap-1">
|
||||
<div
|
||||
className={`p-2 rounded-full transition-all duration-300 ${
|
||||
theme === "light"
|
||||
? "bg-white shadow-sm text-amber-500"
|
||||
: "text-slate-400"
|
||||
}`}
|
||||
>
|
||||
<Sun className="w-4 h-4" />
|
||||
</div>
|
||||
<div
|
||||
className={`p-2 rounded-full transition-all duration-300 ${
|
||||
theme === "dark"
|
||||
? "bg-slate-900 shadow-sm text-blue-400"
|
||||
: "text-slate-400"
|
||||
}`}
|
||||
>
|
||||
<Moon className="w-4 h-4" />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* Sign In - Desktop */}
|
||||
<button className="hidden md:flex items-center gap-2 px-5 py-2 text-sm font-medium text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-600 rounded-full hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200">
|
||||
Sign In
|
||||
</button>
|
||||
|
||||
{/* Get Started - Desktop */}
|
||||
<button className="hidden md:flex items-center gap-2 px-6 py-2.5 text-sm font-semibold text-white btn-gradient rounded-full group">
|
||||
Get Started
|
||||
<ArrowRight className="w-4 h-4 transition-transform duration-300 group-hover:translate-x-1" />
|
||||
</button>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className="lg:hidden p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors duration-200"
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<div className="relative w-6 h-6">
|
||||
<span
|
||||
className={`absolute left-0 w-6 h-0.5 bg-slate-700 dark:bg-slate-300 transition-all duration-300 ${
|
||||
isMobileMenuOpen ? "top-3 rotate-45" : "top-1"
|
||||
}`}
|
||||
/>
|
||||
<span
|
||||
className={`absolute left-0 top-3 w-6 h-0.5 bg-slate-700 dark:bg-slate-300 transition-all duration-300 ${
|
||||
isMobileMenuOpen ? "opacity-0" : "opacity-100"
|
||||
}`}
|
||||
/>
|
||||
<span
|
||||
className={`absolute left-0 w-6 h-0.5 bg-slate-700 dark:bg-slate-300 transition-all duration-300 ${
|
||||
isMobileMenuOpen ? "top-3 -rotate-45" : "top-5"
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
<div
|
||||
className={`fixed inset-0 z-40 lg:hidden transition-all duration-500 ${
|
||||
isMobileMenuOpen ? "opacity-100 visible" : "opacity-0 invisible"
|
||||
}`}
|
||||
>
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
/>
|
||||
|
||||
{/* Menu Panel */}
|
||||
<div
|
||||
className={`absolute right-0 top-0 h-full w-80 max-w-full bg-white dark:bg-slate-900 shadow-2xl transition-transform duration-500 ${
|
||||
isMobileMenuOpen ? "translate-x-0" : "translate-x-full"
|
||||
}`}
|
||||
>
|
||||
<div className="p-6 pt-20">
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
className="absolute top-6 right-6 p-2 rounded-full hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors"
|
||||
aria-label="Close menu"
|
||||
>
|
||||
<X className="w-6 h-6" />
|
||||
</button>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{navLinks.map((link, index) => (
|
||||
<a
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
onClick={(e) => handleLinkClick(e, link.href)}
|
||||
className="px-4 py-3 text-lg font-medium text-slate-700 dark:text-slate-300 rounded-xl hover:bg-slate-100 dark:hover:bg-slate-800 transition-all duration-200"
|
||||
style={{
|
||||
animationDelay: `${index * 0.1}s`,
|
||||
animation: isMobileMenuOpen
|
||||
? "slide-up 0.4s ease-out forwards"
|
||||
: "none",
|
||||
opacity: isMobileMenuOpen ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 flex flex-col gap-3">
|
||||
<button className="w-full px-5 py-3 text-sm font-medium text-slate-700 dark:text-slate-300 border border-slate-300 dark:border-slate-600 rounded-full hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200">
|
||||
Sign In
|
||||
</button>
|
||||
<button className="w-full flex items-center justify-center gap-2 px-6 py-3 text-sm font-semibold text-white btn-gradient rounded-full">
|
||||
Get Started
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
399
components/views/Home/Stats.tsx
Normal file
399
components/views/Home/Stats.tsx
Normal file
@@ -0,0 +1,399 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import {
|
||||
Target,
|
||||
Zap,
|
||||
Shield,
|
||||
Lock,
|
||||
TrendingUp,
|
||||
Award,
|
||||
Check,
|
||||
} from "lucide-react";
|
||||
import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
||||
|
||||
// Count Up Hook
|
||||
function useCountUp(
|
||||
end: number,
|
||||
duration: number = 2000,
|
||||
startOnView: boolean = true,
|
||||
) {
|
||||
const [count, setCount] = useState(0);
|
||||
const [hasStarted, setHasStarted] = useState(!startOnView);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!startOnView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting && !hasStarted) {
|
||||
setHasStarted(true);
|
||||
}
|
||||
},
|
||||
{ threshold: 0.5 },
|
||||
);
|
||||
|
||||
if (ref.current) {
|
||||
observer.observe(ref.current);
|
||||
}
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, [hasStarted, startOnView]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasStarted) return;
|
||||
|
||||
let startTime: number | null = null;
|
||||
let animationFrame: number;
|
||||
|
||||
const animate = (timestamp: number) => {
|
||||
if (!startTime) startTime = timestamp;
|
||||
const progress = Math.min((timestamp - startTime) / duration, 1);
|
||||
|
||||
// Ease out cubic
|
||||
const easeOut = 1 - Math.pow(1 - progress, 3);
|
||||
setCount(Math.floor(end * easeOut));
|
||||
|
||||
if (progress < 1) {
|
||||
animationFrame = requestAnimationFrame(animate);
|
||||
}
|
||||
};
|
||||
|
||||
animationFrame = requestAnimationFrame(animate);
|
||||
|
||||
return () => {
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
}
|
||||
};
|
||||
}, [hasStarted, end, duration]);
|
||||
|
||||
return { count, ref };
|
||||
}
|
||||
|
||||
// Stat Card Component
|
||||
interface StatCardProps {
|
||||
value: string;
|
||||
numericValue?: number;
|
||||
suffix?: string;
|
||||
prefix?: string;
|
||||
label: string;
|
||||
icon: React.ElementType;
|
||||
gradient: string;
|
||||
delay: number;
|
||||
additional?: string;
|
||||
isText?: boolean;
|
||||
}
|
||||
|
||||
function StatCard({
|
||||
value,
|
||||
numericValue,
|
||||
suffix = "",
|
||||
prefix = "",
|
||||
label,
|
||||
icon: Icon,
|
||||
gradient,
|
||||
delay,
|
||||
additional,
|
||||
isText = false,
|
||||
}: StatCardProps) {
|
||||
const { ref: scrollRef, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.3,
|
||||
});
|
||||
const { count, ref: countRef } = useCountUp(numericValue || 0, 2000);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={scrollRef}
|
||||
className="relative group"
|
||||
style={{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(30px)",
|
||||
transition: `all 0.6s ease-out ${delay}s`,
|
||||
}}
|
||||
>
|
||||
<div className="relative glass rounded-3xl p-8 hover-lift overflow-hidden">
|
||||
{/* Background Icon */}
|
||||
<div className="absolute top-4 right-4 opacity-10">
|
||||
<Icon className="w-24 h-24 text-white" />
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="relative z-10">
|
||||
{/* Icon */}
|
||||
<div
|
||||
className={`inline-flex p-3 rounded-2xl ${gradient} mb-6 shadow-lg`}
|
||||
>
|
||||
<Icon className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
|
||||
{/* Value */}
|
||||
<div ref={countRef} className="mb-2">
|
||||
{isText ? (
|
||||
<span className="text-5xl md:text-6xl lg:text-7xl font-black text-white tracking-wider">
|
||||
{value}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-5xl md:text-6xl lg:text-7xl font-black text-white">
|
||||
{prefix}
|
||||
{numericValue !== undefined ? count : value}
|
||||
{suffix}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Label */}
|
||||
<p className="text-lg md:text-xl font-medium text-white/90 mb-2">
|
||||
{label}
|
||||
</p>
|
||||
|
||||
{/* Additional Info */}
|
||||
{additional && (
|
||||
<div className="flex items-center gap-2 mt-3">
|
||||
<TrendingUp className="w-4 h-4 text-emerald-400" />
|
||||
<span className="text-sm text-white/70">{additional}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Glow Effect */}
|
||||
<div
|
||||
className={`absolute -inset-px ${gradient} opacity-0 group-hover:opacity-30 rounded-3xl blur-xl transition-opacity duration-500`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Floating Badge Component
|
||||
function FloatingBadge({
|
||||
text,
|
||||
icon: Icon,
|
||||
delay,
|
||||
position,
|
||||
}: {
|
||||
text: string;
|
||||
icon: React.ElementType;
|
||||
delay: number;
|
||||
position: { top?: string; bottom?: string; left?: string; right?: string };
|
||||
}) {
|
||||
const { ref, isVisible } = useScrollAnimation<HTMLDivElement>({
|
||||
threshold: 0.5,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="absolute glass rounded-full px-3 py-1.5 flex items-center gap-2 shadow-lg"
|
||||
style={{
|
||||
...position,
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? "translateY(0)" : "translateY(20px)",
|
||||
transition: `all 0.5s ease-out ${delay}s`,
|
||||
animationName: isVisible ? "float" : "none",
|
||||
animationDuration: isVisible ? "4s" : undefined,
|
||||
animationTimingFunction: isVisible ? "ease-in-out" : undefined,
|
||||
animationIterationCount: isVisible ? "infinite" : undefined,
|
||||
animationFillMode: "forwards",
|
||||
animationDelay: isVisible ? `${delay}s` : undefined,
|
||||
}}
|
||||
>
|
||||
<Icon className="w-4 h-4 text-blue-400" />
|
||||
<span className="text-xs font-medium text-white">{text}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Stats() {
|
||||
const { ref: headerRef, isVisible: headerVisible } =
|
||||
useScrollAnimation<HTMLDivElement>();
|
||||
|
||||
interface StatItem {
|
||||
value: string;
|
||||
numericValue?: number;
|
||||
suffix?: string;
|
||||
prefix?: string;
|
||||
label: string;
|
||||
icon: React.ElementType;
|
||||
gradient: string;
|
||||
additional?: string;
|
||||
isText?: boolean;
|
||||
}
|
||||
|
||||
const stats: StatItem[] = [
|
||||
{
|
||||
value: "99.9",
|
||||
numericValue: 99,
|
||||
suffix: "%",
|
||||
label: "OCR + AI Accuracy",
|
||||
icon: Target,
|
||||
gradient: "bg-gradient-to-br from-blue-500 to-blue-600",
|
||||
additional: "+0.3% this month",
|
||||
},
|
||||
{
|
||||
value: "< 3",
|
||||
label: "Average AI Response Time",
|
||||
icon: Zap,
|
||||
gradient: "bg-gradient-to-br from-amber-500 to-orange-600",
|
||||
additional: "Lightning fast",
|
||||
isText: true,
|
||||
},
|
||||
{
|
||||
value: "100",
|
||||
numericValue: 100,
|
||||
suffix: "%",
|
||||
label: "Blockchain Verified",
|
||||
icon: Shield,
|
||||
gradient: "bg-gradient-to-br from-violet-500 to-purple-600",
|
||||
additional: "All documents certified",
|
||||
},
|
||||
{
|
||||
value: "GDPR",
|
||||
label: "Full European Compliance",
|
||||
icon: Lock,
|
||||
gradient: "bg-gradient-to-br from-emerald-500 to-green-600",
|
||||
additional: "ISO 27001 Certified",
|
||||
isText: true,
|
||||
},
|
||||
];
|
||||
|
||||
const floatingBadges = [
|
||||
{
|
||||
text: "+1 Verified",
|
||||
icon: Check,
|
||||
position: { top: "10%", left: "5%" },
|
||||
delay: 0.8,
|
||||
},
|
||||
{
|
||||
text: "99.9% Uptime",
|
||||
icon: Shield,
|
||||
position: { top: "20%", right: "8%" },
|
||||
delay: 1,
|
||||
},
|
||||
{
|
||||
text: "AI Powered",
|
||||
icon: Zap,
|
||||
position: { bottom: "15%", left: "10%" },
|
||||
delay: 1.2,
|
||||
},
|
||||
{
|
||||
text: "Secure",
|
||||
icon: Lock,
|
||||
position: { bottom: "25%", right: "5%" },
|
||||
delay: 1.4,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section
|
||||
id="stats"
|
||||
className="relative py-24 px-4 sm:px-6 lg:px-8 overflow-hidden"
|
||||
>
|
||||
{/* Gradient Background */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-blue-600 via-violet-600 to-teal-600">
|
||||
{/* Grid Pattern Overlay */}
|
||||
<div className="absolute inset-0 grid-pattern opacity-20" />
|
||||
|
||||
{/* Radial Glow */}
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(255,255,255,0.1)_0%,transparent_70%)]" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badges */}
|
||||
{floatingBadges.map((badge, i) => (
|
||||
<FloatingBadge
|
||||
key={i}
|
||||
text={badge.text}
|
||||
icon={badge.icon}
|
||||
delay={badge.delay}
|
||||
position={badge.position}
|
||||
/>
|
||||
))}
|
||||
|
||||
<div className="relative max-w-7xl mx-auto">
|
||||
{/* Section Header */}
|
||||
<div
|
||||
ref={headerRef}
|
||||
className="text-center mb-16"
|
||||
style={{
|
||||
opacity: headerVisible ? 1 : 0,
|
||||
transform: headerVisible ? "translateY(0)" : "translateY(30px)",
|
||||
transition: "all 0.6s ease-out",
|
||||
}}
|
||||
>
|
||||
<span className="inline-block text-sm uppercase tracking-widest text-white/70 mb-4">
|
||||
By The Numbers
|
||||
</span>
|
||||
|
||||
<h2 className="text-4xl md:text-5xl lg:text-6xl font-black text-white mb-4">
|
||||
Results That{" "}
|
||||
<span className="relative">
|
||||
Speak
|
||||
<svg
|
||||
className="absolute -bottom-2 left-0 w-full"
|
||||
viewBox="0 0 200 12"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M2 10C50 2 150 2 198 10"
|
||||
stroke="rgba(255,255,255,0.5)"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
className="animate-pulse"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Stats Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 lg:gap-8">
|
||||
{stats.map((stat, index) => (
|
||||
<StatCard
|
||||
key={stat.label}
|
||||
value={stat.value}
|
||||
numericValue={stat.numericValue}
|
||||
suffix={stat.suffix || ""}
|
||||
prefix={stat.prefix || ""}
|
||||
label={stat.label}
|
||||
icon={stat.icon}
|
||||
gradient={stat.gradient}
|
||||
delay={index * 0.1}
|
||||
additional={stat.additional}
|
||||
isText={stat.isText}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Bottom Awards Row */}
|
||||
<div
|
||||
className="mt-16 flex flex-wrap items-center justify-center gap-4"
|
||||
style={{
|
||||
opacity: headerVisible ? 1 : 0,
|
||||
transform: headerVisible ? "translateY(0)" : "translateY(20px)",
|
||||
transition: "all 0.6s ease-out 0.5s",
|
||||
}}
|
||||
>
|
||||
{[
|
||||
{ icon: Award, text: "Best AI Solution 2024" },
|
||||
{ icon: Shield, text: "SOC 2 Type II Certified" },
|
||||
{ icon: Lock, text: "GDPR Compliant" },
|
||||
{ icon: Check, text: "ISO 27001 Certified" },
|
||||
].map((award, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full bg-white/10 backdrop-blur-sm border border-white/20"
|
||||
>
|
||||
<award.icon className="w-4 h-4 text-white/80" />
|
||||
<span className="text-sm font-medium text-white/90">
|
||||
{award.text}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user