158 lines
6.1 KiB
TypeScript
158 lines
6.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { useUser } from "@/lib/context";
|
|
import { Users, Footprints, Check, Zap, Landmark } from "lucide-react";
|
|
import { motion } from "framer-motion";
|
|
|
|
interface TeamChallenge {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
reward: number;
|
|
current: number;
|
|
goal: number;
|
|
joined: boolean;
|
|
icon: React.ReactNode;
|
|
}
|
|
|
|
export default function SquadChallenges() {
|
|
const { addLyts } = useUser();
|
|
const [challenges, setChallenges] = useState<TeamChallenge[]>([
|
|
{
|
|
id: "ch-steps",
|
|
title: "Weekend Step Sprint",
|
|
description: "Collectively log 50,000 steps with your team this weekend.",
|
|
reward: 100,
|
|
current: 41200,
|
|
goal: 50000,
|
|
joined: false,
|
|
icon: <Footprints className="w-5 h-5 text-accent-lime" />,
|
|
},
|
|
{
|
|
id: "ch-stores",
|
|
title: "Starbucks Double Drop",
|
|
description: "Check in at any two Starbucks locations within 7 days.",
|
|
reward: 40,
|
|
current: 1,
|
|
goal: 2,
|
|
joined: true,
|
|
icon: <Landmark className="w-5 h-5 text-emerald-400" />,
|
|
},
|
|
]);
|
|
|
|
const handleJoinChallenge = (id: string, reward: number) => {
|
|
setChallenges((prev) =>
|
|
prev.map((ch) => {
|
|
if (ch.id === id) {
|
|
if (ch.joined) {
|
|
addLyts(reward);
|
|
return { ...ch, current: ch.goal };
|
|
}
|
|
return { ...ch, joined: true };
|
|
}
|
|
return ch;
|
|
})
|
|
);
|
|
};
|
|
|
|
return (
|
|
<section className="py-24 bg-[#090909] relative overflow-hidden">
|
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
|
|
|
<div className="glassmorphism rounded-3xl p-8 sm:p-12 border border-primary/10 space-y-8">
|
|
<div className="text-left space-y-4">
|
|
<div className="w-12 h-12 rounded-2xl bg-primary/10 border border-primary/20 flex items-center justify-center text-primary">
|
|
<Users className="w-6 h-6" />
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<span className="text-primary font-bold text-xs uppercase tracking-wider">Section 13 • Squad Goals</span>
|
|
<h3 className="text-2xl sm:text-4xl font-extrabold font-sora text-white">
|
|
Cooperative Team <br />
|
|
<span className="text-glow-yellow text-primary">Active Challenges</span>
|
|
</h3>
|
|
<p className="text-white/60 text-sm leading-relaxed">
|
|
Connect with friends or match with nearby community squads. Log steps, complete visits, and unlock bulk LYT currency bonuses together.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Challenges listing */}
|
|
<div className="space-y-4 pt-4">
|
|
{challenges.map((ch) => {
|
|
const percentage = Math.min(100, Math.round((ch.current / ch.goal) * 100));
|
|
const isCompleted = ch.current >= ch.goal;
|
|
|
|
return (
|
|
<div
|
|
key={ch.id}
|
|
className={`glassmorphism rounded-2xl p-6 border transition-colors ${
|
|
ch.joined ? "border-primary/20 bg-primary/2" : "border-white/5"
|
|
}`}
|
|
>
|
|
<div className="flex justify-between items-start gap-4 mb-4">
|
|
<div className="flex items-center space-x-3">
|
|
<div className="w-10 h-10 rounded-xl bg-white/5 border border-white/10 flex items-center justify-center">
|
|
{ch.icon}
|
|
</div>
|
|
<div>
|
|
<h4 className="text-sm font-bold text-white font-sora">{ch.title}</h4>
|
|
<p className="text-white/60 text-xs mt-0.5 leading-relaxed">{ch.description}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="text-right">
|
|
<span className="text-[9px] text-white/40 font-bold uppercase tracking-wider block">Reward</span>
|
|
<span className="text-xs font-extrabold text-primary">+{ch.reward} LYTs</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between text-xs font-semibold">
|
|
<span className="text-white/50">{ch.current.toLocaleString()} / {ch.goal.toLocaleString()}</span>
|
|
<span className="text-primary">{percentage}%</span>
|
|
</div>
|
|
<div className="w-full h-1.5 bg-white/5 rounded-full overflow-hidden">
|
|
<div
|
|
style={{ width: `${percentage}%` }}
|
|
className="h-full bg-gradient-to-r from-primary to-accent-lime rounded-full"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-4 flex justify-end">
|
|
<button
|
|
onClick={() => handleJoinChallenge(ch.id, ch.reward)}
|
|
disabled={isCompleted}
|
|
className={`px-4 py-2 rounded-xl text-xs font-bold transition-all flex items-center gap-1.5 cursor-pointer ${
|
|
isCompleted
|
|
? "bg-accent-lime/10 border border-accent-lime/20 text-accent-lime cursor-not-allowed"
|
|
: ch.joined
|
|
? "bg-primary text-dark hover:bg-primary/90"
|
|
: "bg-white/5 border border-white/10 text-white hover:bg-white/10"
|
|
}`}
|
|
>
|
|
{isCompleted ? (
|
|
<>
|
|
<Check className="w-3.5 h-3.5" />
|
|
<span>Claimed</span>
|
|
</>
|
|
) : ch.joined ? (
|
|
<span>Complete & Claim</span>
|
|
) : (
|
|
<span>Join Squad Goal</span>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|