199 lines
11 KiB
TypeScript
199 lines
11 KiB
TypeScript
import { useState } from "react";
|
|
import { Link } from "react-router-dom";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
|
import { Check, X, ArrowRight, Sparkles, Shield } from "lucide-react";
|
|
import Header from "@/components/Header";
|
|
import Footer from "@/components/Footer";
|
|
|
|
const tiers = [
|
|
{
|
|
name: "Starter",
|
|
monthlyPrice: 29,
|
|
annualPrice: 24,
|
|
description: "Perfect for small teams getting started.",
|
|
features: ["Up to 10 team members", "5 projects", "Basic analytics", "Email support", "1 GB storage"],
|
|
cta: "Start Free Trial",
|
|
popular: false,
|
|
},
|
|
{
|
|
name: "Professional",
|
|
monthlyPrice: 79,
|
|
annualPrice: 64,
|
|
description: "For growing teams that need more power.",
|
|
features: ["Up to 50 team members", "Unlimited projects", "Advanced analytics", "Priority support", "50 GB storage", "Custom workflows", "API access"],
|
|
cta: "Start Free Trial",
|
|
popular: true,
|
|
},
|
|
{
|
|
name: "Enterprise",
|
|
monthlyPrice: 199,
|
|
annualPrice: 159,
|
|
description: "For organizations with advanced needs.",
|
|
features: ["Unlimited team members", "Unlimited projects", "AI-powered analytics", "24/7 dedicated support", "Unlimited storage", "Custom workflows", "API access", "SSO & SAML", "Custom SLA"],
|
|
cta: "Contact Sales",
|
|
popular: false,
|
|
},
|
|
];
|
|
|
|
const comparisonFeatures = [
|
|
{ name: "Team members", starter: "10", pro: "50", enterprise: "Unlimited" },
|
|
{ name: "Projects", starter: "5", pro: "Unlimited", enterprise: "Unlimited" },
|
|
{ name: "Storage", starter: "1 GB", pro: "50 GB", enterprise: "Unlimited" },
|
|
{ name: "Unlimited projects", starter: false, pro: true, enterprise: true },
|
|
{ name: "API access", starter: false, pro: true, enterprise: true },
|
|
{ name: "Priority support", starter: false, pro: true, enterprise: true },
|
|
{ name: "Custom integrations", starter: false, pro: true, enterprise: true },
|
|
{ name: "SSO/SAML", starter: false, pro: false, enterprise: true },
|
|
{ name: "Dedicated manager", starter: false, pro: false, enterprise: true },
|
|
];
|
|
|
|
const faqs = [
|
|
{ q: "Can I try Nexus for free?", a: "Yes! Every plan comes with a 14-day free trial. No credit card required to get started." },
|
|
{ q: "Can I switch plans later?", a: "Absolutely. You can upgrade or downgrade your plan at any time. Changes take effect immediately." },
|
|
{ q: "What payment methods do you accept?", a: "We accept all major credit cards, ACH bank transfers, and wire transfers for Enterprise plans." },
|
|
{ q: "Is there a discount for nonprofits?", a: "Yes, we offer a 50% discount for registered nonprofits and educational institutions. Contact sales for details." },
|
|
{ q: "How does the AI task automation work?", a: "Our AI learns from your team patterns and automatically suggests task assignments, priorities, and deadlines based on historical data." },
|
|
{ q: "What happens when my trial ends?", a: "Your data is saved for 30 days after trial expiry. Choose a plan to continue, or export your data at any time." },
|
|
];
|
|
|
|
export default function PricingPage() {
|
|
const [billing, setBilling] = useState("monthly");
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white text-slate-900 antialiased">
|
|
<Header />
|
|
|
|
{/* ── HERO ── */}
|
|
<section className="pt-32 pb-16 bg-gradient-to-b from-slate-50 to-white">
|
|
<div className="mx-auto max-w-7xl px-6 text-center">
|
|
<Badge className="mb-4 bg-indigo-50 text-indigo-600 border-0">Pricing</Badge>
|
|
<h1 className="animate-fade-up text-4xl font-bold tracking-tight sm:text-5xl">Simple, transparent pricing</h1>
|
|
<p className="mt-4 text-lg text-slate-500 max-w-2xl mx-auto">No hidden fees. No surprise charges. Choose the plan that fits your team.</p>
|
|
<div className="mt-8 flex justify-center">
|
|
<Tabs value={billing} onValueChange={setBilling} className="bg-slate-100 rounded-full p-1">
|
|
<TabsList className="bg-transparent">
|
|
<TabsTrigger value="monthly" className="rounded-full px-6 data-[state=active]:bg-white data-[state=active]:shadow-sm">Monthly</TabsTrigger>
|
|
<TabsTrigger value="annual" className="rounded-full px-6 data-[state=active]:bg-white data-[state=active]:shadow-sm">
|
|
Annual <Badge className="ml-2 bg-green-100 text-green-700 border-0 text-xs">Save 20%</Badge>
|
|
</TabsTrigger>
|
|
</TabsList>
|
|
</Tabs>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── PRICING CARDS ── */}
|
|
<section className="pb-24">
|
|
<div className="mx-auto max-w-7xl px-6">
|
|
<div className="grid md:grid-cols-3 gap-6 max-w-5xl mx-auto stagger">
|
|
{tiers.map((tier) => (
|
|
<Card key={tier.name} className={`relative flex flex-col hover:border-primary/50 hover:shadow-xl transition-all duration-300 \${tier.popular ? "ring-2 ring-indigo-600 shadow-xl shadow-indigo-100" : "border-slate-200"}`}>
|
|
{tier.popular && (
|
|
<div className="absolute -top-4 left-1/2 -translate-x-1/2 bg-primary text-primary-foreground px-4 py-1 rounded-full text-sm font-medium shadow-lg flex items-center gap-1.5">
|
|
<Sparkles className="h-3.5 w-3.5" /> Most Popular
|
|
</div>
|
|
)}
|
|
<CardHeader className="pb-4 pt-8">
|
|
<CardTitle className="text-xl">{tier.name}</CardTitle>
|
|
<p className="text-sm text-slate-500 mt-1">{tier.description}</p>
|
|
<div className="mt-4">
|
|
<span className="text-4xl font-bold">\${billing === "monthly" ? tier.monthlyPrice : tier.annualPrice}</span>
|
|
<span className="text-slate-500 ml-1">/mo</span>
|
|
</div>
|
|
{billing === "annual" && (
|
|
<p className="text-sm text-green-600 mt-1">Billed annually (\${tier.annualPrice * 12}/yr)</p>
|
|
)}
|
|
</CardHeader>
|
|
<CardContent className="flex-1 flex flex-col">
|
|
<ul className="space-y-3 flex-1">
|
|
{tier.features.map((f) => (
|
|
<li key={f} className="flex items-center gap-2 text-sm">
|
|
<Check className="h-4 w-4 text-indigo-600 flex-shrink-0" />
|
|
<span>{f}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<Button asChild className={`mt-8 w-full rounded-full active:scale-[0.98] \${tier.popular ? "bg-indigo-600 hover:bg-indigo-500 text-white" : ""}`} variant={tier.popular ? "default" : "outline"}>
|
|
<Link to={tier.name === "Enterprise" ? "/contact" : "/signup"}>{tier.cta}</Link>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
<p className="text-center mt-8 text-sm text-slate-500 flex items-center justify-center gap-1.5">
|
|
<Shield className="h-4 w-4 text-indigo-500" /> 30-day money-back guarantee. No questions asked.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── COMPARISON TABLE ── */}
|
|
<section className="py-24 bg-slate-50">
|
|
<div className="mx-auto max-w-5xl px-6">
|
|
<h2 className="animate-fade-up text-3xl font-bold text-center mb-12 tracking-tight sm:text-4xl">Compare Plans</h2>
|
|
<Card className="overflow-hidden border-slate-200">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow className="bg-slate-50">
|
|
<TableHead className="w-1/3 font-semibold">Feature</TableHead>
|
|
<TableHead className="text-center font-semibold">Free</TableHead>
|
|
<TableHead className="text-center font-semibold text-indigo-600">Pro</TableHead>
|
|
<TableHead className="text-center font-semibold">Enterprise</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{comparisonFeatures.map((f) => (
|
|
<TableRow key={f.name}>
|
|
<TableCell className="font-medium">{f.name}</TableCell>
|
|
<TableCell className="text-center">
|
|
{typeof f.starter === "boolean" ? (f.starter ? <Check className="h-4 w-4 text-green-500 mx-auto" /> : <X className="h-4 w-4 text-slate-300 mx-auto" />) : f.starter}
|
|
</TableCell>
|
|
<TableCell className="text-center bg-indigo-50/50">
|
|
{typeof f.pro === "boolean" ? (f.pro ? <Check className="h-4 w-4 text-green-500 mx-auto" /> : <X className="h-4 w-4 text-slate-300 mx-auto" />) : f.pro}
|
|
</TableCell>
|
|
<TableCell className="text-center">
|
|
{typeof f.enterprise === "boolean" ? (f.enterprise ? <Check className="h-4 w-4 text-green-500 mx-auto" /> : <X className="h-4 w-4 text-slate-300 mx-auto" />) : f.enterprise}
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</Card>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── FAQ ── */}
|
|
<section className="py-24 bg-white">
|
|
<div className="mx-auto max-w-3xl px-6">
|
|
<h2 className="animate-fade-up text-3xl font-bold text-center mb-12 tracking-tight sm:text-4xl">Frequently Asked Questions</h2>
|
|
<Accordion type="single" collapsible className="space-y-3 stagger">
|
|
{faqs.map((faq, i) => (
|
|
<AccordionItem key={i} value={`faq-\${i}`} className="border border-slate-200 rounded-xl px-6 data-[state=open]:shadow-md transition-shadow">
|
|
<AccordionTrigger className="text-left font-medium hover:no-underline py-4">{faq.q}</AccordionTrigger>
|
|
<AccordionContent className="text-slate-500 pb-4">{faq.a}</AccordionContent>
|
|
</AccordionItem>
|
|
))}
|
|
</Accordion>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── CTA ── */}
|
|
<section className="py-24 bg-gradient-to-br from-indigo-600 to-slate-900">
|
|
<div className="mx-auto max-w-3xl px-6 text-center">
|
|
<h2 className="animate-fade-up text-3xl font-bold text-white sm:text-4xl">Start your free trial today</h2>
|
|
<p className="mt-4 text-indigo-200">14 days free. No credit card required. Cancel anytime.</p>
|
|
<Button asChild size="lg" className="active:scale-[0.98] mt-8 bg-white text-indigo-700 hover:bg-indigo-50 rounded-full px-8 shadow-lg font-semibold">
|
|
<Link to="/signup">Start Free Trial <ArrowRight className="ml-2 h-4 w-4" /></Link>
|
|
</Button>
|
|
</div>
|
|
</section>
|
|
|
|
<Footer />
|
|
</div>
|
|
);
|
|
}
|