Manara / src /components /SmartResearcher.tsx
Kebe77's picture
Create src/components/SmartResearcher.tsx
2feeffd verified
Raw
History Blame Contribute Delete
6.15 kB
import React, { useState, useRef, useEffect } from 'react';
import { Send, Sparkles, User, Bot, BookOpen, Quote, RefreshCw } from 'lucide-react';
export const SmartResearcher = ({ allSources, onPromoteToProject, t }) => {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [isLoading, setIsLoading] = useState(false);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
const handleSend = async () => {
if (!input.trim() || isLoading) return;
const userMessage = {
role: 'user',
content: input,
timestamp: Date.now()
};
setMessages(prev => [...prev, userMessage]);
setInput('');
setIsLoading(true);
try {
// هنا سيتم الاتصال بـ API الخاص بـ Gemini
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: input,
history: messages
}),
});
const data = await response.json();
const assistantMessage = {
role: 'assistant',
content: data.text || "عذراً، واجهت مشكلة في الاتصال بالخادم العرفاني.",
citations: data.citations || [],
timestamp: Date.now()
};
setMessages(prev => [...prev, assistantMessage]);
} catch (error) {
console.error("Error:", error);
} finally {
setIsLoading(false);
}
};
return (
<div className="flex flex-col h-[calc(100vh-12rem)] max-w-4xl mx-auto bg-white rounded-2xl shadow-xl overflow-hidden border border-slate-200">
{/* Chat Header */}
<div className="bg-emerald-900 p-4 text-white flex justify-between items-center">
<div className="flex items-center gap-2">
<Sparkles className="w-5 h-5 text-emerald-300" />
<span className="font-bold">المختبر العلمي لمنارة البحث</span>
</div>
{messages.length > 0 && (
<button
onClick={() => onPromoteToProject(messages)}
className="text-xs bg-emerald-700 hover:bg-emerald-600 px-3 py-1.5 rounded-lg transition"
>
تحويل إلى مشروع بحثي
</button>
)}
</div>
{/* Messages Area */}
<div className="flex-grow overflow-y-auto p-6 space-y-6 bg-slate-50">
{messages.length === 0 && (
<div className="h-full flex flex-col items-center justify-center text-center space-y-4 opacity-60">
<div className="bg-white p-6 rounded-full shadow-inner">
<Bot className="w-12 h-12 text-emerald-800" />
</div>
<p className="max-w-xs text-slate-600 font-serif">
مرحباً بك في رحاب البحث المريدي. اسأل عن قصائد الشيخ، مواقفه، أو أصول المنهج.
</p>
</div>
)}
{messages.map((msg, idx) => (
<div key={idx} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[85%] flex gap-3 ${msg.role === 'user' ? 'flex-row-reverse' : 'flex-row'}`}>
<div className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${msg.role === 'user' ? 'bg-emerald-100 text-emerald-800' : 'bg-emerald-800 text-white'}`}>
{msg.role === 'user' ? <User className="w-5 h-5" /> : <Bot className="w-5 h-5" />}
</div>
<div className={`p-4 rounded-2xl shadow-sm ${msg.role === 'user' ? 'bg-emerald-700 text-white rounded-tr-none' : 'bg-white border border-slate-200 text-slate-800 rounded-tl-none'}`}>
<div className="prose prose-sm leading-relaxed whitespace-pre-wrap font-serif">
{msg.content}
</div>
{msg.citations && msg.citations.length > 0 && (
<div className="mt-4 pt-3 border-t border-slate-100 space-y-2">
<p className="text-[10px] font-bold text-emerald-600 uppercase tracking-widest">المصادر المرجعية:</p>
{msg.citations.map((cit, cIdx) => (
<div key={cIdx} className="flex items-center gap-2 text-xs bg-emerald-50 text-emerald-800 p-2 rounded border border-emerald-100">
<Quote className="w-3 h-3" />
<span>{cit.text}</span>
</div>
))}
</div>
)}
</div>
</div>
</div>
))}
{isLoading && (
<div className="flex justify-start">
<div className="bg-white border p-4 rounded-2xl flex items-center gap-3">
<RefreshCw className="w-4 h-4 text-emerald-600 animate-spin" />
<span className="text-sm text-slate-500 italic">الباحث يتدبر في المتون...</span>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Input Area */}
<div className="p-4 bg-white border-t">
<div className="flex gap-3">
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => { if(e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }}
placeholder="اكتب سؤالك هنا عن التراث المريدي..."
className="flex-grow p-3 bg-slate-100 border-none rounded-xl focus:ring-2 focus:ring-emerald-500 resize-none h-12 text-sm"
/>
<button
onClick={handleSend}
disabled={isLoading || !input.trim()}
className="bg-emerald-800 text-white p-3 rounded-xl hover:bg-emerald-700 disabled:opacity-50 transition-colors"
>
<Send className="w-5 h-5" />
</button>
</div>
</div>
</div>
);
};