79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import { Link } from "react-router-dom";
|
|
|
|
import type { LeaderboardEntry } from "../domain/types";
|
|
import { Avatar } from "./Avatar";
|
|
|
|
function pct(v: number | null | undefined): string {
|
|
return v == null ? "—" : `${Math.round(v * 100)}%`;
|
|
}
|
|
|
|
function Row({ entry }: { entry: LeaderboardEntry }) {
|
|
return (
|
|
// Вся строка — ссылка на профиль. stopPropagation: на главной карточка-обёртка
|
|
// ведёт в общую статистику, а клик по строке игрока — в его профиль.
|
|
<Link
|
|
to={`/u/${entry.user_id}`}
|
|
className="lb-row"
|
|
style={{ color: "inherit" }}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className={"lb-rank" + (entry.rank && entry.rank <= 3 ? " top" : "")}>
|
|
{entry.rank ?? "—"}
|
|
</div>
|
|
<Avatar url={entry.avatar_url} nickname={entry.nickname} size={32} />
|
|
<div>
|
|
<div style={{ fontWeight: 600 }}>{entry.nickname}</div>
|
|
<div className="lb-metrics">
|
|
<span>Игр: {entry.games}</span>
|
|
<span>Побед: {entry.wins}</span>
|
|
<span>WR: {pct(entry.win_rate)}</span>
|
|
</div>
|
|
</div>
|
|
<div className="lb-score">{entry.score ?? "—"}</div>
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export function Leaderboard({
|
|
entries,
|
|
provisional,
|
|
inactive,
|
|
}: {
|
|
entries: LeaderboardEntry[];
|
|
provisional?: LeaderboardEntry[];
|
|
inactive?: LeaderboardEntry[];
|
|
}) {
|
|
const empty =
|
|
entries.length === 0 && !provisional?.length && !inactive?.length;
|
|
if (empty) {
|
|
return <div className="muted small">Пока нет сыгранных партий.</div>;
|
|
}
|
|
return (
|
|
<div>
|
|
{entries.map((e) => (
|
|
<Row key={e.user_id} entry={e} />
|
|
))}
|
|
{provisional && provisional.length > 0 && (
|
|
<>
|
|
<div className="label" style={{ marginTop: 10 }}>
|
|
Новички (мало игр)
|
|
</div>
|
|
{provisional.map((e) => (
|
|
<Row key={e.user_id} entry={e} />
|
|
))}
|
|
</>
|
|
)}
|
|
{inactive && inactive.length > 0 && (
|
|
<>
|
|
<div className="label" style={{ marginTop: 10 }}>
|
|
Ещё не играли
|
|
</div>
|
|
{inactive.map((e) => (
|
|
<Row key={e.user_id} entry={e} />
|
|
))}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|