import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Progress } from '@/components/ui/progress'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Trophy, Medal, Award, TrendingUp, Users, Target, Zap, Shield, Star, Crown, Gem, Flame, Rocket, Calendar, Filter, Download, RefreshCw } from 'lucide-react'; import { useToast } from '@/hooks/use-toast'; import { formatDistanceToNow } from 'date-fns'; interface LeaderboardEntry { address: string; rank: number; total_earned: number; submissions: number; avg_accuracy: number; success_rate: number; bounties_completed: number; tier: 'bronze' | 'silver' | 'gold' | 'platinum' | 'diamond'; reputation_score: number; last_active: string; streak_days: number; weekly_growth: number; monthly_growth: number; } interface TopPerformer { address: string; rank: number; metric: string; value: number; change: number; badge?: string; } interface CategoryStats { category: string; total_earnings: number; participant_count: number; avg_earnings: number; top_performer: string; growth_rate: number; } const DeveloperLeaderboard: React.FC = () => { const { toast } = useToast(); const [leaderboard, setLeaderboard] = useState([]); const [topPerformers, setTopPerformers] = useState([]); const [categoryStats, setCategoryStats] = useState([]); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState('earnings'); const [period, setPeriod] = useState('weekly'); const [category, setCategory] = useState('all'); const [metric, setMetric] = useState('total_earned'); const [lastUpdated, setLastUpdated] = useState(new Date()); // Load leaderboard data on component mount useEffect(() => { loadLeaderboard(); loadTopPerformers(); loadCategoryStats(); }, [period, category, metric]); const loadLeaderboard = async () => { try { setLoading(true); const response = await fetch(`/api/v1/bounties/leaderboard?period=${period}&limit=100`); if (response.ok) { const data = await response.json(); setLeaderboard(data); setLastUpdated(new Date()); } else { throw new Error('Failed to load leaderboard'); } } catch (error) { console.error('Error loading leaderboard:', error); toast({ title: 'Error', description: 'Failed to load leaderboard data', variant: 'destructive' }); } finally { setLoading(false); } }; const loadTopPerformers = async () => { try { const response = await fetch(`/api/v1/ecosystem/top-performers?category=${category}&period=${period}&limit=10`); if (response.ok) { const data = await response.json(); setTopPerformers(data.performers); } } catch (error) { console.error('Error loading top performers:', error); } }; const loadCategoryStats = async () => { try { const response = await fetch(`/api/v1/ecosystem/category-stats?period=${period}`); if (response.ok) { const data = await response.json(); setCategoryStats(data.categories); } } catch (error) { console.error('Error loading category stats:', error); } }; const getRankIcon = (rank: number) => { if (rank === 1) return ; if (rank === 2) return ; if (rank === 3) return ; return #{rank}; }; const getTierColor = (tier: string) => { const colors = { bronze: 'bg-orange-100 text-orange-800 border-orange-200', silver: 'bg-gray-100 text-gray-800 border-gray-200', gold: 'bg-yellow-100 text-yellow-800 border-yellow-200', platinum: 'bg-purple-100 text-purple-800 border-purple-200', diamond: 'bg-blue-100 text-blue-800 border-blue-200' }; return colors[tier as keyof typeof colors] || colors.bronze; }; const getGrowthIcon = (growth: number) => { if (growth > 0) return ; if (growth < 0) return ; return
; }; const getGrowthColor = (growth: number) => { if (growth > 0) return 'text-green-600'; if (growth < 0) return 'text-red-600'; return 'text-gray-600'; }; const exportLeaderboard = async () => { try { const response = await fetch(`/api/v1/ecosystem/export?format=csv&period=${period}`); if (response.ok) { const data = await response.json(); // Create download link const link = document.createElement('a'); link.href = data.url; link.download = `leaderboard_${period}.csv`; link.click(); toast({ title: 'Export Started', description: 'Leaderboard data is being downloaded', }); } } catch (error) { console.error('Error exporting leaderboard:', error); toast({ title: 'Error', description: 'Failed to export leaderboard', variant: 'destructive' }); } }; const refreshData = () => { loadLeaderboard(); loadTopPerformers(); loadCategoryStats(); }; if (loading && leaderboard.length === 0) { return (
); } return (
{/* Header */}

Developer Leaderboard

Top performers in the AITBC developer ecosystem

{/* Top 3 Performers */}
{leaderboard.slice(0, 3).map((performer, index) => (
{getRankIcon(performer.rank)}
{performer.address.slice(0, 8)}...{performer.address.slice(-6)} {performer.tier.charAt(0).toUpperCase() + performer.tier.slice(1)}

{performer.total_earned.toLocaleString()}

AITBC Earned

Submissions

{performer.submissions}

Success Rate

{performer.success_rate.toFixed(1)}%

Avg Accuracy

{performer.avg_accuracy.toFixed(1)}%

Streak

{performer.streak_days} days

Weekly Growth
{getGrowthIcon(performer.weekly_growth)} {performer.weekly_growth > 0 ? '+' : ''}{performer.weekly_growth.toFixed(1)}%
))}
{/* Filters */}
Last updated: {formatDistanceToNow(lastUpdated, { addSuffix: true })}
{/* Tabs */} Earnings Performance Categories Trends {/* Earnings Tab */} Earnings Leaderboard Top developers by total AITBC earnings Rank Developer Tier Total Earned Submissions Success Rate Accuracy Growth {leaderboard.map((entry) => (
{getRankIcon(entry.rank)}
{entry.address.slice(0, 8)}...{entry.address.slice(-6)} {entry.tier.charAt(0).toUpperCase() + entry.tier.slice(1)} {entry.total_earned.toLocaleString()} AITBC {entry.submissions}
{entry.success_rate.toFixed(1)}%
{entry.avg_accuracy.toFixed(1)}%
{getGrowthIcon(entry.weekly_growth)} {entry.weekly_growth > 0 ? '+' : ''}{entry.weekly_growth.toFixed(1)}%
))}
{/* Performance Tab */}
Top Accuracy
{leaderboard .sort((a, b) => b.avg_accuracy - a.avg_accuracy) .slice(0, 5) .map((entry, index) => (
#{index + 1} {entry.address.slice(0, 8)}...{entry.address.slice(-6)}
{entry.avg_accuracy.toFixed(1)}%
))}
Fastest Growth
{leaderboard .sort((a, b) => b.weekly_growth - a.weekly_growth) .slice(0, 5) .map((entry, index) => (
#{index + 1} {entry.address.slice(0, 8)}...{entry.address.slice(-6)}
{getGrowthIcon(entry.weekly_growth)} {entry.weekly_growth > 0 ? '+' : ''}{entry.weekly_growth.toFixed(1)}%
))}
Longest Streaks
{leaderboard .sort((a, b) => b.streak_days - a.streak_days) .slice(0, 5) .map((entry, index) => (
#{index + 1} {entry.address.slice(0, 8)}...{entry.address.slice(-6)}
{entry.streak_days} days
))}
Reputation Leaders
{leaderboard .sort((a, b) => b.reputation_score - a.reputation_score) .slice(0, 5) .map((entry, index) => (
#{index + 1} {entry.address.slice(0, 8)}...{entry.address.slice(-6)} {entry.tier.charAt(0).toUpperCase() + entry.tier.slice(1)}
{entry.reputation_score.toFixed(1)}
))}
{/* Categories Tab */}
{categoryStats.map((category) => ( {category.category} {category.participant_count} participants

{category.total_earnings.toLocaleString()}

Total Earnings

Average Earnings {category.avg_earnings.toLocaleString()} AITBC
Growth Rate {category.growth_rate > 0 ? '+' : ''}{category.growth_rate.toFixed(1)}%

Top Performer

{category.top_performer.slice(0, 8)}...{category.top_performer.slice(-6)}

))}
{/* Trends Tab */}
Weekly Trends
Total Participants {leaderboard.length}
Average Earnings {leaderboard.length > 0 ? (leaderboard.reduce((sum, e) => sum + e.total_earned, 0) / leaderboard.length).toLocaleString() : '0' } AITBC
Success Rate {leaderboard.length > 0 ? (leaderboard.reduce((sum, e) => sum + e.success_rate, 0) / leaderboard.length).toFixed(1) : '0' }%
Average Accuracy {leaderboard.length > 0 ? (leaderboard.reduce((sum, e) => sum + e.avg_accuracy, 0) / leaderboard.length).toFixed(1) : '0' }%
Participant Distribution
{['bronze', 'silver', 'gold', 'platinum', 'diamond'].map((tier) => { const count = leaderboard.filter(e => e.tier === tier).length; const percentage = leaderboard.length > 0 ? (count / leaderboard.length) * 100 : 0; return (
{tier} {count} ({percentage.toFixed(1)}%)
); })}
); }; export default DeveloperLeaderboard;