import { Component, createSignal, For, onMount, Show } from 'solid-js' import { query } from '../graphql' import type { Query, AdminUserInfo as User } from '../graphql/generated/schema' import { ADMIN_UPDATE_USER_MUTATION } from '../graphql/mutations' import { ADMIN_GET_USERS_QUERY } from '../graphql/queries' import UserEditModal from '../modals/RolesModal' import styles from '../styles/Admin.module.css' import Pagination from '../ui/Pagination' import { formatDateRelative } from '../utils/date' export interface AuthorsRouteProps { onError?: (error: string) => void onSuccess?: (message: string) => void } const AuthorsRoute: Component = (props) => { console.log('[AuthorsRoute] Initializing...') const [authors, setUsers] = createSignal([]) const [loading, setLoading] = createSignal(true) const [selectedUser, setSelectedUser] = createSignal(null) const [showEditModal, setShowEditModal] = createSignal(false) // Pagination state const [pagination, setPagination] = createSignal<{ page: number limit: number total: number totalPages: number }>({ page: 1, limit: 10, total: 0, totalPages: 1 }) // Search state const [searchQuery, setSearchQuery] = createSignal('') /** * Загрузка списка пользователей с учетом пагинации и поиска */ async function loadUsers() { console.log('[AuthorsRoute] Loading authors...') try { setLoading(true) const data = await query<{ adminGetUsers: Query['adminGetUsers'] }>( `${location.origin}/graphql`, ADMIN_GET_USERS_QUERY, { search: searchQuery(), limit: pagination().limit, offset: (pagination().page - 1) * pagination().limit } ) if (data?.adminGetUsers?.authors) { console.log('[AuthorsRoute] Users loaded:', data.adminGetUsers.authors.length) setUsers(data.adminGetUsers.authors) setPagination((prev) => ({ ...prev, total: data.adminGetUsers.total || 0, totalPages: data.adminGetUsers.totalPages || 1 })) } } catch (error) { console.error('[AuthorsRoute] Failed to load authors:', error) props.onError?.(error instanceof Error ? error.message : 'Failed to load authors') } finally { setLoading(false) } } /** * Обновляет данные пользователя (профиль и роли) */ async function updateUser(userData: { id: number email?: string name?: string slug?: string roles: string[] }) { try { await query(`${location.origin}/graphql`, ADMIN_UPDATE_USER_MUTATION, { user: userData }) setUsers((prev) => prev.map((user) => { if (user.id === userData.id) { return { ...user, email: userData.email || user.email, name: userData.name || user.name, slug: userData.slug || user.slug, roles: userData.roles } } return user }) ) closeEditModal() props.onSuccess?.('Данные пользователя успешно обновлены') void loadUsers() } catch (err) { console.error('Ошибка обновления пользователя:', err) let errorMessage = err instanceof Error ? err.message : 'Ошибка обновления данных пользователя' if (errorMessage.includes('author_role.community')) { errorMessage = 'Ошибка: для роли author требуется указать community. Обратитесь к администратору.' } props.onError?.(errorMessage) } } function closeEditModal() { setShowEditModal(false) setSelectedUser(null) } // Pagination handlers function handlePageChange(page: number) { setPagination((prev) => ({ ...prev, page })) void loadUsers() } function handlePerPageChange(limit: number) { setPagination((prev) => ({ ...prev, page: 1, limit })) void loadUsers() } // Search handlers function handleSearchChange(e: Event) { const input = e.target as HTMLInputElement setSearchQuery(input.value) } function handleSearch() { setPagination((prev) => ({ ...prev, page: 1 })) void loadUsers() } function handleSearchKeyDown(e: KeyboardEvent) { if (e.key === 'Enter') { e.preventDefault() handleSearch() } } // Load authors on mount onMount(() => { console.log('[AuthorsRoute] Component mounted, loading authors...') void loadUsers() }) /** * Компонент для отображения роли с иконкой */ const RoleBadge: Component<{ role: string }> = (props) => { const getRoleIcon = (role: string): string => { switch (role.toLowerCase()) { case 'admin': return '👑' case 'editor': return '✏️' case 'expert': return '🎓' case 'author': return '📝' case 'reader': return '👤' case 'banned': return '🚫' case 'verified': return '✓' default: return '👤' } } return ( {getRoleIcon(props.role)} {props.role} ) } return (
Загрузка данных...
Нет данных для отображения
0}>
{(user) => ( )}
ID Email Имя Создан Роли
{user.id} {user.email} {user.name || '-'} {formatDateRelative(user.created_at || Date.now())}
{(role) => }
{ setSelectedUser(user) setShowEditModal(true) }} > 🎭
) } export default AuthorsRoute