feat(flappy): keep current pilot visible on leaderboard
This commit is contained in:
parent
f69c7ca0b4
commit
643e282fe7
1 changed files with 27 additions and 8 deletions
|
|
@ -36,6 +36,7 @@ interface LeaderboardRow {
|
||||||
bestScore: number;
|
bestScore: number;
|
||||||
xpEarned: number;
|
xpEarned: number;
|
||||||
isCurrentUser: boolean;
|
isCurrentUser: boolean;
|
||||||
|
isOutsideTopTen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FlappyLeaderboardProps {
|
interface FlappyLeaderboardProps {
|
||||||
|
|
@ -60,9 +61,10 @@ export function FlappyLeaderboard({ refreshKey = 0, currentUserId, activePilots
|
||||||
setFailed(false);
|
setFailed(false);
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
"where[progression.minigames.flappyBird.bestScore][greater_than]": "0",
|
|
||||||
sort: "-progression.minigames.flappyBird.bestScore",
|
sort: "-progression.minigames.flappyBird.bestScore",
|
||||||
limit: "10",
|
// Fetch enough profiles to keep the current pilot visible even when
|
||||||
|
// they have not completed a scored run yet.
|
||||||
|
limit: "100",
|
||||||
depth: "1",
|
depth: "1",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -73,8 +75,7 @@ export function FlappyLeaderboard({ refreshKey = 0, currentUserId, activePilots
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
setRows(
|
const mapped: LeaderboardRow[] = (data.docs ?? []).map((doc) => {
|
||||||
(data.docs ?? []).map((doc) => {
|
|
||||||
const flappy = doc.progression?.minigames?.flappyBird ?? {};
|
const flappy = doc.progression?.minigames?.flappyBird ?? {};
|
||||||
const user = typeof doc.user === "object" && doc.user !== null ? doc.user : null;
|
const user = typeof doc.user === "object" && doc.user !== null ? doc.user : null;
|
||||||
const name =
|
const name =
|
||||||
|
|
@ -88,8 +89,14 @@ export function FlappyLeaderboard({ refreshKey = 0, currentUserId, activePilots
|
||||||
xpEarned: flappy.xpEarned ?? 0,
|
xpEarned: flappy.xpEarned ?? 0,
|
||||||
isCurrentUser: user ? String(user.id) === String(currentUserId) : false,
|
isCurrentUser: user ? String(user.id) === String(currentUserId) : false,
|
||||||
};
|
};
|
||||||
}),
|
});
|
||||||
);
|
const scored = mapped.filter((row) => row.bestScore > 0);
|
||||||
|
const visible = scored.slice(0, 10);
|
||||||
|
const current = mapped.find((row) => row.isCurrentUser);
|
||||||
|
if (current && !visible.some((row) => row.id === current.id)) {
|
||||||
|
visible.push({ ...current, isOutsideTopTen: true });
|
||||||
|
}
|
||||||
|
setRows(visible);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
if (!cancelled) setFailed(true);
|
if (!cancelled) setFailed(true);
|
||||||
|
|
@ -141,9 +148,16 @@ export function FlappyLeaderboard({ refreshKey = 0, currentUserId, activePilots
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-border">
|
<tbody className="divide-y divide-border">
|
||||||
{rows.map((row, i) => (
|
{rows.map((row, i) => (
|
||||||
<tr key={row.id} className={cn(row.isCurrentUser && "bg-accent/40")}>
|
<tr
|
||||||
|
key={row.id}
|
||||||
|
className={cn(
|
||||||
|
row.isCurrentUser && "bg-accent/40",
|
||||||
|
row.isOutsideTopTen && "text-muted-foreground opacity-70",
|
||||||
|
)}
|
||||||
|
title={row.isOutsideTopTen ? "Pilot status — not currently ranked in the top 10" : undefined}
|
||||||
|
>
|
||||||
<td className="px-4 py-2">
|
<td className="px-4 py-2">
|
||||||
<span className={rankClass(i)}>{i + 1}</span>
|
<span className={rankClass(i)}>{row.isOutsideTopTen ? "—" : i + 1}</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2 py-2 font-medium">
|
<td className="px-2 py-2 font-medium">
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
|
|
@ -151,6 +165,11 @@ export function FlappyLeaderboard({ refreshKey = 0, currentUserId, activePilots
|
||||||
{row.isCurrentUser && (
|
{row.isCurrentUser && (
|
||||||
<span className="shrink-0 text-xs text-muted-foreground">(you)</span>
|
<span className="shrink-0 text-xs text-muted-foreground">(you)</span>
|
||||||
)}
|
)}
|
||||||
|
{row.isOutsideTopTen && (
|
||||||
|
<span className="shrink-0 text-[10px] font-normal uppercase tracking-wide text-muted-foreground">
|
||||||
|
unranked
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
{activePilots.some((pilot) => pilot.id === row.id) && (
|
{activePilots.some((pilot) => pilot.id === row.id) && (
|
||||||
<span className="size-2 rounded-full bg-emerald-400" title="Playing now" aria-label="Playing now" />
|
<span className="size-2 rounded-full bg-emerald-400" title="Playing now" aria-label="Playing now" />
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue