// ChatModal.jsx — شات كتابى بين العميل والمحامي // يفتح من كارت المحامي بدل/جنب زرار الاتصال. function _chatFmtTime(iso) { if (!iso) return ''; try { const d = new Date(iso); const now = new Date(); const diffMs = now - d; const diffMin = Math.floor(diffMs / 60000); if (diffMin < 1) return 'الآن'; if (diffMin < 60) return `منذ ${diffMin} د`; if (diffMin < 24 * 60) return d.toLocaleTimeString('ar-SA', { hour: '2-digit', minute: '2-digit' }); return d.toLocaleString('ar-SA', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }); } catch { return ''; } } function _chatFmtSize(bytes) { if (!bytes) return ''; if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } const CHAT_MIME_ICON = (mime) => { if (!mime) return '📎'; if (mime.startsWith('image/')) return '🖼️'; if (mime === 'application/pdf') return '📄'; if (mime.includes('word')) return '📝'; if (mime === 'text/plain') return '📃'; return '📎'; }; function ChatModal({ lawyer, onClose }) { const [chatId, setChatId] = React.useState(null); const [messages, setMessages] = React.useState([]); const [input, setInput] = React.useState(''); const [loading, setLoading] = React.useState(true); const [sending, setSending] = React.useState(false); const [uploading, setUploading] = React.useState(false); const [error, setError] = React.useState(null); const scrollRef = React.useRef(null); const fileRef = React.useRef(null); const inputRef = React.useRef(null); const apiBase = window.api?.baseUrl || 'http://localhost:8000'; // start or get chat with this lawyer React.useEffect(() => { let cancel = false; (async () => { try { if (!window.api?.isAuthenticated()) { setError('سجّل دخولك أولاً لبدء المحادثة'); setLoading(false); return; } const c = await window.api.chats.start(lawyer.id); if (cancel) return; setChatId(c.id); window.__openChatId = c.id; // عشان الـ notifier ميطلعش toast على شات مفتوح const detail = await window.api.chats.get(c.id); if (cancel) return; setMessages(detail.messages || []); setLoading(false); setTimeout(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; inputRef.current?.focus(); }, 50); } catch (e) { if (!cancel) { setError(e.message || 'فشل فتح المحادثة'); setLoading(false); } } })(); return () => { cancel = true; window.__openChatId = null; }; }, [lawyer.id]); // poll every 4s for new messages React.useEffect(() => { if (!chatId) return; const t = setInterval(async () => { try { const detail = await window.api.chats.get(chatId); setMessages(detail.messages || []); } catch { /* silent */ } }, 4000); return () => clearInterval(t); }, [chatId]); // auto-scroll on new messages React.useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [messages.length]); // ESC to close React.useEffect(() => { const h = (e) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', h); return () => window.removeEventListener('keydown', h); }, [onClose]); const handleSend = async () => { const text = input.trim(); if (!text || !chatId || sending) return; setSending(true); try { const msg = await window.api.chats.sendMessage(chatId, text); setMessages(prev => [...prev, msg]); setInput(''); } catch (e) { alert(e.message); } finally { setSending(false); inputRef.current?.focus(); } }; const handleFile = async (file) => { if (!file || !chatId) return; setUploading(true); try { const msg = await window.api.chats.sendFile(chatId, file); setMessages(prev => [...prev, msg]); } catch (e) { alert(e.message); } finally { setUploading(false); if (fileRef.current) fileRef.current.value = ''; } }; const currentUserId = window.__sanadCurrentUser?.id; return (