diff --git a/docs/leaderboard.md b/docs/leaderboard.md index e67fe8c..1259a21 100644 --- a/docs/leaderboard.md +++ b/docs/leaderboard.md @@ -35,6 +35,13 @@ History pagination retains the selection and return link. Map links preserve the selected ranking metric. A player without qualifying matches in a selection can still view their lifetime profile and choose another scope. +On phones, per-map records and match history use compact cards with the map, +game, highest round and kills up front. Expand **All stats and record runs** +or **More match stats** for the remaining counters and source evidence. Desktop +profiles retain the complete tables; both views use the same history filters +and pagination. History dates say **First observed**, since a missing start +report can make the first recorded observation later than the actual game start. + Highest-round, best-game-kill and highest-score records link to the completed match that earned them on the leaderboard and in lifetime/per-map profile stats. Each source shows its map, game, completion time, server, and whether the match diff --git a/src/lib/ui/components/PlayerMapCards.svelte b/src/lib/ui/components/PlayerMapCards.svelte new file mode 100644 index 0000000..dbe40ab --- /dev/null +++ b/src/lib/ui/components/PlayerMapCards.svelte @@ -0,0 +1,66 @@ + + +
+ {#each maps as map (`${map.game}:${map.key}`)} +
+
+

{gameName(map.game)}

+

{map.name}

+

Last played

+
+
+
Highest round
{number.format(map.highestRound)}
+
Total kills
{number.format(map.kills)}
+
+
+ All stats and record runs +
+ {#each otherMetrics as metric (metric.key)} +
{metric.label}
{number.format(map[metric.key])}
+ {/each} +
+
+ {#each recordMetrics as key (key)} +
+

{playerStatMetrics.find(metric => metric.key === key)!.label} · {number.format(map[key])}

+ +
+ {/each} +
+
+
+ {/each} +
+ + diff --git a/src/lib/ui/components/PlayerMatchCards.svelte b/src/lib/ui/components/PlayerMatchCards.svelte new file mode 100644 index 0000000..4d26875 --- /dev/null +++ b/src/lib/ui/components/PlayerMatchCards.svelte @@ -0,0 +1,64 @@ + + +
+ {#each matches as match (match.id)} +
+
+

{gameName(match.game)}

+

{#if match.status === 'completed'}{match.mapName}{:else}{match.mapName}{/if}

+

{match.server} {#if match.server_deleted_at}Deleted{/if}

+
+
+
First observed
+
Match status
{match.status} · {match.completed ? 'Completion credited' : 'No completion credit'}
+
+
+
Highest round
{number.format(match.highestRound)}
+
Kills
{number.format(match.kills)}
+
+
+ More match stats +
+ {#each otherMetrics as key (key)} +
{playerStatMetrics.find(metric => metric.key === key)!.label}
{number.format(match[key])}
+ {/each} +
+

Last observed

+

Match #{match.id}

+
+
+ {/each} +
+ + diff --git a/src/routes/leaderboard/players/[guid]/+page.svelte b/src/routes/leaderboard/players/[guid]/+page.svelte index 1f0c3c6..fca48f9 100644 --- a/src/routes/leaderboard/players/[guid]/+page.svelte +++ b/src/routes/leaderboard/players/[guid]/+page.svelte @@ -10,6 +10,8 @@ import CopyValue from '$ui/components/CopyValue.svelte'; import Badge from '$ui/components/primitives/Badge.svelte'; import RecordSource from '$ui/components/RecordSource.svelte'; + import PlayerMapCards from '$ui/components/PlayerMapCards.svelte'; + import PlayerMatchCards from '$ui/components/PlayerMatchCards.svelte'; import EmptyState from '$ui/components/primitives/EmptyState.svelte'; let { data }: { data: { profile: PlayerProfile; returnTo: string; @@ -101,8 +103,9 @@

Per-map records

Personal best rounds and every tracked stat across both games, ordered by highest round.

+
-
+
{#each playerStatMetrics as metric}{/each}{#each profile.maps as map (`${map.game}:${map.key}`)} @@ -116,10 +119,11 @@

Match history

Completed matches in the selected game and map, most recently observed first. Stats reflect this player's participation.

{#if profile.matches.length} +
-
+
Map{metric.label}
- {#each historyColumns as key}{/each} + {#each historyColumns as key}{/each}{#each profile.matches as match (match.id)} @@ -129,7 +133,7 @@
Map / serverMatch startedMatch status{playerStatMetrics.find(metric => metric.key === key)!.label}
Map / serverFirst observedMatch status{playerStatMetrics.find(metric => metric.key === key)!.label}
{#if match.status === 'completed'}{match.mapName}{:else}{match.mapName}{/if}{gameName(match.game)}{match.server} {#if match.server_deleted_at}Deleted{/if}{date(match.startedAt)} {match.status}{match.completed ? 'Completion credited' : 'No completion credit'}
{:else}{#snippet actions()}{/snippet}{/if}
@@ -142,7 +146,7 @@