Mehdi commited on
Commit
aad61ab
·
verified ·
1 Parent(s): e350ad1

Upload components/ChatInterface.jsx with huggingface_hub

Browse files
Files changed (1) hide show
  1. components/ChatInterface.jsx +63 -227
components/ChatInterface.jsx CHANGED
@@ -1,37 +1,19 @@
1
  import { useState, useRef, useEffect } from 'react'
2
- import { motion, AnimatePresence } from 'framer-motion'
3
- import { FaRobot, FaUser, FaPaperPlane, FaMicrophone, FaStop, FaCopy, FaThumbsUp, FaThumbsDown, FaRedo, FaLanguage, FaBrain, FaGlobe, FaCheckCircle, FaExclamationTriangle } from 'react-icons/fa'
4
- import ReactMarkdown from 'react-markdown'
5
- import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
6
- import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'
7
- import toast from 'react-hot-toast'
8
 
9
- export default function ChatInterface({ language, theme }) {
10
  const [messages, setMessages] = useState([
11
  {
12
  id: 1,
13
- type: 'assistant',
14
- content: language === 'fa' ?
15
- 'سلام! من GhadirSync-AI هستم، دستیار هوشمند شما. چطور می‌توانم به شما کمک کنم؟' :
16
- 'Hello! I am GhadirSync-AI, your intelligent assistant. How can I help you?',
17
- timestamp: new Date(),
18
- sources: [],
19
- confidence: 0.95
20
  }
21
  ])
22
  const [input, setInput] = useState('')
23
- const [isTyping, setIsTyping] = useState(false)
24
  const [isListening, setIsListening] = useState(false)
25
- const [selectedModel, setSelectedModel] = useState('local')
26
- const [useInternet, setUseInternet] = useState(false)
27
  const messagesEndRef = useRef(null)
28
- const inputRef = useRef(null)
29
-
30
- const models = [
31
- { id: 'local', name: language === 'fa' ? 'مدل محلی' : 'Local Model', icon: FaBrain, color: 'text-green-400' },
32
- { id: 'gpt4', name: 'GPT-4', icon: FaGlobe, color: 'text-blue-400' },
33
- { id: 'claude', name: 'Claude', icon: FaBrain, color: 'text-purple-400' },
34
- ]
35
 
36
  const scrollToBottom = () => {
37
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
@@ -41,226 +23,80 @@ export default function ChatInterface({ language, theme }) {
41
  scrollToBottom()
42
  }, [messages])
43
 
44
- const handleSend = async () => {
45
  if (!input.trim()) return
46
 
47
  const userMessage = {
48
- id: Date.now(),
49
- type: 'user',
50
- content: input,
51
- timestamp: new Date(),
52
  }
53
 
54
- setMessages(prev => [...prev, userMessage])
55
  setInput('')
56
- setIsTyping(true)
57
 
58
- // Simulate AI response
59
  setTimeout(() => {
60
- const aiResponse = {
61
- id: Date.now() + 1,
62
- type: 'assistant',
63
- content: generateAIResponse(input),
64
- timestamp: new Date(),
65
- sources: useInternet ? [
66
- { title: 'Wikipedia', url: 'https://wikipedia.org' },
67
- { title: 'Stack Overflow', url: 'https://stackoverflow.com' }
68
- ] : [],
69
- confidence: Math.random() * 0.3 + 0.7,
70
- model: selectedModel
71
  }
72
- setMessages(prev => [...prev, aiResponse])
73
- setIsTyping(false)
74
- }, 1500)
75
- }
76
-
77
- const generateAIResponse = (userInput) => {
78
- const responses = {
79
- fa: [
80
- `برای سوال "${userInput}"، من تحلیل کاملی ارائه می‌دهم:\n\n## تحلیل اصلی\n\n1. **نکته اول**: این یک موضوع مهم است\n2. **نکته دوم**: نیاز به بررسی بیشتر دارد\n3. **نکته سوم**: پیشنهادات عملی\n\n\`\`\`javascript\n// نمونه کد\nfunction example() {\n return "Hello World";\n}\n\`\`\`\n\n**نتیجه‌گیری**: بر اساس تحلیل، بهترین راهکار...`,
81
- `در پاسخ به "${userInput}":\n\n### اطلاعات کلیدی\n\n- 🎯 هدف اصلی\n- 📊 تحلیل داده‌ها\n- 💡 راهکارهای نوآورانه\n\n## پیشنهادات\n\n1. راهکار اول\n2. راهکار دوم\n3. راهکار سوم\n\n**توجه**: این اطلاعات بر اساس بهترین منابع موجود است.`,
82
- ],
83
- en: [
84
- `For your question "${userInput}", here's my comprehensive analysis:\n\n## Main Analysis\n\n1. **First Point**: This is an important topic\n2. **Second Point**: Requires further investigation\n3. **Third Point**: Practical suggestions\n\n\`\`\`python\n# Sample code\ndef example():\n return "Hello World"\n\`\`\`\n\n**Conclusion**: Based on the analysis, the best solution is...`,
85
- `In response to "${userInput}":\n\n### Key Information\n\n- 🎯 Main objective\n- 📊 Data analysis\n- 💡 Innovative solutions\n\n## Recommendations\n\n1. First solution\n2. Second solution\n3. Third solution\n\n**Note**: This information is based on the best available sources.`,
86
- ]
87
- }
88
-
89
- const langResponses = responses[language] || responses.en
90
- return langResponses[Math.floor(Math.random() * langResponses.length)]
91
  }
92
 
93
- const handleVoiceInput = () => {
94
- if (isListening) {
95
- setIsListening(false)
96
- toast.success(language === 'fa' ? 'ضبط صدا متوقف شد' : 'Voice recording stopped')
97
- } else {
98
- setIsListening(true)
99
- toast.success(language === 'fa' ? 'در حال ضبط صدا...' : 'Recording voice...')
100
-
101
- // Simulate voice recognition
102
- setTimeout(() => {
103
- setInput(language === 'fa' ? 'این یک متن نمونه از تشخیص صدا است' : 'This is a sample text from voice recognition')
104
- setIsListening(false)
105
- }, 3000)
106
- }
107
- }
108
-
109
- const handleCopyMessage = (content) => {
110
- navigator.clipboard.writeText(content)
111
- toast.success(language === 'fa' ? 'کپی شد!' : 'Copied!')
112
- }
113
-
114
- const handleRegenerateResponse = (messageId) => {
115
- setIsTyping(true)
116
- setTimeout(() => {
117
- setMessages(prev => prev.map(msg =>
118
- msg.id === messageId
119
- ? {
120
- ...msg,
121
- content: generateAIResponse(' regenerated response'),
122
- timestamp: new Date()
123
- }
124
- : msg
125
- ))
126
- setIsTyping(false)
127
- }, 1500)
128
  }
129
 
130
  return (
131
- <div className="flex flex-col h-full space-y-4">
132
- {/* Model Selection */}
133
- <div className="flex items-center justify-between p-4 bg-gray-800 rounded-lg">
134
- <div className="flex items-center space-x-reverse space-x-4">
135
- <span className="text-sm font-medium">
136
- {language === 'fa' ? 'مدل هوش مصنوعی:' : 'AI Model:'}
137
- </span>
138
- <div className="flex space-x-reverse space-x-2">
139
- {models.map(model => {
140
- const Icon = model.icon
141
- return (
142
- <button
143
- key={model.id}
144
- onClick={() => setSelectedModel(model.id)}
145
- className={`flex items-center space-x-reverse space-x-2 px-3 py-2 rounded-lg transition-all ${
146
- selectedModel === model.id
147
- ? 'bg-primary-600 text-white'
148
- : 'bg-gray-700 text-gray-300 hover:bg-gray-600'
149
- }`}
150
- >
151
- <Icon className={`w-4 h-4 ${model.color}`} />
152
- <span className="text-sm">{model.name}</span>
153
- </button>
154
- )
155
- })}
156
  </div>
157
- </div>
158
-
 
 
 
 
 
 
 
 
 
 
 
159
  <button
160
- onClick={() => setUseInternet(!useInternet)}
161
- className={`flex items-center space-x-reverse space-x-2 px-3 py-2 rounded-lg transition-all ${
162
- useInternet
163
- ? 'bg-green-600 text-white'
164
- : 'bg-gray-700 text-gray-300 hover:bg-gray-600'
165
- }`}
166
  >
167
- <FaGlobe className="w-4 h-4" />
168
- <span className="text-sm">
169
- {language === 'fa' ? 'اینترنت' : 'Internet'}
170
- </span>
 
 
 
171
  </button>
172
  </div>
 
 
 
173
 
174
- {/* Messages */}
175
- <div className="flex-1 overflow-y-auto space-y-4 p-4 bg-gray-800 rounded-lg">
176
- <AnimatePresence>
177
- {messages.map(message => (
178
- <motion.div
179
- key={message.id}
180
- initial={{ opacity: 0, y: 20 }}
181
- animate={{ opacity: 1, y: 0 }}
182
- exit={{ opacity: 0, y: -20 }}
183
- className={`flex ${message.type === 'user' ? 'justify-start' : 'justify-end'}`}
184
- >
185
- <div className={`flex space-x-reverse space-x-3 max-w-3xl ${
186
- message.type === 'user' ? 'flex-row' : 'flex-row-reverse'
187
- }`}>
188
- <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${
189
- message.type === 'user' ? 'bg-primary-500' : 'bg-secondary-500'
190
- }`}>
191
- {message.type === 'user' ? (
192
- <FaUser className="w-5 h-5 text-white" />
193
- ) : (
194
- <FaRobot className="w-5 h-5 text-white" />
195
- )}
196
- </div>
197
-
198
- <div className={`flex-1 p-4 rounded-lg ${
199
- message.type === 'user'
200
- ? 'bg-primary-600 text-white'
201
- : 'bg-gray-700 text-gray-100'
202
- }`}>
203
- <div className="flex items-start justify-between mb-2">
204
- <span className="text-xs opacity-75">
205
- {message.timestamp.toLocaleTimeString()}
206
- </span>
207
- {message.type === 'assistant' && (
208
- <div className="flex items-center space-x-reverse space-x-2">
209
- {message.confidence && (
210
- <span className="text-xs opacity-75">
211
- {Math.round(message.confidence * 100)}%
212
- </span>
213
- )}
214
- <button
215
- onClick={() => handleCopyMessage(message.content)}
216
- className="opacity-50 hover:opacity-100 transition-opacity"
217
- >
218
- <FaCopy className="w-3 h-3" />
219
- </button>
220
- <button
221
- onClick={() => handleRegenerateResponse(message.id)}
222
- className="opacity-50 hover:opacity-100 transition-opacity"
223
- >
224
- <FaRedo className="w-3 h-3" />
225
- </button>
226
- </div>
227
- )}
228
- </div>
229
-
230
- <div className="prose prose-sm max-w-none prose-invert">
231
- <ReactMarkdown
232
- components={{
233
- code({ node, inline, className, children, ...props }) {
234
- const match = /language-(\w+)/.exec(className || '')
235
- return !inline && match ? (
236
- <SyntaxHighlighter
237
- style={vscDarkPlus}
238
- language={match[1]}
239
- PreTag="div"
240
- className="rounded-lg"
241
- {...props}
242
- >
243
- {String(children).replace(/\n$/, '')}
244
- </SyntaxHighlighter>
245
- ) : (
246
- <code className={className} {...props}>
247
- {children}
248
- </code>
249
- )
250
- }
251
-
252
- >
253
- {message.content}
254
- </ReactMarkdown>
255
- </div>
256
-
257
- {message.sources && message.sources.length > 0 && (
258
- <div className="mt-4 pt-4 border-t border-gray-600">
259
- <p className="text-xs font-medium mb-2 opacity-75">
260
- {language === 'fa' ? 'منابع:' : 'Sources:'}
261
- </p>
262
- <div className="space-y-1">
263
- {message.sources.map((source, index) => (
264
- <a
265
- key={index}
266
- href={source.url}
 
1
  import { useState, useRef, useEffect } from 'react'
2
+ import { FaPaperPlane, FaMicrophone, FaStop } from 'react-icons/fa'
 
 
 
 
 
3
 
4
+ const ChatInterface = ({ language }) => {
5
  const [messages, setMessages] = useState([
6
  {
7
  id: 1,
8
+ text: language === 'fa'
9
+ ? 'سلام! من GhadirSync-AI هستم. چگونه می‌توانم به شما کمک کنم؟'
10
+ : 'Hello! I am GhadirSync-AI. How can I help you?',
11
+ sender: 'bot'
 
 
 
12
  }
13
  ])
14
  const [input, setInput] = useState('')
 
15
  const [isListening, setIsListening] = useState(false)
 
 
16
  const messagesEndRef = useRef(null)
 
 
 
 
 
 
 
17
 
18
  const scrollToBottom = () => {
19
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
 
23
  scrollToBottom()
24
  }, [messages])
25
 
26
+ const handleSend = () => {
27
  if (!input.trim()) return
28
 
29
  const userMessage = {
30
+ id: messages.length + 1,
31
+ text: input,
32
+ sender: 'user'
 
33
  }
34
 
35
+ setMessages([...messages, userMessage])
36
  setInput('')
 
37
 
38
+ // Simulate bot response
39
  setTimeout(() => {
40
+ const botMessage = {
41
+ id: messages.length + 2,
42
+ text: language === 'fa'
43
+ ? 'پیام شما دریافت شد. در حال پردازش درخواست...'
44
+ : 'Message received. Processing your request...',
45
+ sender: 'bot'
 
 
 
 
 
46
  }
47
+ setMessages(prev => [...prev, botMessage])
48
+ }, 1000)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
 
51
+ const toggleListening = () => {
52
+ setIsListening(!isListening)
53
+ // Here you would integrate with Web Speech API
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
 
56
  return (
57
+ <div className="bg-white rounded-lg shadow-md p-4">
58
+ <div className="h-96 overflow-y-auto mb-4 space-y-4">
59
+ {messages.map((message) => (
60
+ <div
61
+ key={message.id}
62
+ className={`flex ${message.sender === 'user' ? 'justify-start' : 'justify-end'}`}
63
+ >
64
+ <div
65
+ className={`max-w-xs md:max-w-md lg:max-w-lg rounded-lg p-3 ${message.sender === 'user'
66
+ ? 'bg-blue-100 text-blue-900'
67
+ : 'bg-gray-200 text-gray-900'}`}
68
+ >
69
+ {message.text}
70
+ </div>
 
 
 
 
 
 
 
 
 
 
 
71
  </div>
72
+ ))}
73
+ <div ref={messagesEndRef} />
74
+ </div>
75
+
76
+ <div className="flex items-center">
77
+ <input
78
+ type="text"
79
+ value={input}
80
+ onChange={(e) => setInput(e.target.value)}
81
+ onKeyPress={(e) => e.key === 'Enter' && handleSend()}
82
+ placeholder={language === 'fa' ? 'پیام خود را بنویسید...' : 'Type your message...'}
83
+ className="flex-1 p-2 border rounded-l focus:outline-none focus:ring-2 focus:ring-blue-500"
84
+ />
85
  <button
86
+ onClick={toggleListening}
87
+ className={`px-3 py-2 ${isListening ? 'bg-red-500' : 'bg-gray-500'} text-white`}
 
 
 
 
88
  >
89
+ {isListening ? <FaStop /> : <FaMicrophone />}
90
+ </button>
91
+ <button
92
+ onClick={handleSend}
93
+ className="px-4 py-2 bg-blue-600 text-white rounded-r hover:bg-blue-700"
94
+ >
95
+ <FaPaperPlane />
96
  </button>
97
  </div>
98
+ </div>
99
+ )
100
+ }
101
 
102
+ export default ChatInterface