From c4f75d5de095dda8ffc202a0e06165949678f85d Mon Sep 17 00:00:00 2001 From: NotBigGhost Date: Wed, 15 Jul 2026 17:19:07 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=8B:=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Новый хук useRenameGroup (PATCH /api/groups/{id} — эндпойнт уже был на бэкенде) с инвалидацией всех мест, где видно имя группы (шапка группы, переключатель групп, главная). В настройках — карточка «Название» с полем и кнопкой «Сохранить» (по образцу смены ника в аккаунте). Co-Authored-By: Claude Fable 5 --- frontend/src/hooks/groups.ts | 20 +++++++++++ frontend/src/pages/GroupSettingsPage.tsx | 45 +++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/frontend/src/hooks/groups.ts b/frontend/src/hooks/groups.ts index eeaa183..27a3132 100644 --- a/frontend/src/hooks/groups.ts +++ b/frontend/src/hooks/groups.ts @@ -75,6 +75,26 @@ export function useCreateGroup() { }); } +export function useRenameGroup(groupId: number) { + const qc = useQueryClient(); + return useMutation({ + mutationFn: async (name: string) => + unwrap( + await api.PATCH("/api/groups/{group_id}", { + params: { path: { group_id: groupId } }, + body: { name }, + }), + ), + onSuccess: () => { + // Имя группы видно в шапке группы, переключателе групп (me), на главной. + qc.invalidateQueries({ queryKey: qk.group(groupId) }); + qc.invalidateQueries({ queryKey: qk.groups }); + qc.invalidateQueries({ queryKey: qk.me }); + qc.invalidateQueries({ queryKey: qk.home }); + }, + }); +} + export function useSetGroupExpansions(groupId: number) { const qc = useQueryClient(); return useMutation({ diff --git a/frontend/src/pages/GroupSettingsPage.tsx b/frontend/src/pages/GroupSettingsPage.tsx index f4d7f67..2166844 100644 --- a/frontend/src/pages/GroupSettingsPage.tsx +++ b/frontend/src/pages/GroupSettingsPage.tsx @@ -9,7 +9,13 @@ 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, useSetGroupExpansions } from "../hooks/groups"; +import { + useGroup, + useGroupMembers, + useRemoveMember, + useRenameGroup, + useSetGroupExpansions, +} from "../hooks/groups"; import { useExpansions } from "../hooks/reference"; export function GroupSettingsPage() { @@ -19,10 +25,13 @@ export function GroupSettingsPage() { 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(() => { @@ -40,6 +49,20 @@ export function GroupSettingsPage() { 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]); @@ -59,6 +82,26 @@ export function GroupSettingsPage() { return (
+
+

Название

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

Дополнения