'use client'; import React from 'react'; import { Box, TextField, List, ListItemButton, ListItemText, Badge, Avatar, Button, IconButton } from '@mui/material'; import NotificationsActiveRoundedIcon from '@mui/icons-material/NotificationsActiveRounded'; import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded'; import AssignmentRoundedIcon from '@mui/icons-material/AssignmentRounded'; import AddCommentRoundedIcon from '@mui/icons-material/AddCommentRounded'; import type { Chat } from '@/api/chat'; import { NewChatModal } from './NewChatModal'; interface ChatListProps { chats: Chat[]; selectedChatUuid: string | null; onSelect: (chat: Chat) => void; hasMore?: boolean; loadingMore?: boolean; onLoadMore?: () => void; } function parsePreview(text: string) { const t = (text || '').trim(); if (!t) return { icons: [] as Array<'bell' | 'trash' | 'note'>, text: '—' }; const icons: Array<'bell' | 'trash' | 'note'> = []; let rest = t; // выкусываем частые эмодзи-пиктограммы из system сообщений const take = (emoji: string, key: 'bell' | 'trash' | 'note') => { if (rest.includes(emoji)) { icons.push(key); rest = rest.replace(emoji, '').trim(); } }; take('🔔', 'bell'); take('🗑️', 'trash'); take('🗑', 'trash'); take('📝', 'note'); // убираем лишние эмодзи/разделители в начале rest = rest.replace(/^[-–—•\s]+/, '').trim(); return { icons, text: rest || '—' }; } export function ChatList({ chats, selectedChatUuid, onSelect, hasMore, loadingMore, onLoadMore }: ChatListProps) { const [q, setQ] = React.useState(''); const [isNewChatModalOpen, setIsNewChatModalOpen] = React.useState(false); const filtered = React.useMemo(() => { const qq = q.trim().toLowerCase(); if (!qq) return chats; return chats.filter((c) => { const name = (c.participant_name || '').toLowerCase(); const last = (c.last_message || '').toLowerCase(); return name.includes(qq) || last.includes(qq); }); }, [chats, q]); return ( setQ(e.target.value)} placeholder="Поиск" size="small" fullWidth sx={{ '& .MuiInputBase-root': { borderRadius: 3, backgroundColor: 'rgba(255,255,255,0.7)', }, }} /> setIsNewChatModalOpen(true)} sx={{ bgcolor: 'var(--md-sys-color-primary)', color: 'var(--md-sys-color-on-primary)', '&:hover': { bgcolor: 'var(--md-sys-color-primary)', filter: 'brightness(0.9)' } }} > {filtered.map((chat) => { const selected = !!selectedChatUuid && chat.uuid === selectedChatUuid; const preview = parsePreview(chat.last_message || ''); return ( onSelect(chat)} sx={{ borderRadius: 2, mb: 0.5, minWidth: 0, '&.Mui-selected': { backgroundColor: 'rgba(116, 68, 253, 0.12)', }, }} > {(chat.participant_name || 'Ч') .trim() .split(/\s+/) .slice(0, 2) .map((p) => p[0]) .join('') .toUpperCase()} {!!(chat as any).other_is_online && ( )} {chat.participant_name || 'Чат'} {!!chat.unread_count && chat.unread_count > 0 && ( )} } secondary={ {preview.icons.includes('bell') && ( )} {preview.icons.includes('trash') && ( )} {preview.icons.includes('note') && ( )} {preview.text} } sx={{ minWidth: 0 }} primaryTypographyProps={{ component: 'span' }} secondaryTypographyProps={{ component: 'span' }} /> ); })} {hasMore && onLoadMore && ( )} setIsNewChatModalOpen(false)} onChatCreated={(chat) => { onSelect(chat); // Можно добавить уведомление }} /> ); }