v1.6.0: leaderboard pane from the top-bar additional-panels button (ISS-115)
CI / build + unit + e2e (pull_request) Successful in 14m2s
CI / build + unit + e2e (pull_request) Successful in 14m2s
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import { formatCash } from '@/lib/format';
|
||||
import type { PlayerSummary } from '@/lib/game/state';
|
||||
|
||||
// v1.6.0 (ISS-115): leaderboard panel — every player in the world with cash, reputation and
|
||||
// plane count, rendered straight off the shared snapshot (no endpoint of its own). Sorted by
|
||||
// reputation desc; cash then username break ties deterministically so rows don't shuffle
|
||||
// between snapshots when two players share a reputation.
|
||||
export default function Leaderboard({ players }: { players: PlayerSummary[] }) {
|
||||
const sorted = [...players].sort(
|
||||
(a, b) => b.reputation - a.reputation || b.cash - a.cash || a.username.localeCompare(b.username),
|
||||
);
|
||||
return (
|
||||
<div className="leaderboard">
|
||||
<table data-testid="leaderboard-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Cash</th>
|
||||
<th>Reputation</th>
|
||||
<th>Planes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sorted.map((p) => (
|
||||
<tr key={p.id} data-testid={`leaderboard-row-${p.id}`}>
|
||||
<td>{p.username}</td>
|
||||
<td>{formatCash(p.cash)}</td>
|
||||
<td>{p.reputation}</td>
|
||||
<td>{p.planeCount}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user