Initial: saas template via tAI

This commit is contained in:
Joe Wee
2026-05-21 12:02:13 +01:00
commit 1cd690d7a3
24 changed files with 2401 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { ArrowRight, Linkedin, Heart, Target, Lightbulb, Users } from "lucide-react";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
const team = [
{ name: "Alex Kim", role: "Co-Founder & CEO", initials: "AK" },
{ name: "Sophia Patel", role: "Co-Founder & CTO", initials: "SP" },
{ name: "James Moreno", role: "VP of Engineering", initials: "JM" },
{ name: "Lena Chen", role: "Head of Design", initials: "LC" },
];
const values = [
{ icon: Target, title: "Customer Obsessed", desc: "Every decision starts with what is best for our users." },
{ icon: Lightbulb, title: "Relentlessly Innovative", desc: "We push the boundaries of what project management can be." },
{ icon: Heart, title: "People First", desc: "We build for humans, and we treat our team as family." },
{ icon: Users, title: "Radically Transparent", desc: "Open roadmaps, public changelogs, and honest communication." },
];
const milestones = [
{ year: "2020", event: "Founded in San Francisco by two ex-Google engineers" },
{ year: "2021", event: "Launched beta with 500 early adopter teams" },
{ year: "2022", event: "Series A: $18M raised, 5,000 teams onboarded" },
{ year: "2023", event: "AI Copilot launched, crossed 10,000 teams" },
{ year: "2024", event: "Series B: $45M raised, expanded to 150+ countries" },
];
export default function AboutPage() {
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">About Us</Badge>
<h1 className="animate-fade-up text-4xl font-bold tracking-tight sm:text-5xl">We are building the future of work</h1>
<p className="mt-4 text-lg text-slate-500 max-w-2xl mx-auto">
Nexus was born from a simple belief: teams deserve tools that work as hard as they do. We are a team of engineers, designers, and dreamers on a mission to make work feel effortless.
</p>
</div>
</section>
{/* ── MISSION ── */}
<section className="py-24 bg-white">
<div className="mx-auto max-w-7xl px-6">
<div className="grid lg:grid-cols-2 gap-16 items-center">
<div>
<Badge className="mb-4 bg-cyan-50 text-cyan-600 border-0">Our Mission</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight">Empower every team to do their best work</h2>
<p className="mt-6 text-slate-500 leading-relaxed text-lg">We believe that great software should amplify human potential, not replace it. Nexus combines the best of AI with intuitive design so teams can focus on what matters most: building great products.</p>
<Button asChild className="active:scale-[0.98] mt-8 rounded-full bg-indigo-600 hover:bg-indigo-500">
<Link to="/features">See What We Built <ArrowRight className="ml-2 h-4 w-4" /></Link>
</Button>
</div>
<div className="animate-scale-in aspect-[4/3] rounded-2xl bg-gradient-to-br from-indigo-100 via-cyan-50 to-slate-100 flex items-center justify-center relative overflow-hidden">
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wMyI+PGNpcmNsZSBjeD0iMSIgY3k9IjEiIHI9IjEiLz48L2c+PC9nPjwvc3ZnPg==')] opacity-60" />
<div className="absolute -top-10 -right-10 w-40 h-40 rounded-full bg-indigo-300/30 blur-3xl" />
<div className="absolute -bottom-10 -left-10 w-32 h-32 rounded-full bg-cyan-300/30 blur-3xl" />
<span className="relative text-slate-400 text-sm">Mission Image</span>
</div>
</div>
</div>
</section>
{/* ── TEAM ── */}
<section className="py-24 bg-slate-50">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-indigo-50 text-indigo-600 border-0">Our Team</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight">Meet the people behind Nexus</h2>
</div>
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-8 stagger">
{team.map((member) => (
<Card key={member.name} className="hover-card-lift border-slate-200 text-center hover:shadow-lg transition-all duration-300">
<CardContent className="p-8">
<Avatar className="h-20 w-20 mx-auto mb-4">
<AvatarFallback className="bg-gradient-to-br from-indigo-500 to-cyan-500 text-white text-xl font-bold">{member.initials}</AvatarFallback>
</Avatar>
<h3 className="font-semibold text-lg">{member.name}</h3>
<p className="text-sm text-slate-500 mt-1">{member.role}</p>
<a href="#" className="inline-flex items-center gap-1 mt-4 text-indigo-600 hover:text-indigo-700 text-sm">
<Linkedin className="h-4 w-4" /> LinkedIn
</a>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* ── VALUES ── */}
<section className="py-24 bg-white">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-amber-50 text-amber-600 border-0">Our Values</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight">What drives us every day</h2>
</div>
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-6 stagger">
{values.map((v) => (
<Card key={v.title} className="hover-card-lift border-slate-200 hover:border-indigo-200 hover:shadow-lg transition-all duration-300">
<CardContent className="p-6">
<div className="h-12 w-12 rounded-xl bg-gradient-to-br from-indigo-500 to-cyan-500 flex items-center justify-center mb-4">
<v.icon className="h-6 w-6 text-white" />
</div>
<h3 className="font-semibold mb-2">{v.title}</h3>
<p className="text-sm text-slate-500">{v.desc}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* ── TIMELINE ── */}
<section className="py-24 bg-slate-50">
<div className="mx-auto max-w-3xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-indigo-50 text-indigo-600 border-0">Our Journey</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight">Company milestones</h2>
</div>
<div className="relative">
<div className="absolute left-4 top-0 bottom-0 w-px bg-gradient-to-b from-indigo-500 to-cyan-500" />
<div className="space-y-10">
{milestones.map((m) => (
<div key={m.year} className="flex gap-6 items-start">
<div className="relative flex-shrink-0 h-9 w-9 rounded-full bg-indigo-600 flex items-center justify-center text-white text-xs font-bold ring-4 ring-white">
{m.year.slice(2)}
</div>
<div className="pt-1">
<span className="text-sm font-bold text-indigo-600">{m.year}</span>
<p className="text-slate-600 mt-1">{m.event}</p>
</div>
</div>
))}
</div>
</div>
</div>
</section>
<Footer />
</div>
);
}
+127
View File
@@ -0,0 +1,127 @@
import Sidebar from "@/components/Sidebar";
import DashboardHeader from "@/components/DashboardHeader";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts";
const growthData = [
{ month: "Jul", users: 1200 }, { month: "Aug", users: 1800 },
{ month: "Sep", users: 2400 }, { month: "Oct", users: 3100 },
{ month: "Nov", users: 3900 }, { month: "Dec", users: 4800 },
];
const funnel = [
{ label: "Visitors", value: 12450, pct: 100 },
{ label: "Signups", value: 3200, pct: 25.7 },
{ label: "Trials", value: 1840, pct: 14.8 },
{ label: "Paid", value: 920, pct: 7.4 },
];
const engagement = [
{ label: "DAU", value: "1,247" },
{ label: "WAU", value: "4,832" },
{ label: "MAU", value: "12,450" },
{ label: "Avg Session", value: "4m 32s" },
];
const topPages = [
{ page: "Dashboard", views: 8420, unique: 3210, bounce: "24%" },
{ page: "Analytics", views: 5340, unique: 2180, bounce: "31%" },
{ page: "Settings", views: 3120, unique: 1540, bounce: "18%" },
{ page: "API Docs", views: 2890, unique: 1320, bounce: "42%" },
{ page: "Billing", views: 2140, unique: 980, bounce: "15%" },
];
export default function AnalyticsPage() {
return (
<div className="flex min-h-screen bg-slate-50">
<Sidebar activePath="/analytics" />
<div className="flex-1 lg:ml-64">
<DashboardHeader />
<main className="p-6 space-y-6">
{/* User Growth Chart */}
<Card>
<CardHeader>
<CardTitle>User Growth</CardTitle>
</CardHeader>
<CardContent>
<div className="h-72">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={growthData}>
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
<XAxis dataKey="month" stroke="#94a3b8" fontSize={12} />
<YAxis stroke="#94a3b8" fontSize={12} />
<Tooltip />
<Area type="monotone" dataKey="users" stroke="#6366f1" fill="#6366f1" fillOpacity={0.15} />
</AreaChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
{/* Conversion Funnel */}
<Card>
<CardHeader>
<CardTitle>Conversion Funnel</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{funnel.map((step) => (
<div key={step.label} className="space-y-1">
<div className="flex items-center justify-between text-sm">
<span className="font-medium">{step.label}</span>
<span className="text-slate-500">{step.value.toLocaleString()} ({step.pct}%)</span>
</div>
<div className="h-3 bg-slate-100 rounded-full overflow-hidden">
<div className="h-full bg-indigo-500 rounded-full transition-all" style={{ width: `\${step.pct}%` }} />
</div>
</div>
))}
</CardContent>
</Card>
{/* Engagement Grid */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
{engagement.map((e) => (
<Card key={e.label}>
<CardContent className="p-6 text-center">
<p className="text-sm text-slate-500">{e.label}</p>
<p className="text-2xl font-bold mt-1">{e.value}</p>
</CardContent>
</Card>
))}
</div>
{/* Top Pages Table */}
<Card>
<CardHeader>
<CardTitle>Top Pages</CardTitle>
</CardHeader>
<CardContent>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-slate-200">
<th className="text-left py-3 px-4 font-medium text-slate-500">Page</th>
<th className="text-left py-3 px-4 font-medium text-slate-500">Views</th>
<th className="text-left py-3 px-4 font-medium text-slate-500">Unique Visitors</th>
<th className="text-left py-3 px-4 font-medium text-slate-500">Bounce Rate</th>
</tr>
</thead>
<tbody>
{topPages.map((p) => (
<tr key={p.page} className="border-b border-slate-100 last:border-0">
<td className="py-3 px-4 font-medium">{p.page}</td>
<td className="py-3 px-4 text-slate-600">{p.views.toLocaleString()}</td>
<td className="py-3 px-4 text-slate-600">{p.unique.toLocaleString()}</td>
<td className="py-3 px-4 text-slate-600">{p.bounce}</td>
</tr>
))}
</tbody>
</table>
</div>
</CardContent>
</Card>
</main>
</div>
</div>
);
}
+142
View File
@@ -0,0 +1,142 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
const categories = ["All", "Product", "Engineering", "Company", "Guides"];
const articles = [
{
title: "How AI is Reshaping Project Management in 2025",
excerpt: "Discover how machine learning is automating the mundane and freeing teams to focus on creative work.",
category: "Product",
author: "Alex Kim",
initials: "AK",
date: "Mar 15, 2025",
gradient: "from-indigo-500 to-purple-600",
},
{
title: "Building a Culture of Asynchronous Collaboration",
excerpt: "Why the best distributed teams invest in async-first workflows and how you can too.",
category: "Guides",
author: "Sophia Patel",
initials: "SP",
date: "Mar 8, 2025",
gradient: "from-cyan-500 to-blue-600",
},
{
title: "Our Journey to SOC 2 Type II Compliance",
excerpt: "A behind-the-scenes look at how we achieved enterprise-grade security certification.",
category: "Engineering",
author: "James Moreno",
initials: "JM",
date: "Feb 28, 2025",
gradient: "from-emerald-500 to-teal-600",
},
{
title: "Introducing Custom Workflow Automations",
excerpt: "Build powerful no-code automations that save your team hours every week.",
category: "Product",
author: "Lena Chen",
initials: "LC",
date: "Feb 20, 2025",
gradient: "from-amber-500 to-orange-600",
},
{
title: "Scaling from 10 to 10,000 Teams: Lessons Learned",
excerpt: "The architectural decisions and trade-offs we made during our hyper-growth phase.",
category: "Engineering",
author: "Sophia Patel",
initials: "SP",
date: "Feb 12, 2025",
gradient: "from-rose-500 to-pink-600",
},
{
title: "The Future of Work is Hybrid: Our Playbook",
excerpt: "How we keep our own team productive across 12 time zones and 4 continents.",
category: "Company",
author: "Alex Kim",
initials: "AK",
date: "Feb 5, 2025",
gradient: "from-violet-500 to-indigo-600",
},
];
export default function BlogPage() {
const [activeCategory, setActiveCategory] = useState("All");
const filtered = activeCategory === "All" ? articles : articles.filter((a) => a.category === activeCategory);
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">Blog</Badge>
<h1 className="animate-fade-up text-4xl font-bold tracking-tight sm:text-5xl">Insights & Updates</h1>
<p className="mt-4 text-lg text-slate-500 max-w-2xl mx-auto">
Product news, engineering deep-dives, and guides from the Nexus team.
</p>
</div>
</section>
{/* ── CONTENT ── */}
<section className="py-24">
<div className="mx-auto max-w-7xl px-6">
<div className="flex flex-wrap gap-2 mb-12 justify-center">
{categories.map((cat) => (
<Button
key={cat}
variant={activeCategory === cat ? "default" : "outline"}
size="sm"
className={`rounded-full \${activeCategory === cat ? "bg-indigo-600 hover:bg-indigo-500" : ""}`}
onClick={() => setActiveCategory(cat)}
>
{cat}
</Button>
))}
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 stagger">
{filtered.map((article) => (
<Card key={article.title} className="overflow-hidden border-slate-200 hover:-translate-y-1 hover:shadow-xl hover:border-indigo-200 transition-all duration-300 group cursor-pointer">
<div className={`aspect-[16/9] bg-gradient-to-br \${article.gradient} flex items-center justify-center relative overflow-hidden`}>
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wMyI+PGNpcmNsZSBjeD0iMSIgY3k9IjEiIHI9IjEiLz48L2c+PC9nPjwvc3ZnPg==')] opacity-60" />
<div className="absolute -top-8 -right-8 w-32 h-32 rounded-full bg-white/10 blur-3xl" />
<div className="absolute -bottom-8 -left-8 w-24 h-24 rounded-full bg-white/10 blur-3xl" />
<span className="relative text-white/40 text-sm">Article Image</span>
</div>
<CardContent className="p-6">
<Badge className="mb-3 bg-slate-100 text-slate-600 border-0 text-xs">{article.category}</Badge>
<h3 className="font-semibold text-lg leading-tight group-hover:text-indigo-600 transition-colors">{article.title}</h3>
<p className="mt-2 text-sm text-slate-500 line-clamp-2">{article.excerpt}</p>
<div className="mt-4 flex items-center gap-3">
<Avatar className="h-8 w-8">
<AvatarFallback className="bg-gradient-to-br from-indigo-400 to-cyan-400 text-white text-xs">{article.initials}</AvatarFallback>
</Avatar>
<div>
<div className="text-sm font-medium">{article.author}</div>
<div className="text-xs text-slate-400">{article.date}</div>
</div>
</div>
</CardContent>
</Card>
))}
</div>
<div className="mt-12 text-center">
<Button variant="outline" className="active:scale-[0.98] rounded-full px-8">Load More Articles</Button>
</div>
</div>
</section>
<Footer />
</div>
);
}
+154
View File
@@ -0,0 +1,154 @@
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Badge } from "@/components/ui/badge";
import { Mail, Phone, MapPin, Send, CheckCircle2 } from "lucide-react";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
export default function ContactPage() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [company, setCompany] = useState("");
const [subject, setSubject] = useState("");
const [message, setMessage] = useState("");
const [success, setSuccess] = useState(false);
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">Contact</Badge>
<h1 className="animate-fade-up text-4xl font-bold tracking-tight sm:text-5xl">Get in touch</h1>
<p className="mt-4 text-lg text-slate-500 max-w-2xl mx-auto">
Have questions? We would love to hear from you. Our team typically responds within 24 hours.
</p>
</div>
</section>
{/* ── CONTACT SPLIT ── */}
<section className="py-24">
<div className="mx-auto max-w-7xl px-6">
<div className="grid lg:grid-cols-5 gap-12">
{/* Left — Info */}
<div className="lg:col-span-2 space-y-8">
<div>
<h2 className="animate-fade-up text-3xl font-bold mb-4 tracking-tight">Contact Information</h2>
<p className="text-slate-500">Reach out through any of these channels and we will get back to you as soon as possible.</p>
</div>
<div className="space-y-6">
<div className="flex items-start gap-4">
<div className="h-10 w-10 rounded-xl bg-indigo-50 flex items-center justify-center flex-shrink-0">
<Mail className="h-5 w-5 text-indigo-600" />
</div>
<div>
<h3 className="font-semibold text-sm">Email</h3>
<p className="text-slate-500 text-sm mt-0.5">hello@nexus.dev</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="h-10 w-10 rounded-xl bg-indigo-50 flex items-center justify-center flex-shrink-0">
<Phone className="h-5 w-5 text-indigo-600" />
</div>
<div>
<h3 className="font-semibold text-sm">Phone</h3>
<p className="text-slate-500 text-sm mt-0.5">+1 (415) 555-0132</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="h-10 w-10 rounded-xl bg-indigo-50 flex items-center justify-center flex-shrink-0">
<MapPin className="h-5 w-5 text-indigo-600" />
</div>
<div>
<h3 className="font-semibold text-sm">Office</h3>
<p className="text-slate-500 text-sm mt-0.5">100 Market St, Suite 400, San Francisco, CA 94105</p>
</div>
</div>
</div>
</div>
{/* Right — Form */}
<div className="lg:col-span-3">
<Card className="border-slate-200 shadow-lg">
<CardContent className="p-8">
{success && (
<div className="mb-6 flex items-center gap-2 rounded-lg bg-green-50 border border-green-200 px-4 py-3 text-sm text-green-700">
<CheckCircle2 className="h-4 w-4 flex-shrink-0" /> Message sent successfully! We will get back to you within 24 hours.
</div>
)}
<form onSubmit={(e) => { e.preventDefault(); setSuccess(true); toast.success("Message sent! Our team will reach out shortly."); }}>
<div className="grid sm:grid-cols-2 gap-4">
<div>
<Label htmlFor="contact-name" className="text-sm">Name</Label>
<Input id="contact-name" required placeholder="Your name" value={name} onChange={(e) => setName(e.target.value)} className="mt-1.5" />
</div>
<div>
<Label htmlFor="contact-email" className="text-sm">Email</Label>
<Input id="contact-email" type="email" required placeholder="you@company.com" value={email} onChange={(e) => setEmail(e.target.value)} className="mt-1.5" />
</div>
</div>
<div className="mt-4">
<Label htmlFor="contact-company" className="text-sm">Company</Label>
<Input id="contact-company" placeholder="Your company" value={company} onChange={(e) => setCompany(e.target.value)} className="mt-1.5" />
</div>
<div className="mt-4">
<Label htmlFor="contact-subject" className="text-sm">Subject</Label>
<Select value={subject} onValueChange={setSubject}>
<SelectTrigger className="mt-1.5">
<SelectValue placeholder="Select a subject" />
</SelectTrigger>
<SelectContent>
<SelectItem value="general">General Inquiry</SelectItem>
<SelectItem value="sales">Sales</SelectItem>
<SelectItem value="support">Technical Support</SelectItem>
<SelectItem value="partnership">Partnership</SelectItem>
<SelectItem value="press">Press & Media</SelectItem>
</SelectContent>
</Select>
</div>
<div className="mt-4">
<Label htmlFor="contact-message" className="text-sm">Message</Label>
<Textarea
id="contact-message"
required
placeholder="Tell us how we can help..."
value={message}
onChange={(e) => setMessage(e.target.value)}
className="mt-1.5 min-h-[120px]"
/>
</div>
<Button type="submit" className="active:scale-[0.98] mt-6 w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">
<Send className="mr-2 h-4 w-4" /> Send Message
</Button>
</form>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
{/* ── MAP PLACEHOLDER ── */}
<section className="pb-24">
<div className="mx-auto max-w-7xl px-6">
<div className="animate-scale-in h-64 rounded-2xl bg-gradient-to-br from-slate-100 to-slate-200 flex items-center justify-center relative overflow-hidden">
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wMyI+PGNpcmNsZSBjeD0iMSIgY3k9IjEiIHI9IjEiLz48L2c+PC9nPjwvc3ZnPg==')] opacity-60" />
<div className="absolute -top-10 -right-10 w-40 h-40 rounded-full bg-indigo-200/30 blur-3xl" />
<div className="absolute -bottom-10 -left-10 w-32 h-32 rounded-full bg-cyan-200/30 blur-3xl" />
<span className="relative text-slate-400 text-sm">Map Placeholder</span>
</div>
</div>
</section>
<Footer />
</div>
);
}
+120
View File
@@ -0,0 +1,120 @@
import { useState } from "react";
import Sidebar from "@/components/Sidebar";
import DashboardHeader from "@/components/DashboardHeader";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Search } from "lucide-react";
const filters = ["All", "Active", "Trial", "Churned"];
const customers = [
{ name: "Sarah Chen", email: "sarah@acme.co", plan: "Enterprise", mrr: "\$299", joined: "Jan 12, 2024", status: "active", initials: "SC" },
{ name: "Marcus Johnson", email: "marcus@startup.io", plan: "Pro", mrr: "\$49", joined: "Feb 8, 2024", status: "active", initials: "MJ" },
{ name: "Emily Rivera", email: "emily@design.co", plan: "Pro", mrr: "\$49", joined: "Mar 15, 2024", status: "trial", initials: "ER" },
{ name: "David Kim", email: "david@tech.dev", plan: "Enterprise", mrr: "\$299", joined: "Apr 3, 2024", status: "active", initials: "DK" },
{ name: "Anna Petrov", email: "anna@agency.com", plan: "Free", mrr: "\$0", joined: "May 20, 2024", status: "churned", initials: "AP" },
{ name: "James Wright", email: "james@corp.biz", plan: "Pro", mrr: "\$49", joined: "Jun 1, 2024", status: "active", initials: "JW" },
{ name: "Lisa Nguyen", email: "lisa@creative.co", plan: "Enterprise", mrr: "\$299", joined: "Jul 14, 2024", status: "active", initials: "LN" },
{ name: "Tom Bradley", email: "tom@labs.io", plan: "Free", mrr: "\$0", joined: "Aug 22, 2024", status: "trial", initials: "TB" },
];
export default function CustomersPage() {
const [activeFilter, setActiveFilter] = useState("All");
const [search, setSearch] = useState("");
const filtered = customers.filter((c) => {
if (activeFilter !== "All" && c.status !== activeFilter.toLowerCase()) return false;
if (search && !c.name.toLowerCase().includes(search.toLowerCase()) && !c.email.toLowerCase().includes(search.toLowerCase())) return false;
return true;
});
return (
<div className="flex min-h-screen bg-slate-50">
<Sidebar activePath="/customers" />
<div className="flex-1 lg:ml-64">
<DashboardHeader />
<main className="p-6 space-y-6">
<Card>
<CardHeader>
<CardTitle>Customers</CardTitle>
</CardHeader>
<CardContent>
{/* Search & Filters */}
<div className="flex flex-col sm:flex-row gap-4 mb-6">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-slate-400" />
<Input
placeholder="Search customers..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="pl-9"
/>
</div>
<div className="flex gap-2">
{filters.map((f) => (
<Button
key={f}
variant={activeFilter === f ? "default" : "outline"}
size="sm"
onClick={() => setActiveFilter(f)}
>
{f}
</Button>
))}
</div>
</div>
{/* Table */}
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Plan</TableHead>
<TableHead>MRR</TableHead>
<TableHead>Joined</TableHead>
<TableHead>Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filtered.map((c, i) => (
<TableRow key={i}>
<TableCell>
<div className="flex items-center gap-3">
<Avatar className="h-8 w-8">
<AvatarFallback className="bg-indigo-100 text-indigo-600 text-xs">{c.initials}</AvatarFallback>
</Avatar>
<div>
<p className="font-medium">{c.name}</p>
<p className="text-xs text-slate-400">{c.email}</p>
</div>
</div>
</TableCell>
<TableCell>
<Badge variant={c.plan === "Enterprise" ? "default" : c.plan === "Pro" ? "secondary" : "outline"}>
{c.plan}
</Badge>
</TableCell>
<TableCell className="font-medium">{c.mrr}</TableCell>
<TableCell className="text-slate-500">{c.joined}</TableCell>
<TableCell>
<Badge variant={c.status === "active" ? "default" : c.status === "trial" ? "secondary" : "destructive"}>
{c.status}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
<p className="text-sm text-slate-400 mt-4">Showing {filtered.length} of {customers.length} customers</p>
</CardContent>
</Card>
</main>
</div>
</div>
);
}
+172
View File
@@ -0,0 +1,172 @@
import Sidebar from "@/components/Sidebar";
import DashboardHeader from "@/components/DashboardHeader";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { DollarSign, Users, TrendingDown, ThumbsUp, ArrowUpRight, ArrowDownRight, Plus, UserPlus, Download } from "lucide-react";
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts";
const kpis = [
{ label: "MRR", value: "\$48,250", trend: "+12.5%", up: true, icon: DollarSign, color: "bg-sky-100 text-sky-600" },
{ label: "Active Users", value: "2,847", trend: "+8.2%", up: true, icon: Users, color: "bg-emerald-100 text-emerald-600" },
{ label: "Churn Rate", value: "2.4%", trend: "-0.3%", up: false, icon: TrendingDown, color: "bg-orange-100 text-orange-600" },
{ label: "NPS", value: "72", trend: "+4", up: true, icon: ThumbsUp, color: "bg-violet-100 text-violet-600" },
];
const revenueData = [
{ month: "Jan", revenue: 32000 }, { month: "Feb", revenue: 34500 },
{ month: "Mar", revenue: 36200 }, { month: "Apr", revenue: 38100 },
{ month: "May", revenue: 37800 }, { month: "Jun", revenue: 39500 },
{ month: "Jul", revenue: 41200 }, { month: "Aug", revenue: 43000 },
{ month: "Sep", revenue: 44800 }, { month: "Oct", revenue: 45200 },
{ month: "Nov", revenue: 46900 }, { month: "Dec", revenue: 48250 },
];
const activities = [
{ name: "Sarah Chen", action: "Upgraded to Pro", date: "2 hours ago", status: "completed", initials: "SC" },
{ name: "Marcus Johnson", action: "Created new project", date: "4 hours ago", status: "completed", initials: "MJ" },
{ name: "Emily Rivera", action: "Submitted support ticket", date: "5 hours ago", status: "pending", initials: "ER" },
{ name: "David Kim", action: "Payment processed", date: "6 hours ago", status: "completed", initials: "DK" },
{ name: "Anna Petrov", action: "Account deactivated", date: "8 hours ago", status: "failed", initials: "AP" },
{ name: "James Wright", action: "Invited team member", date: "10 hours ago", status: "completed", initials: "JW" },
{ name: "Lisa Nguyen", action: "Exported data", date: "12 hours ago", status: "completed", initials: "LN" },
{ name: "Tom Bradley", action: "Updated billing info", date: "1 day ago", status: "pending", initials: "TB" },
];
export default function DashboardPage() {
return (
<div className="flex min-h-screen bg-slate-50">
<Sidebar activePath="/dashboard" />
<div className="flex-1 lg:ml-64">
<DashboardHeader />
<main className="p-6 space-y-6">
{/* KPI Cards */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{kpis.map((kpi) => {
const Icon = kpi.icon;
return (
<Card key={kpi.label}>
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-slate-500">{kpi.label}</p>
<p className="text-2xl font-bold mt-1">{kpi.value}</p>
</div>
<div className={`h-10 w-10 rounded-full flex items-center justify-center \${kpi.color}`}>
<Icon className="h-5 w-5" />
</div>
</div>
<div className="flex items-center gap-1 mt-2 text-sm">
{kpi.up ? <ArrowUpRight className="h-4 w-4 text-emerald-500" /> : <ArrowDownRight className="h-4 w-4 text-emerald-500" />}
<span className="text-emerald-600 font-medium">{kpi.trend}</span>
<span className="text-slate-400">vs last month</span>
</div>
</CardContent>
</Card>
);
})}
</div>
{/* Revenue Chart */}
<Card>
<CardHeader>
<CardTitle>Revenue Overview</CardTitle>
</CardHeader>
<CardContent>
<div className="h-80">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={revenueData}>
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
<XAxis dataKey="month" stroke="#94a3b8" fontSize={12} />
<YAxis stroke="#94a3b8" fontSize={12} />
<Tooltip />
<Bar dataKey="revenue" fill="#6366f1" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
{/* Recent Activity */}
<Card>
<CardHeader>
<CardTitle>Recent Activity</CardTitle>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>User</TableHead>
<TableHead>Action</TableHead>
<TableHead>Date</TableHead>
<TableHead>Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{activities.map((a, i) => (
<TableRow key={i}>
<TableCell>
<div className="flex items-center gap-3">
<Avatar className="h-8 w-8">
<AvatarFallback className="bg-indigo-100 text-indigo-600 text-xs">{a.initials}</AvatarFallback>
</Avatar>
<span className="font-medium">{a.name}</span>
</div>
</TableCell>
<TableCell className="text-slate-500">{a.action}</TableCell>
<TableCell className="text-slate-400">{a.date}</TableCell>
<TableCell>
<Badge variant={a.status === "completed" ? "default" : a.status === "pending" ? "secondary" : "destructive"}>
{a.status}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
{/* Quick Actions */}
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
<Card className="cursor-pointer hover:shadow-md transition-shadow">
<CardContent className="p-6 flex items-center gap-4">
<div className="h-10 w-10 rounded-full bg-indigo-100 flex items-center justify-center">
<Plus className="h-5 w-5 text-indigo-600" />
</div>
<div>
<p className="font-semibold">New Project</p>
<p className="text-sm text-slate-500">Create a new project</p>
</div>
</CardContent>
</Card>
<Card className="cursor-pointer hover:shadow-md transition-shadow">
<CardContent className="p-6 flex items-center gap-4">
<div className="h-10 w-10 rounded-full bg-emerald-100 flex items-center justify-center">
<UserPlus className="h-5 w-5 text-emerald-600" />
</div>
<div>
<p className="font-semibold">Invite Team</p>
<p className="text-sm text-slate-500">Add team members</p>
</div>
</CardContent>
</Card>
<Card className="cursor-pointer hover:shadow-md transition-shadow">
<CardContent className="p-6 flex items-center gap-4">
<div className="h-10 w-10 rounded-full bg-violet-100 flex items-center justify-center">
<Download className="h-5 w-5 text-violet-600" />
</div>
<div>
<p className="font-semibold">Export Report</p>
<p className="text-sm text-slate-500">Download analytics</p>
</div>
</CardContent>
</Card>
</div>
</main>
</div>
</div>
);
}
+146
View File
@@ -0,0 +1,146 @@
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import {
ArrowRight, CheckCircle2, Zap, Shield, BarChart3, Users,
Layers, Globe, Workflow, BrainCircuit, GitBranch, Blocks
} from "lucide-react";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
const featureSections = [
{
badge: "Automation",
title: "Intelligent Automation That Learns",
desc: "Our AI engine observes how your team works and continuously optimizes task routing, resource allocation, and sprint planning.",
bullets: [
"AI-powered task assignment based on team capacity and expertise",
"Automated status updates and progress tracking",
"Smart deadline predictions using historical sprint data",
],
icon: BrainCircuit,
gradient: "from-indigo-500 to-purple-600",
},
{
badge: "Collaboration",
title: "Collaboration Without Boundaries",
desc: "Break down silos with real-time collaboration tools that keep remote, hybrid, and in-office teams perfectly in sync.",
bullets: [
"Real-time document editing with inline comments",
"Video huddles and screen sharing built right in",
"Cross-team visibility with shared project boards",
],
icon: Users,
gradient: "from-cyan-500 to-blue-600",
},
{
badge: "Analytics",
title: "Analytics That Drive Decisions",
desc: "Go beyond vanity metrics. Get actionable insights with AI-powered predictions and automated reporting.",
bullets: [
"Customizable dashboards with drag-and-drop widgets",
"Predictive burn-down charts and velocity tracking",
"Automated weekly reports delivered to your inbox",
],
icon: BarChart3,
gradient: "from-emerald-500 to-teal-600",
},
];
const integrations = [
"Slack", "GitHub", "Figma", "Jira", "Google Drive",
"Notion", "Zoom", "Linear", "Salesforce", "HubSpot", "Stripe", "Zapier",
];
const stats = [
{ value: "10M+", label: "Tasks completed" },
{ value: "200+", label: "Integrations" },
{ value: "150+", label: "Countries" },
{ value: "60%", label: "Faster delivery" },
];
export default function FeaturesPage() {
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-950 via-indigo-950 to-slate-900">
<div className="mx-auto max-w-7xl px-6 text-center">
<Badge className="mb-4 bg-indigo-500/10 text-indigo-300 border border-indigo-500/20">Platform</Badge>
<h1 className="animate-fade-up text-4xl font-bold tracking-tight text-white sm:text-5xl">Platform Features</h1>
<p className="mt-4 text-lg text-slate-400 max-w-2xl mx-auto">
Discover every tool your team needs to plan, build, and ship world-class products.
</p>
</div>
</section>
{/* ── FEATURE SECTIONS (Alternating) ── */}
{featureSections.map((section, i) => (
<section key={section.title} className={`py-24 \${i % 2 === 1 ? "bg-slate-50" : "bg-white"}`}>
<div className="mx-auto max-w-7xl px-6">
<div className="grid lg:grid-cols-2 gap-16 items-center">
<div className={i % 2 === 1 ? "lg:order-2" : ""}>
<Badge className="mb-4 bg-indigo-50 text-indigo-600 border-0">{section.badge}</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight">{section.title}</h2>
<p className="mt-4 text-lg text-slate-500 leading-relaxed">{section.desc}</p>
<ul className="mt-8 space-y-4">
{section.bullets.map((b) => (
<li key={b} className="flex items-start gap-3">
<CheckCircle2 className="h-5 w-5 text-indigo-600 mt-0.5 flex-shrink-0" />
<span className="text-slate-600">{b}</span>
</li>
))}
</ul>
<Button asChild className="active:scale-[0.98] mt-8 rounded-full bg-indigo-600 hover:bg-indigo-500">
<Link to="/pricing">Learn More <ArrowRight className="ml-2 h-4 w-4" /></Link>
</Button>
</div>
<div className={i % 2 === 1 ? "lg:order-1" : ""}>
<div className={`animate-scale-in aspect-[4/3] rounded-2xl bg-gradient-to-br \${section.gradient} flex items-center justify-center shadow-2xl shadow-indigo-500/10 relative overflow-hidden`}>
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wMyI+PGNpcmNsZSBjeD0iMSIgY3k9IjEiIHI9IjEiLz48L2c+PC9nPjwvc3ZnPg==')] opacity-60" />
<div className="absolute -top-10 -right-10 w-40 h-40 rounded-full bg-white/10 blur-3xl" />
<div className="absolute -bottom-10 -left-10 w-32 h-32 rounded-full bg-white/10 blur-3xl" />
<section.icon className="relative h-24 w-24 text-white/30" />
</div>
</div>
</div>
</div>
</section>
))}
{/* ── INTEGRATIONS ── */}
<section className="py-24 bg-white">
<div className="mx-auto max-w-7xl px-6 text-center">
<Badge className="mb-4 bg-cyan-50 text-cyan-600 border-0">Integrations</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight sm:text-4xl">Works with your favorite tools</h2>
<p className="mt-4 text-slate-500 max-w-2xl mx-auto">Connect Nexus to the tools you already use. 200+ integrations and growing.</p>
<div className="mt-12 grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 gap-4 max-w-4xl mx-auto stagger">
{integrations.map((name) => (
<div key={name} className="flex items-center justify-center h-20 rounded-xl border border-slate-200 hover:border-indigo-200 hover:shadow-md hover:scale-110 transition-all duration-300 bg-white">
<span className="text-sm font-medium text-slate-600">{name}</span>
</div>
))}
</div>
</div>
</section>
{/* ── STATS ── */}
<section className="py-20 bg-gradient-to-br from-indigo-600 to-slate-900">
<div className="mx-auto max-w-5xl px-6">
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 text-center">
{stats.map((s) => (
<div key={s.label}>
<div className="text-4xl font-bold text-white">{s.value}</div>
<div className="mt-2 text-sm text-indigo-200">{s.label}</div>
</div>
))}
</div>
</div>
</section>
<Footer />
</div>
);
}
+107
View File
@@ -0,0 +1,107 @@
import { useState } from "react";
import { toast } from "sonner";
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Layers, ArrowLeft, Mail, CheckCircle2, KeyRound } from "lucide-react";
export default function ForgotPasswordPage() {
const [email, setEmail] = useState("");
const [sent, setSent] = useState(false);
const [code, setCode] = useState("");
const [newPassword, setNewPassword] = useState("");
const [step, setStep] = useState<"email" | "code" | "done">("email");
const handleSendCode = (e: React.FormEvent) => {
e.preventDefault();
setSent(true);
toast.success("Reset code sent to " + email);
setStep("code");
};
const handleResetPassword = (e: React.FormEvent) => {
e.preventDefault();
toast.success("Password reset successfully!");
setStep("done");
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-indigo-950 to-slate-900 flex items-center justify-center p-6">
<div className="w-full max-w-md">
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
<div className="h-10 w-10 rounded-xl bg-gradient-to-br from-indigo-500 to-cyan-500 flex items-center justify-center">
<Layers className="h-5 w-5 text-white" />
</div>
<span className="text-2xl font-bold text-white tracking-tight">Nexus</span>
</Link>
<Card className="border-slate-800 bg-slate-900/50 backdrop-blur-xl shadow-2xl">
<CardContent className="p-8">
{step === "email" && (
<>
<div className="text-center mb-8">
<div className="mx-auto w-12 h-12 rounded-full bg-indigo-500/10 flex items-center justify-center mb-4">
<Mail className="h-6 w-6 text-indigo-400" />
</div>
<h1 className="text-2xl font-bold text-white">Forgot password?</h1>
<p className="text-slate-400 mt-1 text-sm">No worries, we'll send you a reset code</p>
</div>
<form onSubmit={handleSendCode} className="space-y-4">
<div>
<Label htmlFor="reset-email" className="text-slate-300 text-sm">Email</Label>
<Input id="reset-email" type="email" required placeholder="you@company.com" value={email} onChange={(e) => setEmail(e.target.value)} className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500" />
</div>
<Button type="submit" className="w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">Send Reset Code</Button>
</form>
</>
)}
{step === "code" && (
<>
<div className="text-center mb-8">
<div className="mx-auto w-12 h-12 rounded-full bg-emerald-500/10 flex items-center justify-center mb-4">
<KeyRound className="h-6 w-6 text-emerald-400" />
</div>
<h1 className="text-2xl font-bold text-white">Enter reset code</h1>
<p className="text-slate-400 mt-1 text-sm">Check your email for a 6-digit code</p>
</div>
<form onSubmit={handleResetPassword} className="space-y-4">
<div>
<Label htmlFor="code" className="text-slate-300 text-sm">Reset Code</Label>
<Input id="code" type="text" required placeholder="000000" maxLength={6} value={code} onChange={(e) => setCode(e.target.value)} className="mt-1.5 bg-slate-800/50 border-slate-700 text-white text-center text-2xl tracking-[0.5em] placeholder:text-slate-500 placeholder:tracking-[0.5em] focus:border-indigo-500" />
</div>
<div>
<Label htmlFor="new-password" className="text-slate-300 text-sm">New Password</Label>
<Input id="new-password" type="password" required placeholder="Enter new password" minLength={8} value={newPassword} onChange={(e) => setNewPassword(e.target.value)} className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500" />
</div>
<Button type="submit" className="w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">Reset Password</Button>
</form>
</>
)}
{step === "done" && (
<div className="text-center py-4">
<div className="mx-auto w-12 h-12 rounded-full bg-emerald-500/10 flex items-center justify-center mb-4">
<CheckCircle2 className="h-6 w-6 text-emerald-400" />
</div>
<h1 className="text-2xl font-bold text-white">Password reset!</h1>
<p className="text-slate-400 mt-2 text-sm">Your password has been reset successfully</p>
<Link to="/login">
<Button className="mt-6 bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-semibold">Back to Sign In</Button>
</Link>
</div>
)}
<div className="mt-6 text-center">
<Link to="/login" className="text-sm text-slate-400 hover:text-white inline-flex items-center gap-1">
<ArrowLeft className="h-3 w-3" /> Back to sign in
</Link>
</div>
</CardContent>
</Card>
</div>
</div>
);
}
+278
View File
@@ -0,0 +1,278 @@
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
ArrowRight, Zap, Shield, BarChart3, Users, Layers, Globe,
Star, CheckCircle2, Sparkles, ChevronRight, Play, Quote, Lock
} from "lucide-react";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
const metrics = [
{ value: "10,000+", label: "Teams worldwide" },
{ value: "99.9%", label: "Uptime SLA" },
{ value: "4.9/5", label: "User rating" },
];
const logos = [
"Acme Corp", "TechFlow", "Quantum",
"Synapse", "NovaBuild", "Orbitix",
];
const features = [
{ icon: Zap, title: "AI Task Automation", desc: "Automatically prioritize, assign, and schedule tasks using machine learning trained on your team habits." },
{ icon: Shield, title: "Enterprise Security", desc: "SOC 2 Type II compliant with end-to-end encryption, SSO, and role-based access controls." },
{ icon: BarChart3, title: "Advanced Analytics", desc: "Real-time dashboards with predictive insights to spot bottlenecks before they happen." },
{ icon: Users, title: "Team Collaboration", desc: "Real-time editing, threaded comments, and @mentions keep everyone aligned." },
{ icon: Layers, title: "Custom Workflows", desc: "Build automation workflows with a drag-and-drop builder. No code required." },
{ icon: Globe, title: "Global Scale", desc: "Multi-region deployment with 99.99% uptime guarantee and <100ms response times." },
];
const steps = [
{ num: "01", title: "Create your workspace", desc: "Sign up in seconds and invite your team. Import existing projects from Jira, Asana, or Trello." },
{ num: "02", title: "Set up your workflows", desc: "Choose from 50+ templates or build custom workflows. Our AI suggests the best setup for your team." },
{ num: "03", title: "Ship with confidence", desc: "Track progress with real-time dashboards. Get AI-powered predictions on delivery timelines." },
];
const testimonials = [
{ name: "Sarah Chen", role: "VP Engineering, TechFlow", quote: "Nexus cut our sprint planning time by 60%. The AI suggestions are scarily accurate.", stars: 5 },
{ name: "Marcus Rivera", role: "CTO, BuildScale", quote: "We migrated from three different tools to Nexus. Best decision we made all year.", stars: 5 },
{ name: "Emily Watson", role: "Product Lead, Orbitix", quote: "The predictive analytics alone are worth the price. We ship 2x faster now.", stars: 5 },
];
export default function IndexPage() {
return (
<div className="min-h-screen bg-white text-slate-900 antialiased">
<Header />
{/* ── HERO ── */}
<section className="relative overflow-hidden bg-gradient-to-br from-slate-950 via-indigo-950 to-slate-900 pt-32 pb-24 sm:pt-40 sm:pb-32">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-indigo-900/20 via-transparent to-transparent" />
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wMyI+PGNpcmNsZSBjeD0iMSIgY3k9IjEiIHI9IjEiLz48L2c+PC9nPjwvc3ZnPg==')] opacity-40" />
{/* Floating gradient blur circles */}
<div className="absolute top-20 left-1/4 w-72 h-72 rounded-full bg-indigo-600/15 blur-[100px] pointer-events-none" />
<div className="absolute top-40 right-1/4 w-96 h-96 rounded-full bg-cyan-500/15 blur-[100px] pointer-events-none" />
<div className="absolute bottom-10 left-1/3 w-80 h-80 rounded-full bg-violet-500/20 blur-[100px] pointer-events-none" />
<div className="absolute -top-10 right-1/3 w-64 h-64 rounded-full bg-blue-500/15 blur-[100px] pointer-events-none" />
<div className="relative mx-auto max-w-7xl px-6 text-center">
<Badge className="animate-fade-up mb-6 bg-primary/10 text-primary border-primary/20 px-4 py-1.5 text-sm font-medium inline-flex items-center">
<Sparkles className="mr-1.5 h-3.5 w-3.5" /> Now with AI Copilot
</Badge>
<h1 className="mx-auto max-w-4xl text-4xl font-bold tracking-tight text-white sm:text-5xl lg:text-7xl">
<span className="bg-gradient-to-r from-white via-indigo-200 to-cyan-200 bg-clip-text text-transparent">
Manage Projects with the Power of AI
</span>
</h1>
<p className="mx-auto mt-6 max-w-2xl text-lg text-slate-400 leading-relaxed">
Streamline your workflow with intelligent automation, real-time collaboration, and predictive analytics that keep your team ahead of every deadline.
</p>
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
<Button asChild size="lg" className="active:scale-[0.98] bg-indigo-600 hover:bg-indigo-500 text-white px-8 rounded-full shadow-lg shadow-indigo-500/25 text-base">
<Link to="/signup">Start Free Trial <ArrowRight className="ml-2 h-4 w-4" /></Link>
</Button>
<Button asChild variant="outline" size="lg" className="active:scale-[0.98] rounded-full border-slate-700 text-slate-300 hover:bg-slate-800 hover:text-white text-base">
<Link to="/features"><Play className="mr-2 h-4 w-4" /> Watch Demo</Link>
</Button>
</div>
{/* Metrics */}
<div className="mt-16 flex flex-wrap justify-center gap-6">
{metrics.map((m) => (
<div key={m.label} className="text-center px-8 py-4 rounded-2xl bg-white/5 backdrop-blur-sm border border-white/10">
<div className="text-3xl font-bold text-white">{m.value}</div>
<div className="mt-1 text-sm text-slate-400">{m.label}</div>
</div>
))}
</div>
{/* Trust / Security Badges */}
<div className="flex flex-wrap justify-center gap-4 mt-8">
<Badge variant="outline" className="text-xs gap-1.5 text-slate-400 border-slate-700 px-3 py-1.5">
<Shield className="h-3 w-3" /> SOC 2 Certified
</Badge>
<Badge variant="outline" className="text-xs gap-1.5 text-slate-400 border-slate-700 px-3 py-1.5">
<Lock className="h-3 w-3" /> GDPR Compliant
</Badge>
<Badge variant="outline" className="text-xs gap-1.5 text-slate-400 border-slate-700 px-3 py-1.5">
<CheckCircle2 className="h-3 w-3" /> 99.9% Uptime SLA
</Badge>
<Badge variant="outline" className="text-xs gap-1.5 text-slate-400 border-slate-700 px-3 py-1.5">
<Lock className="h-3 w-3" /> 256-bit Encryption
</Badge>
</div>
</div>
</section>
{/* ── LOGO CLOUD ── */}
<section className="py-14 bg-slate-50 border-b border-slate-100">
<div className="mx-auto max-w-7xl px-6">
<p className="text-center text-sm font-medium text-slate-400 mb-8">Trusted by industry-leading teams worldwide</p>
<div className="flex flex-wrap items-center justify-center gap-x-12 gap-y-6">
{logos.map((logo) => (
<div key={logo} className="text-lg font-bold text-slate-300 tracking-wider uppercase">{logo}</div>
))}
</div>
</div>
</section>
{/* ── VIDEO DEMO ── */}
<section className="py-24 bg-white">
<div className="mx-auto max-w-7xl px-6">
<div className="aspect-video max-w-4xl mx-auto rounded-2xl bg-gradient-to-br from-indigo-900 via-slate-900 to-cyan-900 relative overflow-hidden group cursor-pointer shadow-2xl shadow-indigo-500/10">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-indigo-500/10 via-transparent to-transparent" />
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wMyI+PGNpcmNsZSBjeD0iMSIgY3k9IjEiIHI9IjEiLz48L2c+PC9nPjwvc3ZnPg==')] opacity-40" />
<div className="absolute inset-0 flex flex-col items-center justify-center gap-4">
<div className="h-20 w-20 rounded-full bg-white/10 backdrop-blur-sm flex items-center justify-center group-hover:scale-110 group-hover:bg-white/20 transition-all duration-300 ring-1 ring-white/20 animate-pulse">
<Play className="h-8 w-8 text-white ml-1" />
</div>
<span className="text-white/80 text-sm font-medium backdrop-blur-sm bg-white/10 px-4 py-1.5 rounded-full border border-white/10">See it in action</span>
</div>
</div>
<p className="text-center mt-6 text-slate-500 text-sm">Watch how teams ship 3x faster with Nexus</p>
<p className="text-center mt-2 text-xs text-slate-400">Trusted by teams at Google, Stripe, Vercel</p>
</div>
</section>
{/* ── FEATURES GRID ── */}
<section className="py-24 bg-white">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-indigo-50 text-indigo-600 border-0">Features</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight sm:text-4xl">Everything you need to ship faster</h2>
<p className="mt-4 text-lg text-slate-500 max-w-2xl mx-auto">Powerful tools designed to help your team collaborate, automate, and deliver results.</p>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 stagger">
{features.map((f) => (
<Card key={f.title} className="hover-card-lift border-slate-200 hover:border-indigo-200 hover:shadow-lg hover:shadow-indigo-50 hover:bg-gradient-to-b hover:from-primary/5 hover:to-transparent transition-all duration-300 group">
<CardContent className="p-6">
<div className="h-12 w-12 rounded-xl bg-gradient-to-br from-indigo-500 to-cyan-500 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform shadow-lg shadow-primary/10">
<f.icon className="h-6 w-6 text-white" />
</div>
<h3 className="text-lg font-semibold mb-2">{f.title}</h3>
<p className="text-slate-500 text-sm leading-relaxed">{f.desc}</p>
<span className="inline-flex items-center gap-1 mt-4 text-sm font-medium text-indigo-600 group-hover:translate-x-1 transition-transform cursor-pointer">
Learn more <ArrowRight className="h-3.5 w-3.5" />
</span>
</CardContent>
</Card>
))}
</div>
<div className="mt-12 text-center">
<Button asChild variant="outline" className="active:scale-[0.98] rounded-full">
<Link to="/features">Explore All Features <ChevronRight className="ml-1 h-4 w-4" /></Link>
</Button>
</div>
</div>
</section>
{/* ── HOW IT WORKS ── */}
<section className="py-24 bg-slate-50">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-cyan-50 text-cyan-600 border-0">How It Works</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight sm:text-4xl">Get started in minutes</h2>
</div>
<div className="relative max-w-3xl mx-auto">
{/* Connecting line */}
<div className="absolute left-8 top-12 bottom-12 w-px bg-gradient-to-b from-indigo-500 via-cyan-500 to-indigo-500 hidden md:block" />
<div className="space-y-12">
{steps.map((step) => (
<div key={step.num} className="flex gap-6 items-start">
<div className="relative flex-shrink-0 h-16 w-16 rounded-2xl bg-gradient-to-br from-indigo-600 to-cyan-500 flex items-center justify-center text-white font-bold text-lg shadow-lg shadow-indigo-500/20">
{step.num}
</div>
<div className="pt-2">
<h3 className="text-xl font-semibold mb-2">{step.title}</h3>
<p className="text-slate-500 leading-relaxed">{step.desc}</p>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* ── TESTIMONIALS ── */}
<section className="py-24 bg-white">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-amber-50 text-amber-600 border-0">Testimonials</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight sm:text-4xl">Loved by teams everywhere</h2>
</div>
<div className="grid md:grid-cols-3 gap-6 stagger">
{testimonials.map((t) => (
<Card key={t.name} className="backdrop-blur-sm bg-card/80 border-border/50 hover-card-lift transition-all duration-300 group">
<CardContent className="p-6">
<Quote className="h-5 w-5 text-indigo-300/50 mb-3" />
<div className="flex gap-0.5 mb-4">
{Array.from({ length: t.stars }, (_, i) => (
<Star key={i} className="h-4 w-4 fill-amber-400 text-amber-400" />
))}
</div>
<p className="text-slate-600 leading-relaxed mb-6">"{t.quote}"</p>
<div className="flex items-center gap-3">
<div className="h-10 w-10 rounded-full bg-gradient-to-br from-indigo-400 to-cyan-400 flex items-center justify-center text-white font-semibold text-sm">
{t.name.split(" ").map((n) => n[0]).join("")}
</div>
<div className="flex-1">
<div className="font-semibold text-sm">{t.name}</div>
<div className="text-xs text-slate-400">{t.role}</div>
</div>
<div className="h-8 w-8 rounded-full bg-gradient-to-br from-slate-200 to-slate-300 flex items-center justify-center text-slate-500 font-bold text-[10px]">
{t.role.split(" at ").pop()?.slice(0, 2).toUpperCase() || "Co"}
</div>
</div>
<span className="inline-flex items-center gap-1 mt-4 text-xs font-medium text-indigo-600 group-hover:translate-x-1 transition-transform cursor-pointer">
Read case study <ArrowRight className="h-3 w-3" />
</span>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* ── INTEGRATIONS ── */}
<section className="py-24 bg-slate-50">
<div className="mx-auto max-w-7xl px-6 text-center">
<Badge className="mb-4 bg-cyan-50 text-cyan-600 border-0">Integrations</Badge>
<h2 className="animate-fade-up text-3xl font-bold tracking-tight sm:text-4xl">Works with tools you already love</h2>
<p className="mt-4 text-slate-500 max-w-2xl mx-auto">Connect with 200+ tools your team relies on every day.</p>
<div className="mt-12 grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 gap-4 max-w-4xl mx-auto stagger">
{logos.map((logo) => (
<div key={logo} className="flex items-center justify-center h-24 rounded-xl border border-slate-200 bg-white grayscale hover:grayscale-0 hover:border-indigo-200 hover:shadow-lg hover:scale-110 transition-all duration-300 cursor-pointer group" title={logo}>
<span className="text-base font-semibold text-slate-500 group-hover:text-indigo-600 transition-colors">{logo}</span>
</div>
))}
</div>
<Badge className="mt-8 bg-indigo-50 text-indigo-600 border-0 text-sm px-4 py-1.5">50+ integrations</Badge>
</div>
</section>
{/* ── CTA ── */}
<section className="py-24 bg-gradient-to-br from-indigo-600 via-indigo-700 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">Ready to transform your workflow?</h2>
<p className="mt-4 text-lg text-indigo-200">Join 10,000+ teams already using Nexus to ship faster and smarter.</p>
<div className="mt-10 flex flex-col sm:flex-row justify-center gap-4">
<Button asChild size="lg" className="active:scale-[0.98] bg-white text-indigo-700 hover:bg-indigo-50 rounded-full px-8 shadow-lg text-base font-semibold">
<Link to="/signup">Start Free Trial <ArrowRight className="ml-2 h-4 w-4" /></Link>
</Button>
<Button asChild variant="outline" size="lg" className="active:scale-[0.98] rounded-full border-white/30 text-white hover:bg-white/10 text-base">
<Link to="/contact">Talk to Sales</Link>
</Button>
</div>
<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
<Badge className="bg-white/10 text-white/80 border border-white/20 text-xs px-3 py-1">SOC 2</Badge>
<Badge className="bg-white/10 text-white/80 border border-white/20 text-xs px-3 py-1">GDPR</Badge>
<Badge className="bg-white/10 text-white/80 border border-white/20 text-xs px-3 py-1">99.9% Uptime</Badge>
</div>
<p className="mt-4 text-sm text-indigo-300">No credit card required. 14-day free trial.</p>
</div>
</section>
<Footer />
</div>
);
}
+94
View File
@@ -0,0 +1,94 @@
import { useState } from "react";
import { toast } from "sonner";
import { Link, useNavigate } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import { Layers, CheckCircle2 } from "lucide-react";
export default function LoginPage() {
const navigate = useNavigate();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [success, setSuccess] = useState(false);
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-indigo-950 to-slate-900 flex items-center justify-center p-6">
<div className="w-full max-w-md">
{/* Logo */}
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
<div className="h-10 w-10 rounded-xl bg-gradient-to-br from-indigo-500 to-cyan-500 flex items-center justify-center">
<Layers className="h-5 w-5 text-white" />
</div>
<span className="text-2xl font-bold text-white tracking-tight">Nexus</span>
</Link>
<Card className="border-slate-800 bg-slate-900/50 backdrop-blur-xl shadow-2xl">
<CardContent className="p-8">
<div className="text-center mb-8">
<h1 className="text-2xl font-bold text-white">Welcome back</h1>
<p className="text-slate-400 mt-1 text-sm">Sign in to your account to continue</p>
</div>
{success && (
<div className="mb-6 flex items-center gap-2 rounded-lg bg-green-500/10 border border-green-500/20 px-4 py-3 text-sm text-green-400">
<CheckCircle2 className="h-4 w-4 flex-shrink-0" /> Sign in successful! Redirecting...
</div>
)}
<form onSubmit={(e) => { e.preventDefault(); setSuccess(true); toast.success("Welcome back!"); setTimeout(() => navigate("/dashboard"), 1500); }} className="space-y-4">
<div>
<Label htmlFor="email" className="text-slate-300 text-sm">Email</Label>
<Input
id="email"
type="email"
required
placeholder="you@company.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500/20"
/>
</div>
<div>
<div className="flex items-center justify-between">
<Label htmlFor="password" className="text-slate-300 text-sm">Password</Label>
<Link to="/forgot-password" className="text-xs text-indigo-400 hover:text-indigo-300">Forgot password?</Link>
</div>
<Input
id="password"
type="password"
required
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500/20"
/>
</div>
<Button type="submit" className="active:scale-[0.98] w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg mt-2 font-semibold">
Sign In
</Button>
</form>
<div className="relative my-6">
<Separator className="bg-slate-700" />
<span className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-900 px-3 text-xs text-slate-500">or</span>
</div>
<Button variant="outline" className="active:scale-[0.98] w-full border-slate-700 text-slate-300 hover:bg-slate-800 hover:text-white rounded-lg">
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>
Sign in with Google
</Button>
<p className="mt-6 text-center text-sm text-slate-400">
Don't have an account?{" "}
<Link to="/signup" className="text-indigo-400 hover:text-indigo-300 font-medium">Sign up</Link>
</p>
</CardContent>
</Card>
</div>
</div>
);
}
+198
View File
@@ -0,0 +1,198 @@
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>
);
}
+163
View File
@@ -0,0 +1,163 @@
import Sidebar from "@/components/Sidebar";
import DashboardHeader from "@/components/DashboardHeader";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { Copy, UserPlus } from "lucide-react";
const notifications = [
{ label: "Email notifications", desc: "Receive email for important updates", defaultChecked: true },
{ label: "Push notifications", desc: "Browser push notifications", defaultChecked: true },
{ label: "Weekly digest", desc: "Summary of activity every Monday", defaultChecked: false },
{ label: "Marketing emails", desc: "Product news and offers", defaultChecked: false },
];
const apiKeys = [
{ name: "Production", key: "sk-prod-****-****-****-7f3a", created: "Jan 5, 2024" },
{ name: "Development", key: "sk-dev-****-****-****-2b8c", created: "Mar 12, 2024" },
];
const teamMembers = [
{ name: "John Doe", email: "john@company.com", role: "Owner", initials: "JD" },
{ name: "Sarah Chen", email: "sarah@company.com", role: "Admin", initials: "SC" },
{ name: "Marcus Johnson", email: "marcus@company.com", role: "Member", initials: "MJ" },
];
export default function SettingsPage() {
return (
<div className="flex min-h-screen bg-slate-50">
<Sidebar activePath="/settings" />
<div className="flex-1 lg:ml-64">
<DashboardHeader />
<main className="p-6 space-y-6 max-w-4xl">
{/* Profile */}
<Card>
<CardHeader>
<CardTitle>Profile</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center gap-4 mb-4">
<Avatar className="h-16 w-16">
<AvatarFallback className="bg-indigo-100 text-indigo-600 text-xl font-semibold">JD</AvatarFallback>
</Avatar>
<div>
<p className="font-semibold">John Doe</p>
<p className="text-sm text-slate-500">john@company.com</p>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<Label className="text-sm">Name</Label>
<Input defaultValue="John Doe" className="mt-1" />
</div>
<div>
<Label className="text-sm">Email</Label>
<Input defaultValue="john@company.com" className="mt-1" />
</div>
</div>
<Button className="bg-indigo-600 hover:bg-indigo-500 text-white">Save Changes</Button>
</CardContent>
</Card>
{/* Billing */}
<Card>
<CardHeader>
<CardTitle>Billing</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between">
<div>
<div className="flex items-center gap-2">
<span className="font-semibold">Current Plan:</span>
<Badge className="bg-indigo-100 text-indigo-700">Pro</Badge>
</div>
<p className="text-sm text-slate-500 mt-1">\$29/mo billed monthly</p>
</div>
<Button variant="outline">Upgrade</Button>
</div>
<div>
<div className="flex justify-between text-sm mb-1">
<span className="text-slate-500">Usage this period</span>
<span className="font-medium">75%</span>
</div>
<div className="h-2 bg-slate-100 rounded-full overflow-hidden">
<div className="h-full bg-indigo-500 rounded-full" style={{ width: "75%" }} />
</div>
</div>
</CardContent>
</Card>
{/* Notifications */}
<Card>
<CardHeader>
<CardTitle>Notifications</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{notifications.map((n) => (
<div key={n.label} className="flex items-start gap-3">
<Checkbox defaultChecked={n.defaultChecked} className="mt-1" />
<div>
<p className="font-medium text-sm">{n.label}</p>
<p className="text-xs text-slate-400">{n.desc}</p>
</div>
</div>
))}
</CardContent>
</Card>
{/* API Keys */}
<Card>
<CardHeader>
<CardTitle>API Keys</CardTitle>
</CardHeader>
<CardContent className="space-y-3">
{apiKeys.map((k) => (
<div key={k.name} className="flex items-center justify-between p-3 bg-slate-50 rounded-lg">
<div>
<p className="font-medium text-sm">{k.name}</p>
<p className="text-xs text-slate-400 font-mono mt-0.5">{k.key}</p>
</div>
<Button variant="ghost" size="sm">
<Copy className="h-4 w-4" />
</Button>
</div>
))}
</CardContent>
</Card>
{/* Team */}
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle>Team</CardTitle>
<Button size="sm" className="bg-indigo-600 hover:bg-indigo-500 text-white">
<UserPlus className="h-4 w-4 mr-2" /> Invite
</Button>
</CardHeader>
<CardContent className="space-y-3">
{teamMembers.map((m) => (
<div key={m.email} className="flex items-center justify-between p-3 bg-slate-50 rounded-lg">
<div className="flex items-center gap-3">
<Avatar className="h-8 w-8">
<AvatarFallback className="bg-indigo-100 text-indigo-600 text-xs">{m.initials}</AvatarFallback>
</Avatar>
<div>
<p className="font-medium text-sm">{m.name}</p>
<p className="text-xs text-slate-400">{m.email}</p>
</div>
</div>
<Badge variant={m.role === "Owner" ? "default" : m.role === "Admin" ? "secondary" : "outline"}>
{m.role}
</Badge>
</div>
))}
</CardContent>
</Card>
</main>
</div>
</div>
);
}
+130
View File
@@ -0,0 +1,130 @@
import { useState } from "react";
import { toast } from "sonner";
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { Separator } from "@/components/ui/separator";
import { Layers, CheckCircle2 } from "lucide-react";
export default function SignupPage() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [terms, setTerms] = useState(false);
const [success, setSuccess] = useState(false);
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-indigo-950 to-slate-900 flex items-center justify-center p-6">
<div className="w-full max-w-md">
{/* Logo */}
<Link to="/" className="flex items-center justify-center gap-2 mb-8">
<div className="h-10 w-10 rounded-xl bg-gradient-to-br from-indigo-500 to-cyan-500 flex items-center justify-center">
<Layers className="h-5 w-5 text-white" />
</div>
<span className="text-2xl font-bold text-white tracking-tight">Nexus</span>
</Link>
<Card className="border-slate-800 bg-slate-900/50 backdrop-blur-xl shadow-2xl">
<CardContent className="p-8">
<div className="text-center mb-8">
<h1 className="text-2xl font-bold text-white">Create your account</h1>
<p className="text-slate-400 mt-1 text-sm">Start your 14-day free trial</p>
</div>
{success && (
<div className="mb-6 flex items-center gap-2 rounded-lg bg-green-500/10 border border-green-500/20 px-4 py-3 text-sm text-green-400">
<CheckCircle2 className="h-4 w-4 flex-shrink-0" /> Account created! Redirecting to dashboard...
</div>
)}
<form onSubmit={(e) => { e.preventDefault(); setSuccess(true); toast.success("Account created! Check your email."); }} className="space-y-4">
<div>
<Label htmlFor="name" className="text-slate-300 text-sm">Full name</Label>
<Input
id="name"
required
placeholder="John Doe"
value={name}
onChange={(e) => setName(e.target.value)}
className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500/20"
/>
</div>
<div>
<Label htmlFor="signup-email" className="text-slate-300 text-sm">Email</Label>
<Input
id="signup-email"
type="email"
required
placeholder="you@company.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500/20"
/>
</div>
<div>
<Label htmlFor="signup-password" className="text-slate-300 text-sm">Password</Label>
<Input
id="signup-password"
type="password"
required
placeholder="Create a password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500/20"
/>
</div>
<div>
<Label htmlFor="confirm-password" className="text-slate-300 text-sm">Confirm password</Label>
<Input
id="confirm-password"
type="password"
required
placeholder="Confirm your password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="mt-1.5 bg-slate-800/50 border-slate-700 text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500/20"
/>
</div>
<div className="flex items-start gap-2 pt-1">
<Checkbox
id="terms"
required
checked={terms}
onCheckedChange={(checked) => setTerms(checked === true)}
className="border-slate-600 data-[state=checked]:bg-indigo-600 data-[state=checked]:border-indigo-600 mt-0.5"
/>
<Label htmlFor="terms" className="text-xs text-slate-400 leading-relaxed">
I agree to the <a href="#" className="text-indigo-400 hover:text-indigo-300">Terms of Service</a> and <a href="#" className="text-indigo-400 hover:text-indigo-300">Privacy Policy</a>
</Label>
</div>
<Button type="submit" className="active:scale-[0.98] w-full bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg mt-2 font-semibold">
Create Account
</Button>
</form>
<div className="relative my-6">
<Separator className="bg-slate-700" />
<span className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-slate-900 px-3 text-xs text-slate-500">or</span>
</div>
<Button variant="outline" className="active:scale-[0.98] w-full border-slate-700 text-slate-300 hover:bg-slate-800 hover:text-white rounded-lg">
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>
Sign up with Google
</Button>
<p className="mt-6 text-center text-sm text-slate-400">
Already have an account?{" "}
<Link to="/login" className="text-indigo-400 hover:text-indigo-300 font-medium">Sign in</Link>
</p>
</CardContent>
</Card>
</div>
</div>
);
}