Files
glchat/web/src/pages/settings/GuildRolesSection.tsx
T

68 lines
2.6 KiB
TypeScript
Raw Normal View History

import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { fetchRoles, guildRolesQueryKey } from '@/api/guilds';
import { ErrorNotice } from '@/components/ui/ErrorNotice';
import { SkeletonLines } from '@/components/ui/Skeleton';
import { roleColorHex } from '@/lib/format';
import { SettingsSection } from '@/pages/settings/SettingsSection';
interface GuildRolesSectionProps {
guildId: string;
}
/** «Роли»: цвет и позиция. В Фазе 1 — только чтение. */
export function GuildRolesSection({ guildId }: GuildRolesSectionProps) {
const { t } = useTranslation();
const roles = useQuery({
queryKey: guildRolesQueryKey(guildId),
queryFn: ({ signal }) => fetchRoles(guildId, signal),
retry: 0,
});
const sorted = (roles.data ?? []).slice().sort((left, right) => right.position - left.position);
return (
<SettingsSection
title={t('settings.servers.roles.title')}
description={t('settings.servers.roles.description')}
>
{roles.isPending ? (
<SkeletonLines className="mt-4" rows={3} />
) : roles.isError ? (
<ErrorNotice className="mt-4" error={roles.error} onRetry={() => void roles.refetch()} />
) : sorted.length === 0 ? (
<p className="mt-4 text-sm text-fg-muted">{t('settings.servers.roles.empty')}</p>
) : (
<ul className="gl-stagger mt-4 flex flex-col gap-1" data-testid="guild-roles">
{sorted.map((role) => {
const color = roleColorHex(role.color);
return (
<li
key={role.id}
className="flex items-center gap-3 rounded-[var(--radius-md)] px-2 py-1.5 transition-colors duration-[var(--duration-fast)] hover:bg-surface-2"
>
<span
aria-hidden="true"
className="h-3.5 w-3.5 shrink-0 rounded-full border border-border/60"
style={color === null ? undefined : { backgroundColor: color }}
/>
<span className="min-w-0 flex-1 truncate text-sm">{role.name}</span>
{role.is_default ? (
<span className="text-xs text-fg-muted">
{t('settings.servers.roles.default')}
</span>
) : null}
<span className="text-xs text-fg-muted">
{t('settings.servers.roles.position', { position: role.position })}
</span>
</li>
);
})}
</ul>
)}
</SettingsSection>
);
}