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(); + }} + /> + +
+
+

Дополнения