- Create /home route with SEO metadata and JSON-LD structured data - Add hero section with dual CTAs (sign-up and PWA install) - Add features section showcasing dual tracking, health timeline, achievements, savings - Add animated phone demo with rotating screens (auto-advance, pause on hover) - Add final CTA section and footer with affiliate disclosure - Extract usePWAInstall hook for reusable PWA install logic - Enhance theme-context with system preference auto-detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
268 lines
10 KiB
TypeScript
268 lines
10 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { Cigarette, Leaf, Heart, Trophy, DollarSign, TrendingDown, CheckCircle } from 'lucide-react';
|
|
|
|
const DEMO_SCREENS = [
|
|
{
|
|
id: 'logging',
|
|
title: 'Log Your Usage',
|
|
subtitle: 'Track daily consumption with ease',
|
|
content: (
|
|
<div className="space-y-4">
|
|
<div className="flex justify-between items-center p-3 rounded-xl bg-white/5 border border-white/10">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 rounded-lg bg-red-500/20 flex items-center justify-center">
|
|
<Cigarette className="h-4 w-4 text-red-400" />
|
|
</div>
|
|
<span className="font-medium">Nicotine</span>
|
|
</div>
|
|
<div className="text-2xl font-bold">3</div>
|
|
</div>
|
|
<div className="flex justify-between items-center p-3 rounded-xl bg-white/5 border border-white/10">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 rounded-lg bg-green-500/20 flex items-center justify-center">
|
|
<Leaf className="h-4 w-4 text-green-400" />
|
|
</div>
|
|
<span className="font-medium">Marijuana</span>
|
|
</div>
|
|
<div className="text-2xl font-bold">0</div>
|
|
</div>
|
|
<div className="text-center text-xs text-muted-foreground mt-4">
|
|
<TrendingDown className="h-4 w-4 inline mr-1 text-green-400" />
|
|
Down 40% from last week
|
|
</div>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
id: 'health',
|
|
title: 'Health Recovery',
|
|
subtitle: 'Watch your body heal',
|
|
content: (
|
|
<div className="space-y-3">
|
|
<div className="space-y-1">
|
|
<div className="flex justify-between text-xs">
|
|
<span>Blood Pressure Normalizes</span>
|
|
<CheckCircle className="h-3 w-3 text-green-400" />
|
|
</div>
|
|
<div className="h-2 rounded-full bg-white/10 overflow-hidden">
|
|
<div className="h-full w-full bg-gradient-to-r from-teal-500 to-cyan-400 rounded-full" />
|
|
</div>
|
|
</div>
|
|
<div className="space-y-1">
|
|
<div className="flex justify-between text-xs">
|
|
<span>Oxygen Levels Rise</span>
|
|
<CheckCircle className="h-3 w-3 text-green-400" />
|
|
</div>
|
|
<div className="h-2 rounded-full bg-white/10 overflow-hidden">
|
|
<div className="h-full w-full bg-gradient-to-r from-teal-500 to-cyan-400 rounded-full" />
|
|
</div>
|
|
</div>
|
|
<div className="space-y-1">
|
|
<div className="flex justify-between text-xs">
|
|
<span>Circulation Improves</span>
|
|
<span className="text-yellow-400">1 week to go</span>
|
|
</div>
|
|
<div className="h-2 rounded-full bg-white/10 overflow-hidden">
|
|
<div className="h-full w-3/4 bg-gradient-to-r from-teal-500 to-cyan-400 rounded-full" />
|
|
</div>
|
|
</div>
|
|
<div className="space-y-1">
|
|
<div className="flex justify-between text-xs">
|
|
<span>Heart Attack Risk Drops</span>
|
|
<span className="text-muted-foreground">2 weeks to go</span>
|
|
</div>
|
|
<div className="h-2 rounded-full bg-white/10 overflow-hidden">
|
|
<div className="h-full w-1/2 bg-gradient-to-r from-teal-500 to-cyan-400 rounded-full" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
id: 'achievements',
|
|
title: 'Achievements',
|
|
subtitle: 'Celebrate every milestone',
|
|
content: (
|
|
<div className="grid grid-cols-3 gap-2">
|
|
{[
|
|
{ name: 'First Step', unlocked: true },
|
|
{ name: 'Hat Trick', unlocked: true },
|
|
{ name: 'Week Warrior', unlocked: true },
|
|
{ name: 'Fighter', unlocked: false },
|
|
{ name: 'Monthly Master', unlocked: false },
|
|
{ name: 'Goal Crusher', unlocked: false },
|
|
].map((badge) => (
|
|
<div
|
|
key={badge.name}
|
|
className={`aspect-square rounded-xl flex flex-col items-center justify-center p-2 text-center ${
|
|
badge.unlocked
|
|
? 'bg-gradient-to-br from-yellow-500/30 to-amber-600/20 border border-yellow-500/50'
|
|
: 'bg-white/5 border border-white/10 opacity-50'
|
|
}`}
|
|
>
|
|
<Trophy
|
|
className={`h-5 w-5 mb-1 ${badge.unlocked ? 'text-yellow-400' : 'text-muted-foreground'}`}
|
|
/>
|
|
<span className="text-[10px] leading-tight">{badge.name}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
id: 'savings',
|
|
title: 'Money Saved',
|
|
subtitle: 'Track your financial wins',
|
|
content: (
|
|
<div className="text-center space-y-4">
|
|
<div className="w-16 h-16 rounded-2xl bg-emerald-500/20 flex items-center justify-center mx-auto">
|
|
<DollarSign className="h-8 w-8 text-emerald-400" />
|
|
</div>
|
|
<div>
|
|
<div className="text-4xl font-black text-emerald-400">$127.50</div>
|
|
<div className="text-sm text-muted-foreground">saved this month</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-2 text-xs">
|
|
<div className="p-2 rounded-lg bg-white/5 border border-white/10">
|
|
<div className="font-bold">$4.25</div>
|
|
<div className="text-muted-foreground">per day</div>
|
|
</div>
|
|
<div className="p-2 rounded-lg bg-white/5 border border-white/10">
|
|
<div className="font-bold">$1,530</div>
|
|
<div className="text-muted-foreground">per year</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
),
|
|
},
|
|
];
|
|
|
|
export function DemoSection() {
|
|
const [activeScreen, setActiveScreen] = useState(0);
|
|
const [isPaused, setIsPaused] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (isPaused) return;
|
|
|
|
const interval = setInterval(() => {
|
|
setActiveScreen((prev) => (prev + 1) % DEMO_SCREENS.length);
|
|
}, 4000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [isPaused]);
|
|
|
|
return (
|
|
<section
|
|
id="demo"
|
|
aria-labelledby="demo-heading"
|
|
className="py-20 px-4 relative overflow-hidden"
|
|
>
|
|
{/* Background accents */}
|
|
<div className="absolute top-1/2 left-0 w-96 h-96 bg-primary/10 rounded-full blur-[120px] -translate-y-1/2 pointer-events-none" />
|
|
<div className="absolute top-1/2 right-0 w-96 h-96 bg-purple-500/10 rounded-full blur-[120px] -translate-y-1/2 pointer-events-none" />
|
|
|
|
<div className="container mx-auto max-w-6xl relative z-10">
|
|
{/* Section Header */}
|
|
<div className="text-center mb-12">
|
|
<h2
|
|
id="demo-heading"
|
|
className="text-3xl sm:text-4xl font-bold mb-4"
|
|
>
|
|
See It In{' '}
|
|
<span className="bg-gradient-to-r from-primary via-purple-500 to-pink-500 bg-clip-text text-transparent">
|
|
Action
|
|
</span>
|
|
</h2>
|
|
<p className="text-muted-foreground max-w-2xl mx-auto">
|
|
A quick look at how QuitTraq helps you track progress and stay motivated.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col lg:flex-row items-center gap-12 lg:gap-16">
|
|
{/* Phone Mockup */}
|
|
<div
|
|
className="relative mx-auto lg:mx-0"
|
|
onMouseEnter={() => setIsPaused(true)}
|
|
onMouseLeave={() => setIsPaused(false)}
|
|
onTouchStart={() => setIsPaused(true)}
|
|
onTouchEnd={() => setIsPaused(false)}
|
|
>
|
|
{/* Phone frame glow */}
|
|
<div className="absolute inset-0 bg-gradient-to-br from-primary/30 to-purple-500/30 rounded-[3rem] blur-2xl opacity-50" />
|
|
|
|
{/* Phone frame */}
|
|
<div className="relative w-[280px] sm:w-[320px] aspect-[9/16] rounded-[2.5rem] overflow-hidden border-4 border-white/10 bg-background shadow-2xl shadow-black/30">
|
|
{/* Notch */}
|
|
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-24 h-6 bg-black rounded-b-2xl z-20" />
|
|
|
|
{/* Screen content */}
|
|
<div className="absolute inset-0 p-4 pt-10">
|
|
{/* Screen header */}
|
|
<div className="text-center mb-4">
|
|
<h3 className="text-lg font-bold">{DEMO_SCREENS[activeScreen].title}</h3>
|
|
<p className="text-xs text-muted-foreground">
|
|
{DEMO_SCREENS[activeScreen].subtitle}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Screen content with transition */}
|
|
<div className="animate-fade-in" key={activeScreen}>
|
|
{DEMO_SCREENS[activeScreen].content}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bottom gradient overlay */}
|
|
<div className="absolute bottom-0 left-0 right-0 h-20 bg-gradient-to-t from-background to-transparent pointer-events-none" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Description and indicators */}
|
|
<div className="flex-1 text-center lg:text-left">
|
|
<div className="space-y-6">
|
|
{/* Screen descriptions */}
|
|
{DEMO_SCREENS.map((screen, index) => (
|
|
<button
|
|
key={screen.id}
|
|
onClick={() => setActiveScreen(index)}
|
|
className={`w-full text-left p-4 rounded-xl transition-all duration-300 ${
|
|
activeScreen === index
|
|
? 'bg-primary/10 border border-primary/30'
|
|
: 'hover:bg-white/5 border border-transparent'
|
|
}`}
|
|
>
|
|
<h4
|
|
className={`font-semibold mb-1 ${
|
|
activeScreen === index ? 'text-primary' : 'text-foreground'
|
|
}`}
|
|
>
|
|
{screen.title}
|
|
</h4>
|
|
<p className="text-sm text-muted-foreground">{screen.subtitle}</p>
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* Dot indicators (mobile) */}
|
|
<div className="flex justify-center gap-2 mt-6 lg:hidden">
|
|
{DEMO_SCREENS.map((_, index) => (
|
|
<button
|
|
key={index}
|
|
onClick={() => setActiveScreen(index)}
|
|
className={`w-2 h-2 rounded-full transition-all ${
|
|
activeScreen === index
|
|
? 'w-6 bg-primary'
|
|
: 'bg-white/20 hover:bg-white/40'
|
|
}`}
|
|
aria-label={`Go to screen ${index + 1}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|