mohammadSaber26 commited on
Commit
e378268
·
verified ·
1 Parent(s): 92a3f25

Upload components/ChatInterface.jsx with huggingface_hub

Browse files
Files changed (1) hide show
  1. components/ChatInterface.jsx +181 -0
components/ChatInterface.jsx ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+
3
+ import React, { useState, useRef, useEffect } from 'react';
4
+ import { Send, Bot, User, AlertTriangle, Code, ChevronDown } from 'lucide-react';
5
+
6
+ const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1/chat';
7
+ const USER_ID = 1;
8
+
9
+ const ChatInterface = () => {
10
+ const [messages, setMessages] = useState([]);
11
+ const [input, setInput] = useState('');
12
+ const [isLoading, setIsLoading] = useState(false);
13
+ const messagesEndRef = useRef(null);
14
+
15
+ const scrollToBottom = () => {
16
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
17
+ };
18
+
19
+ useEffect(() => {
20
+ scrollToBottom();
21
+ }, [messages]);
22
+
23
+ const addMessage = (content, type = 'bot') => {
24
+ setMessages((prev) => [...prev, { content, type }]);
25
+ };
26
+
27
+ const handleSend = async () => {
28
+ const text = input.trim();
29
+ if (!text) return;
30
+
31
+ addMessage(text, 'user');
32
+ setInput('');
33
+ setIsLoading(true);
34
+
35
+ try {
36
+ const res = await fetch(API_URL, {
37
+ method: 'POST',
38
+ headers: { 'Content-Type': 'application/json' },
39
+ body: JSON.stringify({
40
+ message: text,
41
+ user_id: USER_ID,
42
+ }),
43
+ });
44
+
45
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
46
+
47
+ const data = await res.json();
48
+ renderResponse(data);
49
+ } catch (e) {
50
+ addMessage(`❌ خطا در ارسال پیام: ${e.message}`, 'bot');
51
+ } finally {
52
+ setIsLoading(false);
53
+ }
54
+ };
55
+
56
+ const renderResponse = (data) => {
57
+ let html = '';
58
+
59
+ // متن اصلی
60
+ if (data.type === 'text') {
61
+ html += `<p>${data.data.message}</p>`;
62
+ }
63
+
64
+ // نتیجه محصول
65
+ if (data.type === 'product_list') {
66
+ html += `<p><b>نتیجه:</b> ${data.data.message}</p>`;
67
+ html += `<p>تعداد: ${data.data.total_count}</p>`;
68
+
69
+ data.data.products.forEach((p) => {
70
+ html += `
71
+ <div class="product-card">
72
+ <b>${p.name}</b><br/>
73
+ قیمت: ${p.formatted_price} تومان<br/>
74
+ وضعیت: ${p.stock ? 'موجود' : 'ناموجود'}<br/>
75
+ برند: ${p.brand || '-'} | شهر: ${p.city || '-'}
76
+ </div>
77
+ `;
78
+ });
79
+ }
80
+
81
+ // 🔴 اگر ابهام وجود داشت
82
+ if (data.debug && data.debug.is_ambiguous && data.debug.clarification_question) {
83
+ html += `<p class="message-clarification">❗ ابهام تشخیص داده شد: ${data.debug.clarification_question}</p>`;
84
+ }
85
+
86
+ // 🔍 JSON فیلترها (همیشه)
87
+ if (data.debug) {
88
+ html += `
89
+ <details>
90
+ <summary className="cursor-pointer text-gray-500 hover:text-gray-700 mb-2">
91
+ <ChevronDown className="inline w-4 h-4 mr-1" /> 🧪 فیلترهای استخراج‌شده توسط LLM
92
+ </summary>
93
+ <pre className="debug-panel">{JSON.stringify(data.debug, null, 2)}</pre>
94
+ </details>
95
+ `;
96
+ }
97
+
98
+ addMessage(html, 'bot');
99
+ };
100
+
101
+ return (
102
+ <div className="min-h-screen flex flex-col items-center justify-center bg-gray-100 p-4">
103
+ <div className="chat-container">
104
+ <header className="bg-brand-700 text-white p-4 flex items-center justify-between">
105
+ <div className="flex items-center gap-2">
106
+ <Bot className="w-6 h-6" />
107
+ <h1 className="text-xl font-bold">🧠 Enterprise Search Chat</h1>
108
+ </div>
109
+ <a
110
+ href="https://huggingface.co/spaces/akhaliq/anycoder"
111
+ target="_blank"
112
+ rel="noreferrer"
113
+ className="flex items-center gap-1 text-brand-100 hover:text-white transition-colors text-sm"
114
+ >
115
+ Built with anycoder
116
+ </a>
117
+ </header>
118
+
119
+ <div className="chat-messages">
120
+ {messages.length === 0 && (
121
+ <div className="flex flex-col items-center justify-center h-full text-gray-400 space-y-2">
122
+ <Bot className="w-12 h-12" />
123
+ <p>چطور می‌توانم کمکتان کنم؟</p>
124
+ </div>
125
+ )}
126
+
127
+ {messages.map((msg, idx) => (
128
+ <div key={idx} className={msg.type === 'user' ? 'message-user' : 'message-bot'}>
129
+ <div className="message-content">
130
+ {msg.type === 'user' ? (
131
+ <User className="w-4 h-4 inline-block mb-1" />
132
+ ) : (
133
+ <Bot className="w-4 h-4 inline-block mb-1" />
134
+ )}
135
+ <div className="whitespace-pre-wrap">
136
+ {msg.content}
137
+ </div>
138
+ </div>
139
+ </div>
140
+ ))}
141
+
142
+ {isLoading && (
143
+ <div className="flex justify-start">
144
+ <div className="message-content bg-white border border-gray-200 rounded-bl-none">
145
+ <div className="flex items-center gap-2">
146
+ <div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" />
147
+ <div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce delay-100" />
148
+ <div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce delay-200" />
149
+ </div>
150
+ </div>
151
+ </div>
152
+ )}
153
+ </div>
154
+
155
+ <div className="p-4 bg-white border-t border-gray-200">
156
+ <div className="flex gap-2">
157
+ <input
158
+ type="text"
159
+ value={input}
160
+ onChange={(e) => setInput(e.target.value)}
161
+ onKeyPress={(e) => e.key === 'Enter' && handleSend()}
162
+ placeholder="مثلاً: برند اپکس بالای 5 میلیون"
163
+ disabled={isLoading}
164
+ className="flex-1 px-4 py-3 rounded-xl border border-gray-300 focus:outline-none focus:ring-2 focus:ring-brand-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
165
+ />
166
+ <button
167
+ onClick={handleSend}
168
+ disabled={isLoading || !input.trim()}
169
+ className="px-6 py-3 bg-brand-600 text-white rounded-xl hover:bg-brand-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-all flex items-center gap-2"
170
+ >
171
+ <Send className="w-5 h-5" />
172
+ <span className="hidden sm:inline">ارسال</span>
173
+ </button>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ </div>
178
+ );
179
+ };
180
+
181
+ export default ChatInterface;