'use client' import { useQuery, gql } from '@apollo/client' import { Search, Phone, Building, Calendar, ChevronLeft, ChevronRight, Loader2 } from 'lucide-react' import React, { useState, useEffect, useMemo, useCallback } from 'react' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Card, CardContent } from '@/components/ui/card' import { Input } from '@/components/ui/input' // GraphQL запрос для получения пользователей const ALL_USERS = gql` query AllUsers($search: String, $limit: Int, $offset: Int) { allUsers(search: $search, limit: $limit, offset: $offset) { users { id phone managerName avatar createdAt updatedAt organization { id inn name fullName type status createdAt } } total hasMore } } ` interface User { id: string phone: string managerName?: string avatar?: string createdAt: string updatedAt: string organization?: { id: string inn: string name?: string fullName?: string type: string status?: string createdAt: string } } const UsersSection = React.memo(() => { const [search, setSearch] = useState('') const [currentPage, setCurrentPage] = useState(1) const [searchQuery, setSearchQuery] = useState('') const limit = 20 const { data, loading, error, refetch } = useQuery(ALL_USERS, { variables: { search: searchQuery || undefined, limit, offset: (currentPage - 1) * limit, }, fetchPolicy: 'cache-and-network', }) // Обновляем запрос при изменении поиска с дебаунсом useEffect(() => { const timer = setTimeout(() => { setSearchQuery(search) setCurrentPage(1) // Сбрасываем на первую страницу при поиске }, 500) return () => clearTimeout(timer) }, [search]) const users = useMemo(() => data?.allUsers?.users || [], [data?.allUsers?.users]) const total = useMemo(() => data?.allUsers?.total || 0, [data?.allUsers?.total]) const _hasMore = useMemo(() => data?.allUsers?.hasMore || false, [data?.allUsers?.hasMore]) const totalPages = useMemo(() => Math.ceil(total / limit), [total, limit]) const getOrganizationTypeBadge = useCallback((type: string) => { const typeMap = { FULFILLMENT: { label: 'Фулфилмент', variant: 'default' as const }, SELLER: { label: 'Селлер', variant: 'secondary' as const }, LOGIST: { label: 'Логистика', variant: 'outline' as const }, WHOLESALE: { label: 'Поставщик', variant: 'destructive' as const }, } return typeMap[type as keyof typeof typeMap] || { label: type, variant: 'outline' as const } }, []) const formatDate = useCallback((dateString: string) => { try { const date = new Date(dateString) if (isNaN(date.getTime())) { return 'Неизвестно' } return date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }) } catch { return 'Неизвестно' } }, []) const getInitials = useCallback((name?: string, phone?: string) => { if (name) { return name .split(' ') .map((n) => n[0]) .join('') .toUpperCase() .slice(0, 2) } if (phone) { return phone.slice(-2) } return 'У' }, []) const handlePrevPage = useCallback(() => { if (currentPage > 1) { setCurrentPage(currentPage - 1) } }, [currentPage]) const handleNextPage = useCallback(() => { if (currentPage < totalPages) { setCurrentPage(currentPage + 1) } }, [currentPage, totalPages]) const handleSearchChange = useCallback((value: string) => { setSearch(value) }, []) if (error) { return (

Ошибка загрузки пользователей: {error.message}

) } return (

Пользователи

Управление пользователями системы

{/* Поиск и статистика */}
handleSearchChange(e.target.value)} className="pl-10 glass-input text-white placeholder:text-white/50" />
Всего: {total} {searchQuery && Найдено: {users.length}}
{/* Список пользователей */} {loading ? (

Загрузка пользователей...

) : users.length === 0 ? (

{searchQuery ? 'Пользователи не найдены' : 'Пользователи отсутствуют'}

) : (
{users.map((user: User) => (
{/* Аватар */} {getInitials(user.managerName, user.phone)} {/* Основная информация */}

{user.managerName || 'Без имени'}

{user.phone}
{formatDate(user.createdAt)}
{/* Организация */} {user.organization && (
{user.organization.name || user.organization.fullName || 'Без названия'} {getOrganizationTypeBadge(user.organization.type).label}

ИНН: {user.organization.inn}

{user.organization.status && (

Статус: {user.organization.status}

)}

Зарегистрировано: {formatDate(user.organization.createdAt)}

)}
))}
)} {/* Пагинация */} {totalPages > 1 && (
Страница {currentPage} из {totalPages}
)}
) }) UsersSection.displayName = 'UsersSection' export { UsersSection }