import { Trash2 } from "lucide-react"; import { useEffect, useState } from "react"; import { ApiError } from "../api/client"; import { ConfirmDialog } from "../components/ConfirmDialog"; import { PlayerLink } from "../components/PlayerLink"; import { Spinner } from "../components/Spinner"; import { Switch } from "../components/Switch"; import { MAX_GROUP_SIZE } from "../domain/constants"; import { useToast } from "../context/ToastContext"; import { useMe } from "../hooks/auth"; import { useGroup, useGroupMembers, useRemoveMember, useRenameGroup, useSetGroupExpansions, } from "../hooks/groups"; import { useExpansions } from "../hooks/reference"; export function GroupSettingsPage() { const { data: me } = useMe(); const groupId = me?.active_group_id ?? null; const { data: group, isLoading } = useGroup(groupId); const { data: expansions } = useExpansions(); const { data: members } = useGroupMembers(groupId); const setExpansions = useSetGroupExpansions(groupId ?? 0); const renameGroup = useRenameGroup(groupId ?? 0); const removeMember = useRemoveMember(groupId ?? 0); const toast = useToast(); const [selected, setSelected] = useState>(new Set()); // Название редактируется локально; до первого ввода берём значение из группы. const [name, setName] = useState(null); const [removeTarget, setRemoveTarget] = useState<{ userId: number; nickname: string } | null>(null); useEffect(() => { if (group) setSelected(new Set(group.expansion_ids)); }, [group]); if (isLoading || !group) return ; // Управление группой доступно всем участникам (создатель лишь создаёт и приглашает). const isOwner = true; const toggle = (id: number) => setSelected((s) => { const next = new Set(s); next.has(id) ? next.delete(id) : next.add(id); return next; }); const nameValue = name ?? group.name; const saveName = async () => { const trimmed = nameValue.trim(); if (!trimmed || trimmed === group.name) return; try { await renameGroup.mutateAsync(trimmed); setName(null); toast.show("Название сохранено"); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; const saveExpansions = async () => { try { await setExpansions.mutateAsync([...selected]); toast.show("Дополнения сохранены"); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; const remove = async (userId: number) => { try { await removeMember.mutateAsync(userId); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; return (

Название

setName(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") saveName(); }} />

Дополнения

{/* Базовые дополнения показываем, как и при создании группы: включены и заблокированы. */} {(expansions ?? []).map((e) => ( ))}
{isOwner && ( )}
{/* Приглашение нового игрока — на странице группы («Список игроков»). */}

Участники ({(members ?? []).length}/{MAX_GROUP_SIZE})

{(members ?? []).map((m) => (
{/* Кликабельна вся левая часть строки, не только текст ника. */} {m.nickname}{" "} · {m.role === "owner" ? "владелец" : "участник"} {isOwner && m.role !== "owner" && ( )}
))}
setRemoveTarget(null)} onConfirm={() => { if (!removeTarget) return; const userId = removeTarget.userId; setRemoveTarget(null); remove(userId); }} />
); }