import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { fetchRoles, guildRolesQueryKey, updateRole } from '@/api/guilds';
import {
NICK_EFFECTS,
fetchGuildCosmetics,
guildCosmeticsQueryKey,
type GuildCosmetic,
type NickEffect,
} from '@/api/cosmetics';
import { ErrorNotice } from '@/components/ui/ErrorNotice';
import { SkeletonLines } from '@/components/ui/Skeleton';
import { NICK_COLOR_PALETTE } from '@/components/profile/cosmeticsStyle';
import { roleColorHex } from '@/lib/format';
import { SettingsSection } from '@/pages/settings/SettingsSection';
import type { Role } from '@/api/types';
interface GuildRolesSectionProps {
guildId: string;
/** Право MANAGE_ROLES: без него оформление роли показывается только для чтения. */
canManage?: boolean;
}
/**
* «Роли»: список ролей и — при праве MANAGE_ROLES — оформление роли
* (AGENT.md 7.4): рамка, иконка, цвет и эффект ника. Рамки и иконки берутся из
* галереи сервера, поэтому она читается тем же разделом.
*/
export function GuildRolesSection({ guildId, canManage = false }: GuildRolesSectionProps) {
const { t } = useTranslation();
const queryClient = useQueryClient();
const roles = useQuery({
queryKey: guildRolesQueryKey(guildId),
queryFn: ({ signal }) => fetchRoles(guildId, signal),
retry: 0,
});
const cosmetics = useQuery({
queryKey: guildCosmeticsQueryKey(guildId),
queryFn: ({ signal }) => fetchGuildCosmetics(guildId, signal),
retry: 0,
});
const patch = useMutation({
mutationFn: (input: { roleId: string; body: RoleDecorationInput }) =>
updateRole(guildId, input.roleId, input.body),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: guildRolesQueryKey(guildId) });
// Оформление участников в ленте пересчитывается из списка участников.
void queryClient.invalidateQueries({ queryKey: ['guilds', guildId, 'members'] });
},
});
const sorted = (roles.data ?? []).slice().sort((left, right) => right.position - left.position);
const frames = (cosmetics.data ?? []).filter((item) => item.kind === 'frame');
const badges = (cosmetics.data ?? []).filter((item) => item.kind === 'badge');
return (
{t('settings.servers.roles.empty')}
{t('settings.servers.roles.decorationSaved')}
{sorted.map((role) => {
const color = roleColorHex(role.color);
return (
)}
{patch.isError ?