Группы: приглашения вместо авто-добавления (согласиться/отказаться)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 20:07:20 +03:00
co-authored by Claude Opus 4.8
parent 66370c7df4
commit a5c54512a5
20 changed files with 742 additions and 98 deletions
+5 -1
View File
@@ -1,6 +1,7 @@
import { useNavigate } from "react-router-dom";
import { CreateGroupForm } from "../components/CreateGroupForm";
import { GroupInvitations } from "../components/GroupInvitations";
import { GroupSwitcher } from "../components/GroupSwitcher";
import { Leaderboard } from "../components/Leaderboard";
import { MatchListView } from "../components/MatchList";
@@ -25,9 +26,10 @@ export function GroupPage() {
<div className="card">
<h3>Активная группа не выбрана</h3>
<p className="muted small">
Создайте группу или выберите существующую, чтобы вести учёт партий.
Создайте группу, выберите существующую или примите приглашение, чтобы вести учёт партий.
</p>
</div>
<GroupInvitations />
<GroupSwitcher />
<CreateGroupForm />
</div>
@@ -51,6 +53,8 @@ export function GroupPage() {
</p>
</div>
<GroupInvitations />
<div className="card">
<h3>Топ в группе</h3>
{stats && <Leaderboard entries={stats.leaderboard} provisional={stats.provisional} />}
+10 -6
View File
@@ -6,7 +6,7 @@ import { Spinner } from "../components/Spinner";
import { MAX_GROUP_SIZE } from "../domain/constants";
import { useToast } from "../context/ToastContext";
import { useMe } from "../hooks/auth";
import { useAddMember, useGroup, useGroupMembers, useRemoveMember, useSetGroupExpansions } from "../hooks/groups";
import { useGroup, useGroupMembers, useInviteMember, useRemoveMember, useSetGroupExpansions } from "../hooks/groups";
import { useExpansions } from "../hooks/reference";
export function GroupSettingsPage() {
@@ -16,7 +16,7 @@ export function GroupSettingsPage() {
const { data: expansions } = useExpansions();
const { data: members } = useGroupMembers(groupId);
const setExpansions = useSetGroupExpansions(groupId ?? 0);
const addMember = useAddMember(groupId ?? 0);
const inviteMember = useInviteMember(groupId ?? 0);
const removeMember = useRemoveMember(groupId ?? 0);
const toast = useToast();
@@ -51,9 +51,9 @@ export function GroupSettingsPage() {
const nick = newNick.trim();
if (!nick) return;
try {
await addMember.mutateAsync(nick);
await inviteMember.mutateAsync(nick);
setNewNick("");
toast.show("Игрок добавлен");
toast.show("Приглашение отправлено");
} catch (e) {
toast.show(e instanceof ApiError ? e.message : "Ошибка");
}
@@ -102,8 +102,12 @@ export function GroupSettingsPage() {
)}
{isOwner && (members ?? []).length < MAX_GROUP_SIZE && (
<div className="row" style={{ marginBottom: 10 }}>
<input placeholder="Никнейм игрока" value={newNick} onChange={(e) => setNewNick(e.target.value)} />
<button className="btn btn-primary" onClick={add}>
<input
placeholder="Ник игрока — отправить приглашение"
value={newNick}
onChange={(e) => setNewNick(e.target.value)}
/>
<button className="btn btn-primary" onClick={add} disabled={inviteMember.isPending}>
<UserPlus size={18} />
</button>
</div>