- {leaderboardData.map((user: typeof leaderboardData[0]) => {
- const isCurrentUser = hasDisplayName && userRank && user.rank === userRank.rank;
- const medal = getMedalIcon(user.rank);
-
- return (
-
-
-
- {medal || `#${user.rank}`}
-
- {user.displayName}
-
-
- {selectedType === "streak"
- ? `${(user as any).streak || 0} days`
- : `${(user as any).score || 0} pts`
- }
-
-
- );
- })}
+ {isStreak
+ ? streakData.map((user: StreakEntry) => (
+
+ ))
+ : progressData.map((user: ProgressEntry) => (
+
+ ))
+ }
{/* Show current user's rank if not in top 5 but in top 50 */}
{hasDisplayName && userRank && userRank.rank > 5 && userRank.rank <= 50 && (
diff --git a/src/routes/_authed/leaderboard.tsx b/src/routes/_authed/leaderboard.tsx
index 38465f7..3d6d524 100644
--- a/src/routes/_authed/leaderboard.tsx
+++ b/src/routes/_authed/leaderboard.tsx
@@ -15,6 +15,45 @@ export const Route = createFileRoute("/_authed/leaderboard")({
type LeaderboardType = "streak" | "progress";
type TimePeriod = "weekly" | "monthly" | "all-time";
+type StreakEntry = { rank: number; displayName: string; streak: number; language: string };
+type ProgressEntry = { rank: number; displayName: string; score: number; topLanguage: string };
+
+function LeaderboardRow({ rank, displayName, medal, isUser, language, value }: {
+ rank: number;
+ displayName: string;
+ medal: string | null;
+ isUser: boolean;
+ language: string;
+ value: string;
+}) {
+ return (
+
+
+ {rank}
+
+
+ {medal && {medal}}
+
+
+ {language}
+
+ {displayName}
+ {isUser && ⭐}
+
+
+
+
+ );
+}
+
function LeaderboardPage() {
const [selectedType, setSelectedType] = useState
("streak");
const [selectedPeriod, setSelectedPeriod] = useState("all-time");
@@ -48,8 +87,9 @@ function LeaderboardPage() {
})
);
- const leaderboardData = selectedType === "streak" ? streakData : progressData;
- const isLoading = selectedType === "streak" ? streakLoading : progressLoading;
+ const isStreak = selectedType === "streak";
+ const leaderboardData = isStreak ? streakData : progressData;
+ const isLoading = isStreak ? streakLoading : progressLoading;
// Medal icons for top 3
const getMedalIcon = (rank: number) => {
@@ -140,60 +180,36 @@ function LeaderboardPage() {
) : (
- {leaderboardData.map((user: typeof leaderboardData[0], index: number) => {
- const rank = offset + index + 1;
- const medal = getMedalIcon(rank);
- const isUser = isCurrentUser(rank);
-
- return (
-
- {/* Rank */}
-
- {rank}
-
-
- {/* Medal for top 3 */}
-
- {medal && {medal}}
-
-
- {/* User info */}
-
- {/* Language flag */}
-
- {getLanguageFlagString(
- selectedType === "streak"
- ? (user as any).language
- : (user as any).topLanguage
- )}
-
-
- {/* Display name with star for current user */}
-
- {user.displayName}
- {isUser && ⭐}
-
-
-
- {/* Score */}
-
-
- {selectedType === "streak"
- ? `${(user as any).streak} days`
- : `${Math.round((user as any).score)} pts`
- }
-
-
-
- );
- })}
+ {isStreak
+ ? streakData.map((user: StreakEntry, index: number) => {
+ const rank = offset + index + 1;
+ return (
+
+ );
+ })
+ : progressData.map((user: ProgressEntry, index: number) => {
+ const rank = offset + index + 1;
+ return (
+
+ );
+ })
+ }
)}