163 lines
5.7 KiB
TypeScript
163 lines
5.7 KiB
TypeScript
import React from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { Trophy } from "lucide-react";
|
|
|
|
import { Card, CardHeader, CardTitle, CardContent } from "../../components/ui/card";
|
|
import { Button } from "../../components/ui/button";
|
|
import { ScrollArea } from "../../components/ui/scroll-area";
|
|
import { Avatar, AvatarImage, AvatarFallback } from "../../components/ui/avatar";
|
|
|
|
// Global Leaderboard component - increased height to match Recent Activity
|
|
export function GlobalLeaderboard() {
|
|
const leaderboardData = [
|
|
{
|
|
rank: 1,
|
|
name: "Sarah Chen",
|
|
points: 2450,
|
|
avatar: "https://images.unsplash.com/photo-1494790108755-2616b612b5c8?w=80&h=80&fit=crop&crop=face",
|
|
badge: "gold",
|
|
change: "+15"
|
|
},
|
|
{
|
|
rank: 2,
|
|
name: "Marcus Johnson",
|
|
points: 2380,
|
|
avatar: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=80&h=80&fit=crop&crop=face",
|
|
badge: "silver",
|
|
change: "+8"
|
|
},
|
|
{
|
|
rank: 3,
|
|
name: "Emily Rodriguez",
|
|
points: 2320,
|
|
avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=80&h=80&fit=crop&crop=face",
|
|
badge: "bronze",
|
|
change: "+12"
|
|
},
|
|
{
|
|
rank: 4,
|
|
name: "David Kim",
|
|
points: 2180,
|
|
avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=80&h=80&fit=crop&crop=face",
|
|
badge: "regular",
|
|
change: "+5"
|
|
},
|
|
{
|
|
rank: 5,
|
|
name: "Lisa Thompson",
|
|
points: 2140,
|
|
avatar: "https://images.unsplash.com/photo-1517841905240-472988babdf9?w=80&h=80&fit=crop&crop=face",
|
|
badge: "regular",
|
|
change: "+20"
|
|
},
|
|
{
|
|
rank: 6,
|
|
name: "Alex Patel",
|
|
points: 2090,
|
|
avatar: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=80&h=80&fit=crop&crop=face",
|
|
badge: "regular",
|
|
change: "+3"
|
|
},
|
|
{
|
|
rank: 7,
|
|
name: "Your Position",
|
|
points: 1950,
|
|
avatar: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=80&h=80&fit=crop&crop=face",
|
|
badge: "user",
|
|
change: "+18",
|
|
isCurrentUser: true
|
|
},
|
|
{
|
|
rank: 8,
|
|
name: "Jennifer Lee",
|
|
points: 1890,
|
|
avatar: "https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=80&h=80&fit=crop&crop=face",
|
|
badge: "regular",
|
|
change: "+7"
|
|
}
|
|
];
|
|
|
|
const getBadgeColor = (badge: string) => {
|
|
switch (badge) {
|
|
case 'gold': return 'bg-gradient-to-r from-yellow-400 to-yellow-500 text-white';
|
|
case 'silver': return 'bg-gradient-to-r from-gray-300 to-gray-400 text-gray-800';
|
|
case 'bronze': return 'bg-gradient-to-r from-orange-400 to-orange-500 text-white';
|
|
case 'user': return 'bg-gradient-to-r from-brand-navy to-brand-navy/90 text-white';
|
|
default: return 'bg-gray-100 text-gray-600';
|
|
}
|
|
};
|
|
const navigate = useNavigate();
|
|
|
|
return (
|
|
<Card className="h-96 flex flex-col border-0 shadow-lg bg-white">
|
|
<CardHeader className="pb-3 flex-shrink-0">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 bg-gradient-to-br from-brand-gold to-amber-500 rounded-lg flex items-center justify-center">
|
|
<Trophy className="h-4 w-4 text-white" />
|
|
</div>
|
|
<CardTitle className="text-lg font-semibold text-gray-900">
|
|
Global Leaderboard
|
|
</CardTitle>
|
|
</div>
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={() => navigate('/leaderboard?view=individual')}
|
|
className="text-brand-navy hover:bg-brand-navy/10 border-brand-navy/20 text-sm px-3 py-1.5 h-auto font-medium"
|
|
>
|
|
View All
|
|
</Button>
|
|
</div>
|
|
<p className="text-sm text-gray-600 mt-1">
|
|
Top learners this month
|
|
</p>
|
|
</CardHeader>
|
|
|
|
<CardContent className="px-6 pb-4 flex-1 min-h-0">
|
|
<ScrollArea className="h-full">
|
|
<div className="space-y-2 pr-2">
|
|
{leaderboardData.map((user) => (
|
|
<div
|
|
key={user.rank}
|
|
className={`flex items-center gap-3 p-3 rounded-lg transition-all duration-200 hover:shadow-sm ${
|
|
user.isCurrentUser
|
|
? 'bg-gradient-to-r from-brand-navy/5 to-brand-navy/10 border border-brand-navy/20'
|
|
: 'bg-gray-50 hover:bg-gray-100'
|
|
}`}
|
|
>
|
|
{/* Rank */}
|
|
<div className={`w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0 ${getBadgeColor(user.badge)}`}>
|
|
{user.rank}
|
|
</div>
|
|
|
|
{/* Avatar */}
|
|
<Avatar className="h-8 w-8 flex-shrink-0">
|
|
<AvatarImage src={user.avatar} alt={user.name} />
|
|
<AvatarFallback className="text-xs">{user.name.split(' ').map(n => n[0]).join('')}</AvatarFallback>
|
|
</Avatar>
|
|
|
|
{/* User Info */}
|
|
<div className="flex-1 min-w-0">
|
|
<h4 className={`text-sm font-semibold leading-tight ${
|
|
user.isCurrentUser ? 'text-brand-navy' : 'text-gray-900'
|
|
}`}>
|
|
{user.name}
|
|
</h4>
|
|
<p className="text-xs text-gray-600 font-medium">
|
|
{user.points.toLocaleString()} points
|
|
</p>
|
|
</div>
|
|
|
|
{/* Change */}
|
|
<div className="text-xs font-semibold text-green-600 flex-shrink-0">
|
|
{user.change}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</ScrollArea>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
} |