import { createSignal, For, onMount, Show } from 'solid-js' import { useData } from '../context/data' import { CREATE_CUSTOM_ROLE_MUTATION, DELETE_CUSTOM_ROLE_MUTATION, GET_COMMUNITY_ROLES_QUERY } from '../graphql/queries' import formStyles from '../styles/Form.module.css' import styles from '../styles/RoleManager.module.css' interface Role { id: string name: string description: string icon: string } interface RoleSettings { default_roles: string[] available_roles: string[] } interface RoleManagerProps { communityId?: number roleSettings: RoleSettings onRoleSettingsChange: (settings: RoleSettings) => void customRoles: Role[] onCustomRolesChange: (roles: Role[]) => void } const STANDARD_ROLES = [ { id: 'reader', name: 'Читатель', description: 'Может читать и комментировать', icon: '👁️' }, { id: 'author', name: 'Автор', description: 'Может создавать публикации', icon: '✍️' }, { id: 'artist', name: 'Художник', description: 'Может быть credited artist', icon: '🎨' }, { id: 'expert', name: 'Эксперт', description: 'Может добавлять доказательства', icon: '🧠' }, { id: 'editor', name: 'Редактор', description: 'Может модерировать контент', icon: '📝' }, { id: 'admin', name: 'Администратор', description: 'Полные права', icon: '👑' } ] const RoleManager = (props: RoleManagerProps) => { const { queryGraphQL } = useData() const [showAddRole, setShowAddRole] = createSignal(false) const [newRole, setNewRole] = createSignal({ id: '', name: '', description: '', icon: '🔖' }) const [errors, setErrors] = createSignal>({}) // Загружаем роли при монтировании компонента onMount(async () => { if (props.communityId) { try { const rolesData = await queryGraphQL(GET_COMMUNITY_ROLES_QUERY, { community: props.communityId }) if (rolesData?.adminGetRoles) { const standardRoleIds = STANDARD_ROLES.map((r) => r.id) const customRolesList = rolesData.adminGetRoles .filter((role: Role) => !standardRoleIds.includes(role.id)) .map((role: Role) => ({ id: role.id, name: role.name, description: role.description || '', icon: '🔖' })) props.onCustomRolesChange(customRolesList) } } catch (error) { console.error('Ошибка загрузки ролей:', error) } } }) const getAllRoles = () => [...STANDARD_ROLES, ...props.customRoles] const isRoleDisabled = (roleId: string) => roleId === 'admin' const validateNewRole = (): boolean => { const role = newRole() const newErrors: Record = {} if (!role.id.trim()) { newErrors.newRoleId = 'ID роли обязательно' } else if (!/^[a-z0-9_-]+$/.test(role.id)) { newErrors.newRoleId = 'ID может содержать только латинские буквы, цифры, дефисы и подчеркивания' } else if (getAllRoles().some((r) => r.id === role.id)) { newErrors.newRoleId = 'Роль с таким ID уже существует' } if (!role.name.trim()) { newErrors.newRoleName = 'Название роли обязательно' } setErrors(newErrors) return Object.keys(newErrors).length === 0 } const addCustomRole = async () => { if (!validateNewRole()) return const role = newRole() if (props.communityId) { try { const result = await queryGraphQL(CREATE_CUSTOM_ROLE_MUTATION, { role: { id: role.id, name: role.name, description: role.description, icon: role.icon, community_id: props.communityId } }) if (result?.adminCreateCustomRole?.success) { props.onCustomRolesChange([...props.customRoles, role]) props.onRoleSettingsChange({ ...props.roleSettings, available_roles: [...props.roleSettings.available_roles, role.id] }) resetNewRoleForm() } else { setErrors({ newRoleId: result?.adminCreateCustomRole?.error || 'Ошибка создания роли' }) } } catch (error) { console.error('Ошибка создания роли:', error) setErrors({ newRoleId: 'Ошибка создания роли' }) } } else { props.onCustomRolesChange([...props.customRoles, role]) props.onRoleSettingsChange({ ...props.roleSettings, available_roles: [...props.roleSettings.available_roles, role.id] }) resetNewRoleForm() } } const removeCustomRole = async (roleId: string) => { if (props.communityId) { try { const result = await queryGraphQL(DELETE_CUSTOM_ROLE_MUTATION, { role_id: roleId, community_id: props.communityId }) if (result?.adminDeleteCustomRole?.success) { updateRolesAfterRemoval(roleId) } else { console.error('Ошибка удаления роли:', result?.adminDeleteCustomRole?.error) } } catch (error) { console.error('Ошибка удаления роли:', error) } } else { updateRolesAfterRemoval(roleId) } } const updateRolesAfterRemoval = (roleId: string) => { props.onCustomRolesChange(props.customRoles.filter((r) => r.id !== roleId)) props.onRoleSettingsChange({ available_roles: props.roleSettings.available_roles.filter((r) => r !== roleId), default_roles: props.roleSettings.default_roles.filter((r) => r !== roleId) }) } const resetNewRoleForm = () => { setNewRole({ id: '', name: '', description: '', icon: '🔖' }) setShowAddRole(false) setErrors({}) } const toggleAvailableRole = (roleId: string) => { if (isRoleDisabled(roleId)) return const current = props.roleSettings const newAvailable = current.available_roles.includes(roleId) ? current.available_roles.filter((r) => r !== roleId) : [...current.available_roles, roleId] const newDefault = newAvailable.includes(roleId) ? current.default_roles : current.default_roles.filter((r) => r !== roleId) props.onRoleSettingsChange({ available_roles: newAvailable, default_roles: newDefault }) } const toggleDefaultRole = (roleId: string) => { if (isRoleDisabled(roleId)) return const current = props.roleSettings const newDefault = current.default_roles.includes(roleId) ? current.default_roles.filter((r) => r !== roleId) : [...current.default_roles, roleId] props.onRoleSettingsChange({ ...current, default_roles: newDefault }) } return (
{/* Доступные роли */}

🎭 Доступные роли в сообществе

Выберите роли, которые могут быть назначены в этом сообществе

{(role) => (
!isRoleDisabled(role.id) && toggleAvailableRole(role.id)} >
{role.icon}
r.id === role.id)}>
toggleAvailableRole(role.id)} />
{role.name}
{role.description}
Системная роль
)}
{/* Форма добавления новой роли */} setShowAddRole(true)}> Добавить роль } >

Добавить новую роль

setNewRole((prev) => ({ ...prev, id: e.currentTarget.value }))} placeholder="my_custom_role" /> ⚠️ {errors().newRoleId}
setNewRole((prev) => ({ ...prev, name: e.currentTarget.value }))} placeholder="Моя роль" /> ⚠️ {errors().newRoleName}
setNewRole((prev) => ({ ...prev, description: e.currentTarget.value }))} placeholder="Описание роли" />
setNewRole((prev) => ({ ...prev, icon: e.currentTarget.value }))} placeholder="🔖" />
{/* Дефолтные роли */}

Дефолтные роли для новых пользователей *

Роли, которые автоматически назначаются при вступлении в сообщество

props.roleSettings.available_roles.includes(role.id))}> {(role) => (
!isRoleDisabled(role.id) && toggleDefaultRole(role.id)} >
{role.icon}
toggleDefaultRole(role.id)} />
{role.name}
Системная роль
)}
) } export default RoleManager