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:
@@ -1,12 +1,11 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { X, Search, MessageCircle, Users, Radio } from 'lucide-react';
|
import { X, Search, MessageCircle, Users, Radio } from 'lucide-react';
|
||||||
import api from '../api/client';
|
import api from '../api/client';
|
||||||
import { useStore } from '../store';
|
|
||||||
import Avatar from './Avatar';
|
import Avatar from './Avatar';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onOpen: (chatId: string) => void;
|
onOpen: (chatId: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Step = 'type' | 'user' | 'group';
|
type Step = 'type' | 'user' | 'group';
|
||||||
@@ -19,16 +18,18 @@ export default function NewChatModal({ onClose, onOpen }: Props) {
|
|||||||
const [selected, setSelected] = useState<string[]>([]);
|
const [selected, setSelected] = useState<string[]>([]);
|
||||||
const [groupTitle, setGroupTitle] = useState('');
|
const [groupTitle, setGroupTitle] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { setChats, chats } = useStore();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.get('/api/users').then(r => setUsers(r.data));
|
api.get('/api/users').then(r => setUsers(r.data));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const filtered = users.filter(u =>
|
const filtered = !search.trim() ? users : users.filter(u => {
|
||||||
u.displayName.toLowerCase().includes(search.toLowerCase()) ||
|
const q = search.toLowerCase();
|
||||||
u.username.toLowerCase().includes(search.toLowerCase())
|
return (u.displayName || '').toLowerCase().includes(q) ||
|
||||||
);
|
(u.username || '').toLowerCase().includes(q) ||
|
||||||
|
(u.phone || '').includes(q);
|
||||||
|
});
|
||||||
|
|
||||||
function toggleSelect(id: string) {
|
function toggleSelect(id: string) {
|
||||||
setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
|
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);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data } = await api.post(`/api/chats/private/${userId}`);
|
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();
|
onClose();
|
||||||
|
await onOpen(data.id);
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error('createPrivate error', e);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -58,10 +57,10 @@ export default function NewChatModal({ onClose, onOpen }: Props) {
|
|||||||
title: groupTitle,
|
title: groupTitle,
|
||||||
memberIds: selected,
|
memberIds: selected,
|
||||||
});
|
});
|
||||||
const { data: allChats } = await api.get('/api/chats');
|
|
||||||
setChats(allChats);
|
|
||||||
onOpen(data.id);
|
|
||||||
onClose();
|
onClose();
|
||||||
|
await onOpen(data.id);
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error('createGroup error', e);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,9 +246,13 @@ export default function MainLayout() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Modals */}
|
{/* Modals */}
|
||||||
{showNew && <NewChatModal onClose={() => setShowNew(false)} onOpen={(id) => {
|
{showNew && <NewChatModal onClose={() => setShowNew(false)} onOpen={async (id) => {
|
||||||
const chat = chats.find(c => c.id === id);
|
try {
|
||||||
if (chat) openChat(chat);
|
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)} />}
|
{showAdmin && <AdminPanel onClose={() => setShowAdmin(false)} />}
|
||||||
{showProfile && <ProfileModal onClose={() => setShowProfile(false)} />}
|
{showProfile && <ProfileModal onClose={() => setShowProfile(false)} />}
|
||||||
|
|||||||
Reference in New Issue
Block a user