import { Trash2, UserPlus } 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, useInviteMember, useRemoveMember, 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 inviteMember = useInviteMember(); const removeMember = useRemoveMember(groupId ?? 0); const toast = useToast(); const [selected, setSelected] = useState>(new Set()); const [newNick, setNewNick] = useState(""); 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 saveExpansions = async () => { try { await setExpansions.mutateAsync([...selected]); toast.show("Дополнения сохранены"); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; const add = async () => { const nick = newNick.trim(); if (!nick) return; try { await inviteMember.mutateAsync({ groupId: group.id, nickname: nick }); setNewNick(""); 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 (

Дополнения

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

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

{isOwner && (members ?? []).length >= MAX_GROUP_SIZE && (

Достигнут максимум участников ({MAX_GROUP_SIZE}).

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