import React, { useState, useEffect, useContext, useCallback } from "react"; import axios from "axios"; import { toast } from "react-toastify"; import { AuthContext } from "../context/AuthContext"; import LeaderboardCard from "./LeaderboardCard"; /** * Leaderboard component displays top users by points with different timeframes */ const Leaderboard = () => { const { auth } = useContext(AuthContext); const [activeTab, setActiveTab] = useState("global"); const [leaderboard, setLeaderboard] = useState([]); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const limit = 50; // Load leaderboard data based on active tab const loadLeaderboard = useCallback(async () => { try { setLoading(true); setError(null); const offset = (page - 1) * limit; let endpoint = ""; switch (activeTab) { case "global": endpoint = `/api/leaderboard/global?limit=${limit}&offset=${offset}`; break; case "weekly": endpoint = `/api/leaderboard/weekly?limit=${limit}&offset=${offset}`; break; case "monthly": endpoint = `/api/leaderboard/monthly?limit=${limit}&offset=${offset}`; break; case "friends": endpoint = `/api/leaderboard/friends?limit=${limit}&offset=${offset}`; break; default: endpoint = `/api/leaderboard/global?limit=${limit}&offset=${offset}`; } const config = {}; // Friends endpoint requires authentication if (activeTab === "friends") { const token = localStorage.getItem("token"); config.headers = { "x-auth-token": token }; } const res = await axios.get(endpoint, config); setLeaderboard(res.data); setHasMore(res.data.length === limit); } catch (err) { console.error("Error loading leaderboard:", err); const errorMessage = err.response?.data?.msg || err.response?.data?.message || "Failed to load leaderboard. Please try again later."; setError(errorMessage); toast.error(errorMessage); } finally { setLoading(false); } }, [activeTab, page]); // Load leaderboard stats const loadStats = useCallback(async () => { try { const res = await axios.get("/api/leaderboard/stats"); setStats(res.data); } catch (err) { console.error("Error loading leaderboard stats:", err); } }, []); useEffect(() => { loadLeaderboard(); }, [loadLeaderboard]); useEffect(() => { loadStats(); }, [loadStats]); // Handle tab change const handleTabChange = (tab) => { if (tab === "friends" && !auth.isAuthenticated) { toast.warning("Please login to view friends leaderboard"); return; } setActiveTab(tab); setPage(1); setLeaderboard([]); }; // Handle pagination const handlePreviousPage = () => { if (page > 1) { setPage(page - 1); } }; const handleNextPage = () => { if (hasMore) { setPage(page + 1); } }; if (loading && leaderboard.length === 0) { return (
Loading leaderboard...
{error}