replay canvas

This commit is contained in:
FURRO404
2026-06-18 20:10:47 -07:00
parent 4fd5dd0fc9
commit fb08e99e5d
4 changed files with 1823 additions and 4 deletions
+30 -4
View File
@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import Tree, { prewarmTreeCanvas } from '../Tree/Tree'
import FallingLeaves from '../Tree/FallingLeaves'
import ReplayCanvasPanel from './ReplayCanvas'
const numberFormat = new Intl.NumberFormat('en-GB')
const dateFormat = new Intl.DateTimeFormat('en-GB', {
@@ -152,13 +153,36 @@ function displayTeamName(value) {
return String(value || '').trim()
}
function ParticipantNames({ participants }) {
function ParticipantNames({ participants, spread = false }) {
if (!participants.length) {
return <p className="truncate text-sm font-semibold text-text-soft">Participants unknown</p>
}
// On wide rows (battle logs), spread the two teams to opposite ends with a
// centered "vs" so each side gets an equal share of the available width.
if (spread && participants.length === 2) {
const [first, second] = participants
return (
<div className="flex min-w-0 items-center gap-x-3">
<span
className={`min-w-0 flex-1 truncate text-left text-sm font-semibold ${first.result === 'win' ? 'text-win' : 'text-loss'}`}
>
{first.name}
</span>
<span className="shrink-0 text-xs font-semibold uppercase tracking-wide text-text-muted">
vs
</span>
<span
className={`min-w-0 flex-1 truncate text-right text-sm font-semibold ${second.result === 'win' ? 'text-win' : 'text-loss'}`}
>
{second.name}
</span>
</div>
)
}
return (
<div className="flex min-w-0 flex-wrap gap-x-3 gap-y-1">
<div className={`flex min-w-0 flex-wrap gap-x-3 gap-y-1${spread ? ' justify-between' : ''}`}>
{participants.map((participant) => (
<span
className={`truncate text-sm font-semibold ${participant.result === 'win' ? 'text-win' : 'text-loss'}`}
@@ -3085,6 +3109,8 @@ function GamePage({ gameId, navigate }) {
</div>
</div>
<ReplayCanvasPanel gameId={gameId} />
{battleEvents.length || logs.battle_log.length ? (
<details className="rounded-lg border border-border bg-fury-white shadow-sm">
<summary className="cursor-pointer px-5 py-4 font-semibold">Battle Log</summary>
@@ -3275,7 +3301,7 @@ function BattleLogsPage({ live, matches, navigate }) {
<div className="overflow-hidden rounded-lg border border-border bg-fury-white shadow-sm">
{matches.map((match) => (
<button
className="grid w-full gap-4 border-b border-surface px-5 py-4 text-left transition hover:bg-surface md:grid-cols-[1fr_minmax(10rem,0.8fr)_auto] md:items-center"
className="grid w-full gap-x-8 gap-y-2 border-b border-surface px-5 py-4 text-left transition hover:bg-surface md:grid-cols-[minmax(0,0.9fr)_minmax(0,1.7fr)_auto] md:items-center"
key={match.session_id}
onClick={() => navigate(gamePath(match.session_id))}
type="button"
@@ -3286,7 +3312,7 @@ function BattleLogsPage({ live, matches, navigate }) {
{formatDate(match.timestamp)} · {match.session_id}
</p>
</div>
<ParticipantNames participants={gameParticipants(match)} />
<ParticipantNames participants={gameParticipants(match)} spread />
<p className="text-sm">{formatMatchSize(match.player_count)}</p>
</button>
))}