UI: единый PlayerLink — ники игроков кликабельны во всех местах просмотра

Новый компонент PlayerLink (ссылка на /u/:id, кликабельно всё поле строки,
stopPropagation для вложенности в кликабельные карточки). Применён:
- Leaderboard и общая статистика (рефакторинг ручных Link);
- страница партии: результаты и состав;
- настройки группы: список участников;
- список партий и незавершённые на главной (карточки button -> div,
  т.к. ссылки внутри button — невалидная разметка).
«пригласил: X» в приглашениях остаётся текстом — в API нет id пригласившего.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 17:37:19 +03:00
co-authored by Claude Fable 5
parent d81f5d8964
commit cbf3cfc6e6
7 changed files with 68 additions and 28 deletions
+5 -4
View File
@@ -4,6 +4,7 @@ import { useNavigate, useParams } from "react-router-dom";
import { ApiError } from "../api/client";
import { ConfirmDialog } from "../components/ConfirmDialog";
import { MatchMedia } from "../components/MatchMedia";
import { PlayerLink } from "../components/PlayerLink";
import { Spinner } from "../components/Spinner";
import { formatDuration, formatTime } from "../domain/format";
import { WIN_REASONS, type WinReason, winReasonLabel } from "../domain/winReasons";
@@ -145,7 +146,7 @@ export function MatchDetailPage() {
<div className="stack">
{sorted.map((p) => (
<div key={p.user_id}>
<div className="row" style={{ gap: 8 }}>
<PlayerLink userId={p.user_id} className="row" style={{ gap: 8 }}>
<span
className={
"place-badge" +
@@ -158,7 +159,7 @@ export function MatchDetailPage() {
<b>{p.nickname}</b>
<span className="muted small">· {p.faction_name}</span>
{p.was_random && <span className="badge">🎲</span>}
</div>
</PlayerLink>
{p.comment && <div className="small muted" style={{ marginLeft: 32 }}>{p.comment}</div>}
</div>
))}
@@ -181,11 +182,11 @@ export function MatchDetailPage() {
<h3>Состав</h3>
<div className="stack">
{match.participants.map((p) => (
<div key={p.user_id} className="row" style={{ gap: 8 }}>
<PlayerLink key={p.user_id} userId={p.user_id} className="row" style={{ gap: 8 }}>
<b>{p.nickname}</b>
<span className="muted small">· {p.faction_name}</span>
{p.was_random && <span className="badge">🎲</span>}
</div>
</PlayerLink>
))}
</div>
</div>