/** * ContactsPanel — extracted from AIChatPanel.renderContactsPanel() * Displays a list of contacts with search, favorites, and type filtering. */ import React from 'react'; import { X, Search, Star, Loader2 } from 'lucide-react'; import { cn } from '@/shared/utils/cn'; import { AccordionContactItem } from '../components/AccordionContactItem'; type PanelTab = 'none' | 'contacts' | 'ai-agents' | 'tasks' | 'settings' | 'inbox'; interface ContactUser { id: number; name: string; email?: string | null; avatar_url?: string | null; managed_by_agent_table_id?: number | null; } interface ChatParticipant { id: number; name: string; type: 'user' | 'agent'; email?: string; avatar?: string; } interface ChatPartner { type: string; id: number; name: string; avatarUrl?: string; email?: string; icon?: string | null; participants?: Array<{ id: number; name: string; type: 'user' | 'agent' }>; } export interface ContactsPanelProps { showFavorites: boolean; setShowFavorites: React.Dispatch>; userTypeFilter: 'all' | 'humans' | 'agents'; setUserTypeFilter: (value: 'all' | 'humans' | 'agents') => void; showAllContacts: boolean; setShowAllContacts: React.Dispatch>; setActivePanel: (panel: PanelTab) => void; contactsSearch: string; setContactsSearch: (value: string) => void; isLoadingUsers: boolean; filteredUsers: ContactUser[]; chatParticipants: ChatParticipant[]; chatPartner: ChatPartner | null; favorites: number[]; handleUserSelect: (user: ContactUser) => void; selectConversation: (id: number) => void; toggleFavorite: (userId: number) => void; handleAddToGroup: (user: ContactUser) => void; forceNewChatRef: React.MutableRefObject; createNewConversation: () => void; setUserConversationId: (id: number | null) => void; setChatPartner: (partner: ChatPartner | null) => void; setChatParticipants: (participants: ChatParticipant[]) => void; } export function ContactsPanel({ showFavorites, setShowFavorites, userTypeFilter, setUserTypeFilter, showAllContacts, setShowAllContacts, setActivePanel, contactsSearch, setContactsSearch, isLoadingUsers, filteredUsers, chatParticipants, chatPartner, favorites, handleUserSelect, selectConversation, toggleFavorite, handleAddToGroup, forceNewChatRef, createNewConversation, setUserConversationId, setChatPartner, setChatParticipants, }: ContactsPanelProps) { return (
{/* Header with close button */}
{/* Favorites toggle */} {/* Type filter */} {/* Show all users toggle */}
{/* Close panel - fixed right */}
{/* Search - shown in wide mode sidebar */}
setContactsSearch(e.target.value)} placeholder="Поиск контактов..." className="w-full pl-8 pr-3 py-1.5 text-sm rounded-lg bg-[var(--bg-tertiary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] border-none focus:outline-none focus:ring-2 focus:ring-[var(--color-primary-500)]/30" />
{/* Content */}
{isLoadingUsers ? (
) : filteredUsers.length === 0 ? (
{contactsSearch ? 'Не найдено' : 'Нет контактов'}
) : ( filteredUsers.map(user => { const isInChat = chatParticipants.some(p => p.id === user.id); const isCurrent = chatPartner?.type === 'user' && chatPartner.id === user.id; const isFavorite = favorites.includes(user.id); return ( { selectConversation(chatId); setActivePanel('none'); }} onToggleFavorite={toggleFavorite} onAddToGroup={handleAddToGroup} onCreateNewChat={(targetUser) => { // Force creation of a new conversation (skip "find existing" logic) forceNewChatRef.current = true; createNewConversation(); setUserConversationId(null); setChatPartner({ type: 'user', id: targetUser.id, name: targetUser.name, avatarUrl: targetUser.avatar_url ?? undefined, email: targetUser.email ?? undefined }); setChatParticipants([{ type: targetUser.managed_by_agent_table_id ? 'agent' : 'user', id: targetUser.id, name: targetUser.name, email: targetUser.email ?? undefined, avatar: targetUser.avatar_url ?? undefined }]); setActivePanel('none'); }} /> ); }) )}
); }