fix: private chat creation and search in NewChatModal

- Fix: onOpen now async, MainLayout fetches fresh chats before opening
  (was using stale closure, chat wasn't found after creation)
- Fix: search null-safety in user list filter (displayName/username could be undefined)
- Fix: search also matches by phone number

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ai
2026-05-22 12:22:32 +03:00
parent 8e5c4cd67d
commit 5d3be2a628
2 changed files with 21 additions and 18 deletions

View File

@@ -1,12 +1,11 @@
import { useState, useEffect } from 'react';
import { X, Search, MessageCircle, Users, Radio } from 'lucide-react';
import api from '../api/client';
import { useStore } from '../store';
import Avatar from './Avatar';
interface Props {
onClose: () => void;
onOpen: (chatId: string) => void;
onOpen: (chatId: string) => Promise<void>;
}
type Step = 'type' | 'user' | 'group';
@@ -19,16 +18,18 @@ export default function NewChatModal({ onClose, onOpen }: Props) {
const [selected, setSelected] = useState<string[]>([]);
const [groupTitle, setGroupTitle] = useState('');
const [loading, setLoading] = useState(false);
const { setChats, chats } = useStore();
useEffect(() => {
api.get('/api/users').then(r => setUsers(r.data));
}, []);
const filtered = users.filter(u =>
u.displayName.toLowerCase().includes(search.toLowerCase()) ||
u.username.toLowerCase().includes(search.toLowerCase())
);
const filtered = !search.trim() ? users : users.filter(u => {
const q = search.toLowerCase();
return (u.displayName || '').toLowerCase().includes(q) ||
(u.username || '').toLowerCase().includes(q) ||
(u.phone || '').includes(q);
});
function toggleSelect(id: string) {
setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
@@ -38,12 +39,10 @@ export default function NewChatModal({ onClose, onOpen }: Props) {
setLoading(true);
try {
const { data } = await api.post(`/api/chats/private/${userId}`);
const { data: chat } = await api.get(`/api/chats/${data.id}`);
// Refresh chats
const { data: allChats } = await api.get('/api/chats');
setChats(allChats);
onOpen(data.id);
onClose();
await onOpen(data.id);
} catch (e: any) {
console.error('createPrivate error', e);
} finally {
setLoading(false);
}
@@ -58,10 +57,10 @@ export default function NewChatModal({ onClose, onOpen }: Props) {
title: groupTitle,
memberIds: selected,
});
const { data: allChats } = await api.get('/api/chats');
setChats(allChats);
onOpen(data.id);
onClose();
await onOpen(data.id);
} catch (e: any) {
console.error('createGroup error', e);
} finally {
setLoading(false);
}

View File

@@ -246,9 +246,13 @@ export default function MainLayout() {
</div>
{/* Modals */}
{showNew && <NewChatModal onClose={() => setShowNew(false)} onOpen={(id) => {
const chat = chats.find(c => c.id === id);
if (chat) openChat(chat);
{showNew && <NewChatModal onClose={() => setShowNew(false)} onOpen={async (id) => {
try {
const { data: allChats } = await api.get('/api/chats');
setChats(allChats);
const found = allChats.find((c: any) => c.id === id);
if (found) openChat(found);
} catch {}
}} />}
{showAdmin && <AdminPanel onClose={() => setShowAdmin(false)} />}
{showProfile && <ProfileModal onClose={() => setShowProfile(false)} />}