Files
pragativeer-v2/src/app/dashboard/leaderboard/page.tsx

147 lines
8.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { useState } from "react"
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
import { Trophy, Medal, Star, Shield, Search } from "lucide-react"
type LeaderboardTab = 'all-india' | 'state' | 'school'
export default function LeaderboardPage() {
const [activeTab, setActiveTab] = useState<LeaderboardTab>('all-india')
const [isAnonymous, setIsAnonymous] = useState(false)
// Mock data representing F-07 requirements (Accuracy x Consistency)
const rankings = [
{ rank: 1, name: "Rahul Verma", score: 9850, accuracy: "92%", streak: 45, isCurrentUser: false },
{ rank: 2, name: "Priya Sharma", score: 9420, accuracy: "89%", streak: 42, isCurrentUser: false },
{ rank: 3, name: "Amit Kumar", score: 9100, accuracy: "87%", streak: 38, isCurrentUser: false },
{ rank: 4, name: "Sneha Patel", score: 8950, accuracy: "85%", streak: 30, isCurrentUser: false },
{ rank: 5, name: "Vikram Singh", score: 8800, accuracy: "84%", streak: 28, isCurrentUser: false },
{ rank: 6, name: "Demo Student", score: 8650, accuracy: "82%", streak: 25, isCurrentUser: true },
{ rank: 7, name: "Ananya Desai", score: 8500, accuracy: "80%", streak: 20, isCurrentUser: false },
{ rank: 8, name: "Karan Johar", score: 8450, accuracy: "79%", streak: 18, isCurrentUser: false },
{ rank: 9, name: "Neha Gupta", score: 8300, accuracy: "78%", streak: 15, isCurrentUser: false },
{ rank: 10, name: "Rohan Das", score: 8100, accuracy: "75%", streak: 12, isCurrentUser: false },
]
return (
<div className="p-8 space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500 max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row justify-between items-start md:items-end gap-4">
<div>
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">
<span className="p-2.5 rounded-xl bg-[#00F0FF]/10 border border-[#00F0FF]/20">
<Trophy className="text-[#00F0FF]" size={28} />
</span>
Leaderboard
</h1>
<p className="text-muted-foreground text-base font-medium max-w-2xl pl-1">
Rankings are based on your Accuracy × Consistency (Streak Bonus).
</p>
</div>
<div className="flex items-center gap-3 bg-secondary/50 p-1.5 rounded-xl border border-border">
<button
onClick={() => setActiveTab('all-india')}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${activeTab === 'all-india' ? 'bg-background shadow-sm border border-border text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
>
All India
</button>
<button
onClick={() => setActiveTab('state')}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${activeTab === 'state' ? 'bg-background shadow-sm border border-border text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
>
State
</button>
<button
onClick={() => setActiveTab('school')}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${activeTab === 'school' ? 'bg-background shadow-sm border border-border text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
>
School
</button>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-4">
<div className="flex justify-between items-center bg-card border border-border rounded-xl p-4 shadow-sm sticky top-0 z-10 backdrop-blur-md bg-opacity-90">
<span className="text-sm font-bold text-muted-foreground w-12 text-center">RANK</span>
<span className="text-sm font-bold text-muted-foreground flex-1 px-4">STUDENT</span>
<div className="flex gap-8 w-48 justify-end pr-4">
<span className="text-sm font-bold text-muted-foreground text-center">SCORE</span>
<span className="text-sm font-bold text-muted-foreground text-center">STREAK</span>
</div>
</div>
<div className="space-y-3">
{rankings.map((student) => (
<div
key={student.rank}
className={`flex justify-between items-center p-4 rounded-xl border transition-all ${
student.isCurrentUser
? 'border-[#00F0FF] bg-[#00F0FF]/5 shadow-[0_0_15px_-3px_rgba(0,240,255,0.2)]'
: 'border-border bg-card hover:bg-secondary/20'
}`}
>
<div className="w-12 flex justify-center">
{student.rank === 1 ? <Medal className="text-yellow-500" size={24} /> :
student.rank === 2 ? <Medal className="text-gray-400" size={24} /> :
student.rank === 3 ? <Medal className="text-amber-700" size={24} /> :
<span className={`font-bold text-lg ${student.isCurrentUser ? 'text-[#00F0FF]' : 'text-muted-foreground'}`}>#{student.rank}</span>}
</div>
<div className="flex-1 px-4 flex items-center gap-3">
<div className={`h-10 w-10 rounded-full flex items-center justify-center font-bold text-sm ${
student.isCurrentUser ? 'bg-[#00F0FF]/20 text-[#00F0FF]' : 'bg-secondary text-muted-foreground'
}`}>
{student.name.substring(0, 2).toUpperCase()}
</div>
<div>
<p className={`font-bold ${student.isCurrentUser ? 'text-[#00F0FF]' : 'text-foreground'}`}>
{student.isCurrentUser ? (isAnonymous ? "Anonymous User" : student.name + " (You)") : student.name}
</p>
<p className="text-xs text-muted-foreground flex items-center gap-1">
<Shield size={12} /> Accuracy: {student.accuracy}
</p>
</div>
</div>
<div className="flex gap-8 w-48 justify-end pr-4 items-center">
<div className="text-center font-mono font-bold text-foreground">
{student.score.toLocaleString()}
</div>
<div className="text-center flex items-center gap-1 font-bold text-orange-500">
<Star size={14} className="fill-orange-500" /> {student.streak}
</div>
</div>
</div>
))}
</div>
</div>
<div className="space-y-6">
<Card className="border-[#00F0FF]/30 bg-gradient-to-br from-[#00F0FF]/10 to-transparent">
<CardHeader className="pb-2">
<CardTitle className="text-xl flex items-center gap-2">Your Standing</CardTitle>
</CardHeader>
<CardContent>
<div className="text-4xl font-black text-[#00F0FF] mb-1">#6</div>
<p className="text-sm font-medium text-foreground mb-4">Top 15% of users</p>
<p className="text-xs text-muted-foreground leading-relaxed">
You are 150 points away from breaking into the Top 5. Complete today's DPS to earn your streak bonus!
</p>
<div className="mt-6 flex items-center justify-between border-t border-border pt-4">
<span className="text-sm font-medium text-foreground">Anonymous Mode</span>
<label className="relative inline-flex items-center cursor-pointer">
<input type="checkbox" className="sr-only peer" checked={isAnonymous} onChange={() => setIsAnonymous(!isAnonymous)} />
<div className="w-11 h-6 bg-secondary peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#00F0FF]"></div>
</label>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
)
}