Группы: добавление (приглашение) со страницы чужого профиля

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 20:09:19 +03:00
co-authored by Claude Opus 4.8
parent a5c54512a5
commit 366742d6da
3 changed files with 68 additions and 5 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ export function GroupSettingsPage() {
const { data: expansions } = useExpansions();
const { data: members } = useGroupMembers(groupId);
const setExpansions = useSetGroupExpansions(groupId ?? 0);
const inviteMember = useInviteMember(groupId ?? 0);
const inviteMember = useInviteMember();
const removeMember = useRemoveMember(groupId ?? 0);
const toast = useToast();
@@ -51,7 +51,7 @@ export function GroupSettingsPage() {
const nick = newNick.trim();
if (!nick) return;
try {
await inviteMember.mutateAsync(nick);
await inviteMember.mutateAsync({ groupId: group.id, nickname: nick });
setNewNick("");
toast.show("Приглашение отправлено");
} catch (e) {
+62
View File
@@ -1,8 +1,13 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { ApiError } from "../api/client";
import { Avatar } from "../components/Avatar";
import { ProfileStatsCard } from "../components/ProfileStatsCard";
import { Spinner } from "../components/Spinner";
import { useToast } from "../context/ToastContext";
import { useMe } from "../hooks/auth";
import { useInviteMember } from "../hooks/groups";
import { usePublicProfile } from "../hooks/stats";
/**
@@ -13,10 +18,27 @@ export function PublicProfilePage() {
const { userId } = useParams();
const id = Number(userId);
const { data, isLoading, isError } = usePublicProfile(id);
const { data: me } = useMe();
const invite = useInviteMember();
const toast = useToast();
const [pickOpen, setPickOpen] = useState(false);
if (isLoading) return <Spinner />;
if (isError || !data) return <div className="muted">Профиль не найден.</div>;
const groups = me?.groups ?? [];
const isSelf = me?.id === data.user_id;
const doInvite = async (groupId: number) => {
setPickOpen(false);
try {
await invite.mutateAsync({ groupId, nickname: data.nickname });
toast.show("Приглашение отправлено");
} catch (e) {
toast.show(e instanceof ApiError ? e.message : "Не удалось пригласить");
}
};
return (
<div>
<div className="card">
@@ -37,6 +59,46 @@ export function PublicProfilePage() {
</div>
</div>
{/* Пригласить в группу (только чужой профиль и если у меня есть группы). */}
{!isSelf && groups.length > 0 && (
<div className="card">
{groups.length === 1 ? (
<button
className="btn btn-primary"
style={{ width: "100%" }}
onClick={() => doInvite(groups[0].id)}
disabled={invite.isPending}
>
Добавить в группу «{groups[0].name}»
</button>
) : (
<>
<button
className="btn btn-primary"
style={{ width: "100%" }}
onClick={() => setPickOpen((v) => !v)}
>
Добавить в группу
</button>
{pickOpen && (
<div className="stack" style={{ marginTop: 8 }}>
{groups.map((g) => (
<button
key={g.id}
className="btn"
onClick={() => doInvite(g.id)}
disabled={invite.isPending}
>
{g.name}
</button>
))}
</div>
)}
</>
)}
</div>
)}
<ProfileStatsCard stats={data.stats} title="Статистика" />
</div>
);