From ced1f04bf11816d2204ab43411759275d4e9c684 Mon Sep 17 00:00:00 2001 From: Etan Joseph Heyman Date: Sun, 15 Feb 2026 04:08:33 +0200 Subject: [PATCH] nightshift: remove as-any casts in leaderboard components Co-Authored-By: Claude Opus 4.6 --- node_modules | 1 + .../dashboard/LeaderboardMiniSection.tsx | 76 +++++++---- src/routes/_authed/leaderboard.tsx | 128 ++++++++++-------- 3 files changed, 122 insertions(+), 83 deletions(-) create mode 120000 node_modules diff --git a/node_modules b/node_modules new file mode 120000 index 0000000..2d38314 --- /dev/null +++ b/node_modules @@ -0,0 +1 @@ +/Users/etanheyman/Gits/songscript/node_modules \ No newline at end of file diff --git a/src/components/dashboard/LeaderboardMiniSection.tsx b/src/components/dashboard/LeaderboardMiniSection.tsx index c17efa2..cab32aa 100644 --- a/src/components/dashboard/LeaderboardMiniSection.tsx +++ b/src/components/dashboard/LeaderboardMiniSection.tsx @@ -8,6 +8,32 @@ import { ToggleGroup, ToggleGroupItem } from "../ui/toggle-group"; import { Button } from "../ui/button"; type LeaderboardType = "streak" | "progress"; +type StreakEntry = { rank: number; displayName: string; streak: number; language: string }; +type ProgressEntry = { rank: number; displayName: string; score: number; topLanguage: string }; + +function MiniLeaderboardRow({ rank, displayName, medal, isCurrentUser, value }: { + rank: number; + displayName: string; + medal: string | null; + isCurrentUser: boolean; + value: string; +}) { + return ( +
+
+ + {medal || `#${rank}`} + + {displayName} +
+
{value}
+
+ ); +} export function LeaderboardMiniSection() { const [selectedType, setSelectedType] = useState("streak"); @@ -35,7 +61,7 @@ export function LeaderboardMiniSection() { ); const hasDisplayName = userInfo?.displayName !== null; - const leaderboardData = selectedType === "streak" ? streakData : progressData; + const isStreak = selectedType === "streak"; // Medal icons for top 3 const getMedalIcon = (rank: number) => { @@ -82,32 +108,28 @@ export function LeaderboardMiniSection() { ) : (
- {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 && } + +
+
+
{value}
+
+
+ ); +} + 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 ( + + ); + }) + }
)}