Профиль: блок истории игр с переключателями режима и подробности
В «Аккаунте» появился блок «История игр» с двумя тумблерами — «Только лучшая партия» и «Подробные карточки»; выбор уходит в профиль, поэтому переживает перезаход и другое устройство. Новый компонент MatchHistory: подробный режим переиспользует список партий группы (MatchListView со всеми участниками), компактный рисует строку с результатом самого игрока — место, фракция, дата и длительность. Публичный профиль показывает ту же историю в режиме владельца и без контролов: страница намеренно read-only. schema.d.ts пересобран с живого бэкенда (npm run gen:api). #1 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { formatDate, formatDuration } from "../domain/format";
|
||||
import type { MatchListItem } from "../domain/types";
|
||||
import { MatchListView } from "./MatchList";
|
||||
|
||||
/**
|
||||
* История партий игрока в профиле. Подробный режим — тот же список, что у группы
|
||||
* (MatchListView со всеми участниками); компактный — строка с результатом самого
|
||||
* владельца профиля, поэтому компонент и принимает его userId.
|
||||
*/
|
||||
export function MatchHistory({
|
||||
items,
|
||||
userId,
|
||||
detail,
|
||||
}: {
|
||||
items: MatchListItem[];
|
||||
userId: number;
|
||||
detail: string;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
if (items.length === 0) return <div className="muted small">Партий пока нет.</div>;
|
||||
if (detail === "full") return <MatchListView items={items} />;
|
||||
|
||||
return (
|
||||
<div className="stack">
|
||||
{items.map((m) => {
|
||||
const mine = m.participants.find((p) => p.user_id === userId);
|
||||
return (
|
||||
<button
|
||||
key={m.id}
|
||||
className="card row-between"
|
||||
style={{ margin: 0, width: "100%", textAlign: "left" }}
|
||||
onClick={() => navigate(`/match/${m.id}`)}
|
||||
>
|
||||
<div className="row" style={{ gap: 10, minWidth: 0 }}>
|
||||
<span
|
||||
className={
|
||||
"place-badge" +
|
||||
(mine?.place === 1 && !mine?.eliminated ? " first" : "") +
|
||||
(mine?.eliminated ? " eliminated" : "")
|
||||
}
|
||||
>
|
||||
{mine?.eliminated ? "✕" : (mine?.place ?? "—")}
|
||||
</span>
|
||||
<span
|
||||
style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}
|
||||
>
|
||||
{mine?.faction_name ?? "—"}
|
||||
</span>
|
||||
</div>
|
||||
<span className="muted small" style={{ flexShrink: 0 }}>
|
||||
{formatDate(m.played_at)} · {formatDuration(m.duration_minutes)}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user