UI: выбор игрока при создании партии — выпадашка в стиле подсказок

Вместо нативного select — кнопка-триггер (аватар + ник) с выпадающим
списком всех игроков группы в стилистике подсказок инвайта; игроки,
уже выбранные в других строках, не предлагаются (заодно исключены
дубли). Для аватаров в списке MemberRead теперь отдаёт avatar_url.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 03:00:26 +03:00
co-authored by Claude Fable 5
parent 4a681430af
commit f22ee1ec29
7 changed files with 137 additions and 16 deletions
+18 -10
View File
@@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { ApiError } from "../api/client";
import { PlayerSelect } from "../components/PlayerSelect";
import { Spinner } from "../components/Spinner";
import { MAX_MATCH_PLAYERS } from "../domain/constants";
import { useToast } from "../context/ToastContext";
@@ -55,6 +56,13 @@ export function CreateMatchPage() {
.map((r) => r.faction_id)
.filter((x): x is number => typeof x === "number");
// Игроки, уже выбранные в других строках, — в списке не предлагаются.
const takenUserIds = (exceptIdx: number) =>
rows
.filter((_, i) => i !== exceptIdx)
.map((r) => r.user_id)
.filter((x): x is number => typeof x === "number");
const update = (idx: number, patch: Partial<Draft>) =>
setRows((rs) => rs.map((r, i) => (i === idx ? { ...r, ...patch } : r)));
@@ -181,17 +189,17 @@ export function CreateMatchPage() {
)}
</div>
<select
<PlayerSelect
value={row.user_id}
onChange={(e) => update(idx, { user_id: e.target.value ? Number(e.target.value) : "" })}
>
<option value="">— игрок —</option>
{memberOptions.map((m) => (
<option key={m.user_id} value={m.user_id}>
{m.nickname}
</option>
))}
</select>
options={memberOptions
.filter((m) => !takenUserIds(idx).includes(m.user_id))
.map((m) => ({
user_id: m.user_id,
nickname: m.nickname,
avatar_url: m.avatar_url,
}))}
onPick={(id) => update(idx, { user_id: id })}
/>
<div className="row">
{spin[idx] != null ? (