mirror of
http://88.130.71.182:3000/BlitTech/contexta_fe.git
synced 2026-06-12 23:23:22 +00:00
Updates Mar6
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import {
|
||||
Sparkles, Bot, Globe, Code, Database, Shield, Zap, ArrowRight,
|
||||
Check, MessageSquare, Upload, Play, ChevronRight, Star, Users,
|
||||
Check, MessageSquare, Upload, Play, ChevronRight, Star,
|
||||
FileText, Cpu, Lock, Download, Menu, X
|
||||
} from 'lucide-react'
|
||||
|
||||
@@ -20,11 +20,20 @@ function useInView(options?: IntersectionObserverInit) {
|
||||
)
|
||||
observer.observe(el)
|
||||
return () => observer.disconnect()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
return { ref, isInView }
|
||||
}
|
||||
|
||||
// ─── Static conversation data (outside component to avoid re-creation) ─────────
|
||||
const CHAT_CONVERSATION = [
|
||||
{ role: 'user', text: 'What are your return policies?' },
|
||||
{ role: 'bot', text: 'Based on your company documents, we offer a 30-day return policy for all items in original condition. Refunds are processed within 5-7 business days.' },
|
||||
{ role: 'user', text: 'Can I return sale items?' },
|
||||
{ role: 'bot', text: 'According to Section 4.2 of your policy, sale items can be exchanged within 14 days but are not eligible for refunds. Would you like to know more?' },
|
||||
]
|
||||
|
||||
// ─── Animated Counter ──────────────────────────────────────────────────────────
|
||||
const AnimatedCounter: React.FC<{ end: number; suffix?: string; label: string; isInView: boolean }> = ({ end, suffix = '', label, isInView }) => {
|
||||
const [count, setCount] = useState(0)
|
||||
@@ -58,28 +67,21 @@ const FloatingChatPreview: React.FC = () => {
|
||||
const [isTyping, setIsTyping] = useState(false)
|
||||
const [step, setStep] = useState(0)
|
||||
|
||||
const conversation = [
|
||||
{ role: 'user', text: 'What are your return policies?' },
|
||||
{ role: 'bot', text: 'Based on your company documents, we offer a 30-day return policy for all items in original condition. Refunds are processed within 5-7 business days.' },
|
||||
{ role: 'user', text: 'Can I return sale items?' },
|
||||
{ role: 'bot', text: 'According to Section 4.2 of your policy, sale items can be exchanged within 14 days but are not eligible for refunds. Would you like to know more?' },
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
if (step >= conversation.length) {
|
||||
if (step >= CHAT_CONVERSATION.length) {
|
||||
const timeout = setTimeout(() => { setMessages([]); setStep(0) }, 4000)
|
||||
return () => clearTimeout(timeout)
|
||||
}
|
||||
const timeout = setTimeout(() => {
|
||||
if (conversation[step].role === 'bot') {
|
||||
if (CHAT_CONVERSATION[step].role === 'bot') {
|
||||
setIsTyping(true)
|
||||
setTimeout(() => {
|
||||
setIsTyping(false)
|
||||
setMessages(prev => [...prev, conversation[step]])
|
||||
setMessages(prev => [...prev, CHAT_CONVERSATION[step]])
|
||||
setStep(s => s + 1)
|
||||
}, 1500)
|
||||
} else {
|
||||
setMessages(prev => [...prev, conversation[step]])
|
||||
setMessages(prev => [...prev, CHAT_CONVERSATION[step]])
|
||||
setStep(s => s + 1)
|
||||
}
|
||||
}, step === 0 ? 1500 : 1000)
|
||||
@@ -240,12 +242,12 @@ export const LandingPage: React.FC = () => {
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||
const [scrolled, setScrolled] = useState(false)
|
||||
|
||||
const features = useInView()
|
||||
const howItWorks = useInView()
|
||||
const stats = useInView()
|
||||
const testimonials = useInView()
|
||||
const pricing = useInView()
|
||||
const cta = useInView()
|
||||
const { ref: featuresRef, isInView: featuresInView } = useInView()
|
||||
const { ref: howItWorksRef, isInView: howItWorksInView } = useInView()
|
||||
const { ref: statsRef, isInView: statsInView } = useInView()
|
||||
const { ref: testimonialsRef, isInView: testimonialsInView } = useInView()
|
||||
const { ref: pricingRef, isInView: pricingInView } = useInView()
|
||||
const { ref: ctaRef, isInView: ctaInView } = useInView()
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => setScrolled(window.scrollY > 20)
|
||||
@@ -385,32 +387,32 @@ export const LandingPage: React.FC = () => {
|
||||
</section>
|
||||
|
||||
{/* ── Trusted By / Stats ── */}
|
||||
<section ref={stats.ref} className="py-16 border-t border-b border-gray-100 bg-gray-50/50">
|
||||
<section ref={statsRef} className="py-16 border-t border-b border-gray-100 bg-gray-50/50">
|
||||
<div className="max-w-5xl mx-auto px-6">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
|
||||
<AnimatedCounter end={2500} suffix="+" label="Chatbots Created" isInView={stats.isInView} />
|
||||
<AnimatedCounter end={500} suffix="+" label="Companies" isInView={stats.isInView} />
|
||||
<AnimatedCounter end={10} suffix="M+" label="Messages Processed" isInView={stats.isInView} />
|
||||
<AnimatedCounter end={99} suffix="%" label="Uptime" isInView={stats.isInView} />
|
||||
<AnimatedCounter end={2500} suffix="+" label="Chatbots Created" isInView={statsInView} />
|
||||
<AnimatedCounter end={500} suffix="+" label="Companies" isInView={statsInView} />
|
||||
<AnimatedCounter end={10} suffix="M+" label="Messages Processed" isInView={statsInView} />
|
||||
<AnimatedCounter end={99} suffix="%" label="Uptime" isInView={statsInView} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Features ── */}
|
||||
<section id="features" ref={features.ref} className="py-20 md:py-28">
|
||||
<section id="features" ref={featuresRef} className="py-20 md:py-28">
|
||||
<div className="max-w-6xl mx-auto px-6">
|
||||
<div className="text-center mb-16">
|
||||
<div className={`inline-flex items-center gap-2 bg-primary-50 text-primary-700 text-xs px-3 py-1 rounded-full
|
||||
mb-4 font-semibold uppercase tracking-wider transition-all duration-500
|
||||
${features.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`}>
|
||||
<div className={`inline-flex items-center gap-2 bg-primary-50 text-primary-700 text-xs px-3 py-1 rounded-full
|
||||
mb-4 font-semibold uppercase tracking-wider transition-all duration-500
|
||||
${featuresInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`}>
|
||||
Features
|
||||
</div>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${features.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${featuresInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Everything you need to build
|
||||
</h2>
|
||||
<p className={`text-gray-500 max-w-lg mx-auto transition-all duration-700 delay-100
|
||||
${features.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<p className={`text-gray-500 max-w-lg mx-auto transition-all duration-700 delay-100
|
||||
${featuresInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
From document upload to deployment — we handle the heavy lifting so you can focus on your business.
|
||||
</p>
|
||||
</div>
|
||||
@@ -424,24 +426,24 @@ export const LandingPage: React.FC = () => {
|
||||
{ icon: <Sparkles className="w-6 h-6" />, title: 'Premium AI Models', desc: 'Access GPT-4o, Claude 3.5 Sonnet, Gemini 1.5 Pro, and open-source models.', color: 'bg-yellow-100 text-yellow-700' },
|
||||
{ icon: <Shield className="w-6 h-6" />, title: 'Data Isolation', desc: 'Each company gets its own isolated vector database. Your data is never mixed with others.', color: 'bg-red-100 text-red-600' },
|
||||
].map((f, i) => (
|
||||
<FeatureCard key={f.title} {...f} delay={i * 100} isInView={features.isInView} />
|
||||
<FeatureCard key={f.title} {...f} delay={i * 100} isInView={featuresInView} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── How It Works ── */}
|
||||
<section ref={howItWorks.ref} className="py-20 md:py-28 bg-gray-50/70 relative">
|
||||
<section ref={howItWorksRef} className="py-20 md:py-28 bg-gray-50/70 relative">
|
||||
<div className="absolute inset-0 bg-dots" />
|
||||
<div className="relative max-w-5xl mx-auto px-6">
|
||||
<div className="text-center mb-16">
|
||||
<div className={`inline-flex items-center gap-2 bg-primary-50 text-primary-700 text-xs px-3 py-1 rounded-full
|
||||
mb-4 font-semibold uppercase tracking-wider transition-all duration-500
|
||||
${howItWorks.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`}>
|
||||
<div className={`inline-flex items-center gap-2 bg-primary-50 text-primary-700 text-xs px-3 py-1 rounded-full
|
||||
mb-4 font-semibold uppercase tracking-wider transition-all duration-500
|
||||
${howItWorksInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`}>
|
||||
How It Works
|
||||
</div>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${howItWorks.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${howItWorksInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Three steps to your AI chatbot
|
||||
</h2>
|
||||
</div>
|
||||
@@ -452,13 +454,13 @@ export const LandingPage: React.FC = () => {
|
||||
|
||||
<Step num={1} icon={<Upload className="w-7 h-7 text-white" />}
|
||||
title="Upload Documents" desc="Drag and drop your PDFs, DOCX, CSV, Excel, or text files. We handle parsing and chunking automatically."
|
||||
isInView={howItWorks.isInView} delay={0} />
|
||||
isInView={howItWorksInView} delay={0} />
|
||||
<Step num={2} icon={<Cpu className="w-7 h-7 text-white" />}
|
||||
title="Configure & Train" desc="Choose your AI model, customize the system prompt, and let our RAG engine build your knowledge base."
|
||||
isInView={howItWorks.isInView} delay={200} />
|
||||
isInView={howItWorksInView} delay={200} />
|
||||
<Step num={3} icon={<Play className="w-7 h-7 text-white" />}
|
||||
title="Deploy Anywhere" desc="Publish to the marketplace, embed on your website, or export the full source code for self-hosting."
|
||||
isInView={howItWorks.isInView} delay={400} />
|
||||
isInView={howItWorksInView} delay={400} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -534,17 +536,17 @@ async def chat(message: str):
|
||||
</section>
|
||||
|
||||
{/* ── Testimonials ── */}
|
||||
<section ref={testimonials.ref} className="py-20 md:py-28 bg-gray-50/70 relative">
|
||||
<section ref={testimonialsRef} className="py-20 md:py-28 bg-gray-50/70 relative">
|
||||
<div className="absolute inset-0 bg-grid opacity-30" />
|
||||
<div className="relative max-w-6xl mx-auto px-6">
|
||||
<div className="text-center mb-16">
|
||||
<div className={`inline-flex items-center gap-2 bg-primary-50 text-primary-700 text-xs px-3 py-1 rounded-full
|
||||
mb-4 font-semibold uppercase tracking-wider transition-all duration-500
|
||||
${testimonials.isInView ? 'opacity-100' : 'opacity-0'}`}>
|
||||
<div className={`inline-flex items-center gap-2 bg-primary-50 text-primary-700 text-xs px-3 py-1 rounded-full
|
||||
mb-4 font-semibold uppercase tracking-wider transition-all duration-500
|
||||
${testimonialsInView ? 'opacity-100' : 'opacity-0'}`}>
|
||||
Testimonials
|
||||
</div>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${testimonials.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${testimonialsInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Loved by builders
|
||||
</h2>
|
||||
</div>
|
||||
@@ -553,36 +555,36 @@ async def chat(message: str):
|
||||
<TestimonialCard
|
||||
quote="We had our support chatbot live in under an hour. The code export feature meant we could customize everything to match our brand perfectly."
|
||||
name="Sarah Chen" role="CTO" company="TechFlow"
|
||||
isInView={testimonials.isInView} delay={0}
|
||||
isInView={testimonialsInView} delay={0}
|
||||
/>
|
||||
<TestimonialCard
|
||||
quote="The data isolation gives us confidence to use this with sensitive healthcare data. Each client's information stays completely separate."
|
||||
name="Marcus Johnson" role="Head of Engineering" company="MedAssist"
|
||||
isInView={testimonials.isInView} delay={150}
|
||||
isInView={testimonialsInView} delay={150}
|
||||
/>
|
||||
<TestimonialCard
|
||||
quote="No other platform lets you export the full source code. That was the dealbreaker for us — we needed to own the entire stack."
|
||||
name="Elena Kowalski" role="VP of Product" company="DataBridge"
|
||||
isInView={testimonials.isInView} delay={300}
|
||||
isInView={testimonialsInView} delay={300}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Pricing Teaser ── */}
|
||||
<section ref={pricing.ref} className="py-20 md:py-28">
|
||||
<section ref={pricingRef} className="py-20 md:py-28">
|
||||
<div className="max-w-4xl mx-auto px-6 text-center">
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${pricing.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-gray-900 mb-4 tracking-tight transition-all duration-700
|
||||
${pricingInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Start free, scale as you grow
|
||||
</h2>
|
||||
<p className={`text-gray-500 mb-10 transition-all duration-700 delay-100
|
||||
${pricing.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<p className={`text-gray-500 mb-10 transition-all duration-700 delay-100
|
||||
${pricingInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Build unlimited chatbots for free. Upgrade to publish and unlock premium features.
|
||||
</p>
|
||||
|
||||
<div className={`flex flex-wrap justify-center gap-x-6 gap-y-3 mb-10 transition-all duration-700 delay-200
|
||||
${pricing.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<div className={`flex flex-wrap justify-center gap-x-6 gap-y-3 mb-10 transition-all duration-700 delay-200
|
||||
${pricingInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
{[
|
||||
{ feature: 'Free forever plan', included: true },
|
||||
{ feature: 'Unlimited chatbot creation', included: true },
|
||||
@@ -603,15 +605,15 @@ async def chat(message: str):
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Link to="/pricing" className={`text-primary-600 font-semibold hover:text-primary-700 text-sm inline-flex items-center gap-1.5
|
||||
transition-all duration-700 delay-300 hover:gap-2.5 ${pricing.isInView ? 'opacity-100' : 'opacity-0'}`}>
|
||||
<Link to="/pricing" className={`text-primary-600 font-semibold hover:text-primary-700 text-sm inline-flex items-center gap-1.5
|
||||
transition-all duration-700 delay-300 hover:gap-2.5 ${pricingInView ? 'opacity-100' : 'opacity-0'}`}>
|
||||
View full pricing <ArrowRight className="w-4 h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CTA ── */}
|
||||
<section ref={cta.ref} className="relative py-20 md:py-24 overflow-hidden">
|
||||
<section ref={ctaRef} className="relative py-20 md:py-24 overflow-hidden">
|
||||
{/* Gradient background */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary-600 via-primary-700 to-indigo-800" />
|
||||
<div className="absolute inset-0 bg-grid opacity-10" />
|
||||
@@ -620,16 +622,16 @@ async def chat(message: str):
|
||||
<div className="absolute bottom-10 right-10 w-60 h-60 bg-white/5 rounded-full blur-2xl animate-float-delayed" />
|
||||
|
||||
<div className="relative max-w-2xl mx-auto px-6 text-center">
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-white mb-5 tracking-tight transition-all duration-700
|
||||
${cta.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<h2 className={`text-3xl md:text-4xl font-extrabold text-white mb-5 tracking-tight transition-all duration-700
|
||||
${ctaInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Ready to build your first chatbot?
|
||||
</h2>
|
||||
<p className={`text-primary-100 mb-10 text-lg transition-all duration-700 delay-100
|
||||
${cta.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<p className={`text-primary-100 mb-10 text-lg transition-all duration-700 delay-100
|
||||
${ctaInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
Join hundreds of companies using Contexta to power their AI experiences.
|
||||
</p>
|
||||
<div className={`flex flex-col sm:flex-row items-center justify-center gap-4 transition-all duration-700 delay-200
|
||||
${cta.isInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<div className={`flex flex-col sm:flex-row items-center justify-center gap-4 transition-all duration-700 delay-200
|
||||
${ctaInView ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<Link to="/signup" className="bg-white text-primary-700 px-8 py-3.5 rounded-xl font-semibold
|
||||
hover:bg-primary-50 transition-all inline-flex items-center gap-2 shadow-lg shadow-black/10
|
||||
hover:-translate-y-0.5 w-full sm:w-auto justify-center text-base">
|
||||
|
||||
Reference in New Issue
Block a user