Files
lytsup-site/src/components/sections/EarningFeatures.tsx
R-Bharathraj 3cb2613195 first commit
2026-07-15 17:13:09 +05:30

418 lines
20 KiB
TypeScript

"use client";
import { useState } from "react";
import { useUser } from "@/lib/context";
import { Footprints, ShoppingBag, MapPin, Share2, ClipboardCheck, Sparkles, Check, RefreshCw } from "lucide-react";
export default function EarningFeatures() {
const { profile, addLyts, incrementSteps } = useUser();
// Walk simulator state
const [simSteps, setSimSteps] = useState(1200);
const [walkClaimed, setWalkClaimed] = useState(false);
const walkReward = Math.floor(simSteps / 400); // 1 LYT per 400 steps for the simulator
// Shop state
const [selectedItems, setSelectedItems] = useState<string[]>(["coffee"]);
const [shopClaimed, setShopClaimed] = useState(false);
const shopItems = [
{ id: "coffee", name: "Starbucks Iced Latte", cost: "$5.80", reward: 8 },
{ id: "sneakers", name: "Nike Air Max Essentials", cost: "$120.00", reward: 150 },
{ id: "gym", name: "Gymshark Fitness Tee", cost: "$35.00", reward: 40 },
];
const totalShopReward = shopItems
.filter((item) => selectedItems.includes(item.id))
.reduce((sum, item) => sum + item.reward, 0);
// Map state
const [visitedStores, setVisitedStores] = useState<string[]>([]);
const [mapClaimed, setMapClaimed] = useState<string | null>(null);
const checkinLocations = [
{ id: "cafe", name: "Brew & Co Cafe", reward: 5, checked: false },
{ id: "apparel", name: "H&M flagship", reward: 12, checked: false },
{ id: "arena", name: "Downtown Arena", reward: 25, checked: false },
];
// Referral state
const [referralCopied, setReferralCopied] = useState(false);
const referralCode = `lytsup.com/invite/${profile.name.toLowerCase().replace(/\s+/g, "")}-77`;
const handleSimulateWalk = () => {
incrementSteps(simSteps);
addLyts(walkReward);
setWalkClaimed(true);
setTimeout(() => {
setWalkClaimed(false);
setSimSteps(1200);
}, 4000);
};
const handleShopClaim = () => {
if (totalShopReward > 0) {
addLyts(totalShopReward);
setShopClaimed(true);
setTimeout(() => {
setShopClaimed(false);
setSelectedItems([]);
}, 4000);
}
};
const handleCheckin = (id: string, name: string, reward: number) => {
if (visitedStores.includes(id)) return;
setVisitedStores((prev) => [...prev, id]);
addLyts(reward);
setMapClaimed(name);
setTimeout(() => setMapClaimed(null), 3000);
};
const handleCopyReferral = () => {
navigator.clipboard.writeText(referralCode);
setReferralCopied(true);
addLyts(50); // Referral bonus!
setTimeout(() => setReferralCopied(false), 4000);
};
return (
<section id="earn" className="py-24 bg-[#090909] relative overflow-hidden">
{/* Background glow lines */}
<div className="absolute top-1/2 left-0 right-0 h-0.5 bg-gradient-to-r from-transparent via-white/5 to-transparent pointer-events-none" />
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
{/* Section Header */}
<div className="text-center max-w-3xl mx-auto mb-20 space-y-4">
<span className="text-accent-pink font-extrabold text-xs tracking-widest uppercase">
How it works
</span>
<h2 className="text-3xl sm:text-5xl font-extrabold font-sora text-white leading-tight">
Earn LYTs for <span className="text-glow-yellow text-primary">Living Your Life</span>
</h2>
<p className="text-white/60 text-base sm:text-lg">
Interact with our live simulations below to see how easy it is to rack up social currency.
</p>
</div>
{/* Feature Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Card 1: Walk to Earn (Simulator) */}
<div className="glassmorphism rounded-3xl p-8 flex flex-col justify-between group hover:border-primary/20 transition-all duration-300">
<div className="space-y-6">
<div className="flex items-center justify-between">
<div className="w-12 h-12 rounded-2xl bg-primary/10 border border-primary/20 flex items-center justify-center text-primary">
<Footprints className="w-6 h-6 animate-pulse" />
</div>
<span className="text-xs font-bold px-3 py-1 rounded-full bg-white/5 text-white/50 border border-white/5">
1 LYT / 400 Steps
</span>
</div>
<div className="space-y-2">
<h3 className="text-2xl font-bold font-sora text-white">Walk-to-Earn</h3>
<p className="text-white/60 text-sm">
Keep your phone in your pocket, walk to class, run errands, or jog. Watch your step count convert to LYTs automatically.
</p>
</div>
{/* Step Simulator Widget */}
<div className="bg-white/3 border border-white/5 rounded-2xl p-6 space-y-4">
<div className="flex justify-between items-end">
<div>
<span className="text-white/40 text-[10px] font-bold tracking-wider uppercase block">Steps to Simulate</span>
<span className="text-2xl font-extrabold font-sora text-white">
+{simSteps.toLocaleString()} <span className="text-xs text-white/40">Steps</span>
</span>
</div>
<div className="text-right">
<span className="text-white/40 text-[10px] font-bold tracking-wider uppercase block">Estimated Earn</span>
<span className="text-xl font-extrabold text-primary font-sora flex items-center justify-end gap-1">
+{walkReward} <span className="text-xs font-medium text-white/60">LYTs</span>
</span>
</div>
</div>
{/* Range Slider */}
<input
type="range"
min="400"
max="12000"
step="400"
value={simSteps}
onChange={(e) => setSimSteps(parseInt(e.target.value))}
disabled={walkClaimed}
className="w-full h-1.5 bg-white/10 rounded-lg appearance-none cursor-pointer accent-primary"
/>
<div className="flex justify-between text-[10px] text-white/40 font-bold">
<span>400 Steps</span>
<span>6,000 Steps</span>
<span>12,000 Steps</span>
</div>
</div>
</div>
<div className="mt-8">
<button
onClick={handleSimulateWalk}
disabled={walkClaimed}
className={`w-full py-4 rounded-xl font-extrabold text-sm tracking-wider flex items-center justify-center gap-2 cursor-pointer transition-all ${
walkClaimed
? "bg-accent-lime text-dark shadow-[0_0_20px_rgba(200,255,55,0.3)]"
: "bg-white/5 hover:bg-primary hover:text-dark text-white border border-white/10 hover:border-primary"
}`}
>
{walkClaimed ? (
<>
<Check className="w-5 h-5" />
<span>Steps Synced! +{walkReward} LYTs Claimed</span>
</>
) : (
<>
<RefreshCw className="w-4 h-4 animate-spin-slow" />
<span>Simulate Walk & Sync Steps</span>
</>
)}
</button>
</div>
</div>
{/* Card 2: Shop & Earn (Receipt Simulator) */}
<div className="glassmorphism rounded-3xl p-8 flex flex-col justify-between group hover:border-accent-pink/20 transition-all duration-300">
<div className="space-y-6">
<div className="flex items-center justify-between">
<div className="w-12 h-12 rounded-2xl bg-accent-pink/10 border border-accent-pink/20 flex items-center justify-center text-accent-pink">
<ShoppingBag className="w-6 h-6" />
</div>
<span className="text-xs font-bold px-3 py-1 rounded-full bg-white/5 text-white/50 border border-white/5">
10% LYT Cashback
</span>
</div>
<div className="space-y-2">
<h3 className="text-2xl font-bold font-sora text-white">Shop-to-Earn</h3>
<p className="text-white/60 text-sm">
Shop from partner merchants (food, clothing, fitness centers) and scan your digital receipt to claim instant LYT cashback.
</p>
</div>
{/* Receipt Widget */}
<div className="bg-[#0b0b0b] border border-white/5 rounded-2xl p-5 space-y-3.5 relative overflow-hidden">
<div className="absolute top-0 right-0 bg-accent-pink/10 text-accent-pink px-2.5 py-0.5 text-[9px] font-bold tracking-wider rounded-bl-lg uppercase">
Pending Receipt
</div>
<h4 className="text-[10px] font-bold text-white/40 uppercase tracking-widest">Select items purchased:</h4>
<div className="space-y-2">
{shopItems.map((item) => (
<div
key={item.id}
onClick={() => {
if (shopClaimed) return;
setSelectedItems((prev) =>
prev.includes(item.id)
? prev.filter((id) => id !== item.id)
: [...prev, item.id]
);
}}
className={`flex items-center justify-between p-3 rounded-xl border cursor-pointer transition-all ${
selectedItems.includes(item.id)
? "bg-accent-pink/5 border-accent-pink/30 text-white"
: "bg-white/3 border-white/5 text-white/60 hover:border-white/10"
}`}
>
<div className="flex items-center space-x-3">
<div
className={`w-4 h-4 rounded flex items-center justify-center border transition-all ${
selectedItems.includes(item.id)
? "bg-accent-pink border-accent-pink"
: "border-white/20"
}`}
>
{selectedItems.includes(item.id) && <Check className="w-3 h-3 text-white" />}
</div>
<div className="text-xs font-semibold">{item.name}</div>
</div>
<div className="text-right">
<div className="text-xs font-extrabold text-white">{item.cost}</div>
<div className="text-[10px] text-accent-pink font-bold">+{item.reward} LYTs</div>
</div>
</div>
))}
</div>
</div>
</div>
<div className="mt-8">
<button
onClick={handleShopClaim}
disabled={shopClaimed || totalShopReward === 0}
className={`w-full py-4 rounded-xl font-extrabold text-sm tracking-wider flex items-center justify-center gap-2 cursor-pointer transition-all ${
shopClaimed
? "bg-accent-lime text-dark shadow-[0_0_20px_rgba(200,255,55,0.3)]"
: totalShopReward === 0
? "bg-white/5 text-white/20 border border-white/5 cursor-not-allowed"
: "bg-white/5 hover:bg-accent-pink hover:text-white text-white border border-white/10 hover:border-accent-pink"
}`}
>
{shopClaimed ? (
<>
<Check className="w-5 h-5" />
<span>Receipt Scanned! +{totalShopReward} LYTs Claimed</span>
</>
) : (
<span>Claim Receipt Reward (+{totalShopReward} LYTs)</span>
)}
</button>
</div>
</div>
{/* Card 3: Visit to Earn (Geofence Checkins) */}
<div className="glassmorphism rounded-3xl p-8 flex flex-col justify-between group hover:border-accent-purple/20 transition-all duration-300">
<div className="space-y-6">
<div className="flex items-center justify-between">
<div className="w-12 h-12 rounded-2xl bg-accent-purple/10 border border-accent-purple/20 flex items-center justify-center text-accent-purple">
<MapPin className="w-6 h-6" />
</div>
<span className="text-xs font-bold px-3 py-1 rounded-full bg-white/5 text-white/50 border border-white/5">
Location Check-Ins
</span>
</div>
<div className="space-y-2">
<h3 className="text-2xl font-bold font-sora text-white">Visit-to-Earn</h3>
<p className="text-white/60 text-sm">
Explore your city! Check in at partner gyms, parks, retail shops, or cafes. Each location visit awards you instant points.
</p>
</div>
{/* Map Simulator Widget */}
<div className="bg-[#0b0b0b] border border-white/5 rounded-2xl p-5 space-y-4 relative overflow-hidden">
{mapClaimed && (
<div className="absolute inset-0 bg-dark/95 flex items-center justify-center z-10 p-4 text-center animate-in fade-in duration-200">
<div className="space-y-2">
<div className="w-10 h-10 rounded-full bg-accent-purple/10 border border-accent-purple/30 mx-auto flex items-center justify-center text-accent-purple">
<Sparkles className="w-5 h-5 animate-spin-slow" />
</div>
<p className="text-sm font-semibold text-white">Checked in at {mapClaimed}!</p>
<p className="text-xs text-accent-lime font-bold">LYTs Added directly to wallet</p>
</div>
</div>
)}
<h4 className="text-[10px] font-bold text-white/40 uppercase tracking-widest">Active nodes near you:</h4>
<div className="space-y-2.5">
{checkinLocations.map((loc) => {
const visited = visitedStores.includes(loc.id);
return (
<div
key={loc.id}
className={`flex items-center justify-between p-3 rounded-xl border transition-all ${
visited
? "bg-white/2 border-white/5 opacity-50"
: "bg-white/3 border-white/5 hover:border-accent-purple/30"
}`}
>
<div className="flex items-center space-x-3">
<MapPin className={`w-4 h-4 ${visited ? "text-white/40" : "text-accent-purple animate-bounce"}`} />
<div className="text-xs font-semibold text-white">{loc.name}</div>
</div>
<button
onClick={() => handleCheckin(loc.id, loc.name, loc.reward)}
disabled={visited}
className={`px-3 py-1.5 rounded-lg text-xs font-bold transition-all cursor-pointer ${
visited
? "bg-white/5 text-white/40 cursor-not-allowed"
: "bg-accent-purple text-white hover:bg-accent-purple/90"
}`}
>
{visited ? "Visited" : `Check In (+${loc.reward} LYT)`}
</button>
</div>
);
})}
</div>
</div>
</div>
<div className="mt-8 text-center text-xs text-white/40">
<span className="font-semibold text-accent-purple">Glow tips:</span> Allow location permissions in-app to auto check-in.
</div>
</div>
{/* Card 4: Refer to Earn (Social Loop) */}
<div className="glassmorphism rounded-3xl p-8 flex flex-col justify-between group hover:border-accent-orange/20 transition-all duration-300">
<div className="space-y-6">
<div className="flex items-center justify-between">
<div className="w-12 h-12 rounded-2xl bg-accent-orange/10 border border-accent-orange/20 flex items-center justify-center text-accent-orange">
<Share2 className="w-6 h-6" />
</div>
<span className="text-xs font-bold px-3 py-1 rounded-full bg-white/5 text-white/50 border border-white/5">
50 LYTs / Referral
</span>
</div>
<div className="space-y-2">
<h3 className="text-2xl font-bold font-sora text-white">Refer-to-Earn</h3>
<p className="text-white/60 text-sm">
Everything is better with friends. Send your personal link to your friends. Get 50 LYTs the second they verify their profile!
</p>
</div>
{/* Referral Widget */}
<div className="bg-[#0b0b0b] border border-white/5 rounded-2xl p-5 space-y-4">
<div>
<label className="text-[10px] font-bold text-white/40 uppercase tracking-widest block mb-2">
Your Invite Link:
</label>
<div className="relative flex">
<input
type="text"
readOnly
value={referralCode}
className="w-full bg-white/3 border border-white/10 rounded-xl px-4 py-3 text-xs text-white/80 font-mono focus:outline-none select-all pr-12"
/>
<div className="absolute right-3 top-1/2 -translate-y-1/2 text-white/40">
<Share2 className="w-4 h-4" />
</div>
</div>
</div>
<div className="text-xs text-white/50 leading-relaxed bg-white/3 p-3 rounded-xl border border-white/5">
🔥 <span className="text-white font-semibold">Bonus:</span> Your friends also start with <span className="text-primary font-bold">50 LYTs</span> in their wallet when they sign up!
</div>
</div>
</div>
<div className="mt-8">
<button
onClick={handleCopyReferral}
className={`w-full py-4 rounded-xl font-extrabold text-sm tracking-wider flex items-center justify-center gap-2 cursor-pointer transition-all ${
referralCopied
? "bg-accent-lime text-dark shadow-[0_0_20px_rgba(200,255,55,0.3)]"
: "bg-white/5 hover:bg-accent-orange hover:text-white text-white border border-white/10 hover:border-accent-orange"
}`}
>
{referralCopied ? (
<>
<ClipboardCheck className="w-5 h-5 animate-bounce" />
<span>Copied! +50 LYTs Added to wallet</span>
</>
) : (
<>
<span>Copy Invite Link & Earn</span>
</>
)}
</button>
</div>
</div>
</div>
</div>
</section>
);
}