tigerbase-chatbot 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ChatbotPopup.js +101 -50
- package/package.json +55 -55
package/dist/ChatbotPopup.js
CHANGED
|
@@ -14,31 +14,18 @@ const ChatbotPopup = () => {
|
|
|
14
14
|
const cfg = getConfig();
|
|
15
15
|
const MCP_URL = cfg.secretKey || "";
|
|
16
16
|
const genAIKey = cfg.aiKey;
|
|
17
|
-
const defaultLang = cfg.defaultLang || "ar";
|
|
18
|
-
if (!genAIKey) {
|
|
19
|
-
toast.error(defaultLang === "ar"
|
|
20
|
-
? "مفتاح Google GenAI غير موجود"
|
|
21
|
-
: "Google GenAI key not set");
|
|
22
|
-
throw new Error("Google GenAI key not set");
|
|
23
|
-
}
|
|
24
|
-
const genAI = new GoogleGenerativeAI(genAIKey);
|
|
25
|
-
const systemInstruction = `You are a helpful assistant for product management. Always respond in ${defaultLang === "ar" ? "Arabic" : "English"}. ${cfg.customPrompt || ""}
|
|
26
|
-
When user asks for product information with an ID, use the get-product-info tool and pass the ID in the arguments.
|
|
27
|
-
When user asks to list products, use the list-products tool.
|
|
28
|
-
When user asks to add a product, use the add-product tool with name, price, and description.`;
|
|
29
|
-
const model = genAI.getGenerativeModel({
|
|
30
|
-
model: "gemini-2.5-flash",
|
|
31
|
-
systemInstruction,
|
|
32
|
-
});
|
|
33
17
|
const [isOpen, setIsOpen] = useState(false);
|
|
34
18
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
const [remoteConfig, setRemoteConfig] = useState(null);
|
|
21
|
+
const effectiveLang = remoteConfig?.language || cfg.defaultLang || "ar";
|
|
35
22
|
const [messages, setMessages] = useState([
|
|
36
23
|
{
|
|
37
24
|
role: "model",
|
|
38
|
-
content:
|
|
25
|
+
content: effectiveLang === "ar"
|
|
39
26
|
? "أهلاً وسهلاً! أنا هنا لمساعدتك في إدارة المنتجات. كيف يمكنني مساعدتك؟"
|
|
40
27
|
: "Hello! I'm here to help with product management. How can I assist you?",
|
|
41
|
-
timestamp: new Date().toLocaleTimeString(
|
|
28
|
+
timestamp: new Date().toLocaleTimeString(effectiveLang === "ar" ? "ar-EG" : "en-US", {
|
|
42
29
|
hour: "2-digit",
|
|
43
30
|
minute: "2-digit",
|
|
44
31
|
hour12: true,
|
|
@@ -48,6 +35,66 @@ const ChatbotPopup = () => {
|
|
|
48
35
|
const [input, setInput] = useState("");
|
|
49
36
|
const [loading, setLoading] = useState(false);
|
|
50
37
|
const messagesEndRef = useRef(null);
|
|
38
|
+
if (!genAIKey) {
|
|
39
|
+
toast.error(effectiveLang === "ar"
|
|
40
|
+
? "مفتاح Google GenAI غير موجود"
|
|
41
|
+
: "Google GenAI key not set");
|
|
42
|
+
throw new Error("Google GenAI key not set");
|
|
43
|
+
}
|
|
44
|
+
const genAI = new GoogleGenerativeAI(genAIKey);
|
|
45
|
+
const baseSystemInstruction = `You are a helpful assistant. Always respond in ${effectiveLang === "ar" ? "Arabic" : "English"}.
|
|
46
|
+
When user asks for product information with an ID, use the get-product-info tool and pass the ID in the arguments.
|
|
47
|
+
When user asks to list products, use the list-products tool.
|
|
48
|
+
When user asks to add a product, use the add-product tool with name, price, and description.
|
|
49
|
+
|
|
50
|
+
IMPORTANT: If specific information (regulations, data, etc.) is provided in the context below, prioritize it over your general knowledge.`;
|
|
51
|
+
const systemInstruction = remoteConfig?.systemInstruction
|
|
52
|
+
? `${remoteConfig.systemInstruction}\n\n${baseSystemInstruction}`
|
|
53
|
+
: baseSystemInstruction;
|
|
54
|
+
const model = genAI.getGenerativeModel({
|
|
55
|
+
model: "gemini-2.5-flash",
|
|
56
|
+
systemInstruction,
|
|
57
|
+
});
|
|
58
|
+
// Fetch remote config
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
const fetchConfig = async () => {
|
|
61
|
+
if (!MCP_URL || !cfg.apiKey)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
// Derive API URL from MCP URL (remove /mcp suffix if present)
|
|
65
|
+
const baseUrl = MCP_URL.replace(/\/mcp\/?$/, "");
|
|
66
|
+
const response = await fetch(`${baseUrl}/chatbots/public/config`, {
|
|
67
|
+
headers: {
|
|
68
|
+
"x-api-key": cfg.apiKey,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
if (response.ok) {
|
|
72
|
+
const data = await response.json();
|
|
73
|
+
setRemoteConfig(data);
|
|
74
|
+
// Update initial message if no user interaction yet
|
|
75
|
+
if (messages.length === 1 && messages[0].role === "model") {
|
|
76
|
+
const initialMsg = data.initialMessage ||
|
|
77
|
+
(data.language === "ar"
|
|
78
|
+
? "أهلاً وسهلاً! كيف يمكنني مساعدتك؟"
|
|
79
|
+
: "Hello! How can I help you?");
|
|
80
|
+
setMessages([
|
|
81
|
+
{
|
|
82
|
+
role: "model",
|
|
83
|
+
content: initialMsg,
|
|
84
|
+
timestamp: new Date().toLocaleTimeString(data.language === "ar" ? "ar-EG" : "en-US", { hour: "2-digit", minute: "2-digit", hour12: true }),
|
|
85
|
+
},
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error("Failed to fetch chatbot config:", error);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
if (isOpen) {
|
|
95
|
+
fetchConfig();
|
|
96
|
+
}
|
|
97
|
+
}, [MCP_URL, cfg.apiKey, isOpen]);
|
|
51
98
|
// Auto delete chats
|
|
52
99
|
useEffect(() => {
|
|
53
100
|
if (cfg.autoDeleteChats) {
|
|
@@ -55,23 +102,23 @@ const ChatbotPopup = () => {
|
|
|
55
102
|
setMessages([
|
|
56
103
|
{
|
|
57
104
|
role: "model",
|
|
58
|
-
content:
|
|
105
|
+
content: effectiveLang === "ar"
|
|
59
106
|
? "أهلاً وسهلاً! أنا هنا لمساعدتك في إدارة المنتجات. كيف يمكنني مساعدتك؟"
|
|
60
107
|
: "Hello! I'm here to help with product management. How can I assist you?",
|
|
61
|
-
timestamp: new Date().toLocaleTimeString(
|
|
108
|
+
timestamp: new Date().toLocaleTimeString(effectiveLang === "ar" ? "ar-EG" : "en-US", {
|
|
62
109
|
hour: "2-digit",
|
|
63
110
|
minute: "2-digit",
|
|
64
111
|
hour12: true,
|
|
65
112
|
}),
|
|
66
113
|
},
|
|
67
114
|
]);
|
|
68
|
-
toast.info(
|
|
115
|
+
toast.info(effectiveLang === "ar"
|
|
69
116
|
? "تم مسح المحادثة تلقائيًا"
|
|
70
117
|
: "Chat cleared automatically");
|
|
71
118
|
}, cfg.autoDeleteChats * 60 * 1000);
|
|
72
119
|
return () => clearTimeout(timer);
|
|
73
120
|
}
|
|
74
|
-
}, [messages, cfg.autoDeleteChats,
|
|
121
|
+
}, [messages, cfg.autoDeleteChats, effectiveLang]);
|
|
75
122
|
const scrollToBottom = () => {
|
|
76
123
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
77
124
|
};
|
|
@@ -79,7 +126,7 @@ const ChatbotPopup = () => {
|
|
|
79
126
|
scrollToBottom();
|
|
80
127
|
}, [messages]);
|
|
81
128
|
const formatTimestamp = () => {
|
|
82
|
-
return new Date().toLocaleTimeString(
|
|
129
|
+
return new Date().toLocaleTimeString(effectiveLang === "ar" ? "ar-EG" : "en-US", {
|
|
83
130
|
hour: "2-digit",
|
|
84
131
|
minute: "2-digit",
|
|
85
132
|
hour12: true,
|
|
@@ -87,7 +134,7 @@ const ChatbotPopup = () => {
|
|
|
87
134
|
};
|
|
88
135
|
const handleMcpToolCall = async (toolName, args, retries = 2) => {
|
|
89
136
|
if (!cfg.validatedTools.includes(toolName)) {
|
|
90
|
-
throw new Error(
|
|
137
|
+
throw new Error(effectiveLang === "ar"
|
|
91
138
|
? `الأداة ${toolName} غير متاحة لهذا السيريال`
|
|
92
139
|
: `Tool ${toolName} not available for this serial`);
|
|
93
140
|
}
|
|
@@ -124,7 +171,7 @@ const ChatbotPopup = () => {
|
|
|
124
171
|
return JSON.parse(data.result.content[0].text);
|
|
125
172
|
}
|
|
126
173
|
return (data.result ||
|
|
127
|
-
(
|
|
174
|
+
(effectiveLang === "ar"
|
|
128
175
|
? "تم تنفيذ الأمر بنجاح"
|
|
129
176
|
: "Command executed successfully"));
|
|
130
177
|
}
|
|
@@ -133,7 +180,7 @@ const ChatbotPopup = () => {
|
|
|
133
180
|
await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
|
|
134
181
|
continue;
|
|
135
182
|
}
|
|
136
|
-
throw new Error(
|
|
183
|
+
throw new Error(effectiveLang === "ar"
|
|
137
184
|
? `فشل استدعاء ${toolName} بعد ${retries + 1} محاولة: ${e.message}`
|
|
138
185
|
: `Failed to call ${toolName} after ${retries + 1} attempts: ${e.message}`);
|
|
139
186
|
}
|
|
@@ -221,7 +268,7 @@ const ChatbotPopup = () => {
|
|
|
221
268
|
},
|
|
222
269
|
tools: toolsConfig,
|
|
223
270
|
});
|
|
224
|
-
let assistantReply =
|
|
271
|
+
let assistantReply = effectiveLang === "ar"
|
|
225
272
|
? "عذرًا، لم أفهم الطلب."
|
|
226
273
|
: "Sorry, I didn't understand the request.";
|
|
227
274
|
const response = await result.response;
|
|
@@ -238,13 +285,13 @@ const ChatbotPopup = () => {
|
|
|
238
285
|
assistantReply = {
|
|
239
286
|
products: Array.isArray(toolResult) ? toolResult : [toolResult],
|
|
240
287
|
};
|
|
241
|
-
toast.success(
|
|
288
|
+
toast.success(effectiveLang === "ar"
|
|
242
289
|
? "تم جلب البيانات بنجاح!"
|
|
243
290
|
: "Data fetched successfully!");
|
|
244
291
|
}
|
|
245
292
|
catch (e) {
|
|
246
293
|
assistantReply =
|
|
247
|
-
|
|
294
|
+
effectiveLang === "ar"
|
|
248
295
|
? `عذرًا، حدث خطأ أثناء تنفيذ الأمر: ${e.message}`
|
|
249
296
|
: `Sorry, an error occurred while executing the command: ${e.message}`;
|
|
250
297
|
toast.error(e.message);
|
|
@@ -258,7 +305,9 @@ const ChatbotPopup = () => {
|
|
|
258
305
|
.join("\n");
|
|
259
306
|
assistantReply =
|
|
260
307
|
textParts ||
|
|
261
|
-
(
|
|
308
|
+
(effectiveLang === "ar"
|
|
309
|
+
? "لم أتمكن من الرد."
|
|
310
|
+
: "Couldn't respond.");
|
|
262
311
|
}
|
|
263
312
|
}
|
|
264
313
|
setMessages((prev) => [
|
|
@@ -275,20 +324,22 @@ const ChatbotPopup = () => {
|
|
|
275
324
|
const isOverloaded = errorMessage.includes("overloaded") || errorMessage.includes("503");
|
|
276
325
|
const waitTime = isOverloaded ? 5000 : 1000;
|
|
277
326
|
if (retryCount > 0) {
|
|
278
|
-
toast.warn(
|
|
327
|
+
toast.warn(effectiveLang === "ar"
|
|
279
328
|
? `فشل الطلب، جاري إعادة المحاولة... (${retryCount} محاولة متبقية)`
|
|
280
329
|
: `Request failed, retrying... (${retryCount} attempts left)`);
|
|
281
330
|
setTimeout(() => handleSend(retryCount - 1), waitTime);
|
|
282
331
|
return;
|
|
283
332
|
}
|
|
284
333
|
const errorMsg = errorMessage ||
|
|
285
|
-
(
|
|
286
|
-
toast.error(`${
|
|
334
|
+
(effectiveLang === "ar" ? "حدث خطأ غير متوقع" : "Unexpected error");
|
|
335
|
+
toast.error(`${effectiveLang === "ar" ? "خطأ" : "Error"}: ${errorMsg}`);
|
|
287
336
|
setMessages((prev) => [
|
|
288
337
|
...prev,
|
|
289
338
|
{
|
|
290
339
|
role: "model",
|
|
291
|
-
content: `${
|
|
340
|
+
content: `${effectiveLang === "ar"
|
|
341
|
+
? "عذرًا، حدث خطأ"
|
|
342
|
+
: "Sorry, an error occurred"}: ${errorMsg}`,
|
|
292
343
|
timestamp: formatTimestamp(),
|
|
293
344
|
},
|
|
294
345
|
]);
|
|
@@ -317,12 +368,12 @@ const ChatbotPopup = () => {
|
|
|
317
368
|
timestamp: formatTimestamp(),
|
|
318
369
|
},
|
|
319
370
|
]);
|
|
320
|
-
toast.success(
|
|
371
|
+
toast.success(effectiveLang === "ar"
|
|
321
372
|
? "تم تحديث قائمة المنتجات!"
|
|
322
373
|
: "Product list updated!");
|
|
323
374
|
}
|
|
324
375
|
catch (e) {
|
|
325
|
-
toast.error(
|
|
376
|
+
toast.error(effectiveLang === "ar"
|
|
326
377
|
? `فشل تحديث المنتجات: ${e.message}`
|
|
327
378
|
: `Failed to update products: ${e.message}`);
|
|
328
379
|
}
|
|
@@ -334,24 +385,24 @@ const ChatbotPopup = () => {
|
|
|
334
385
|
setMessages([
|
|
335
386
|
{
|
|
336
387
|
role: "model",
|
|
337
|
-
content:
|
|
388
|
+
content: effectiveLang === "ar"
|
|
338
389
|
? "أهلاً وسهلاً! أنا هنا لمساعدتك في إدارة المنتجات. كيف يمكنني مساعدتك؟"
|
|
339
390
|
: "Hello! I'm here to help with product management. How can I assist you?",
|
|
340
391
|
timestamp: formatTimestamp(),
|
|
341
392
|
},
|
|
342
393
|
]);
|
|
343
394
|
setInput("");
|
|
344
|
-
toast.info(
|
|
395
|
+
toast.info(effectiveLang === "ar" ? "تم مسح المحادثة" : "Chat cleared");
|
|
345
396
|
};
|
|
346
397
|
const showCart = () => {
|
|
347
398
|
const cart = JSON.parse(localStorage.getItem("cart") || "[]");
|
|
348
399
|
if (cart.length === 0) {
|
|
349
|
-
toast.warn(
|
|
400
|
+
toast.warn(effectiveLang === "ar" ? "السلة فاضية!" : "Cart is empty!");
|
|
350
401
|
setMessages((prev) => [
|
|
351
402
|
...prev,
|
|
352
403
|
{
|
|
353
404
|
role: "model",
|
|
354
|
-
content:
|
|
405
|
+
content: effectiveLang === "ar"
|
|
355
406
|
? "السلة فاضية حالياً! يمكنك إضافة المنتجات من قائمة المنتجات."
|
|
356
407
|
: "The cart is empty! You can add products from the product list.",
|
|
357
408
|
timestamp: formatTimestamp(),
|
|
@@ -367,38 +418,38 @@ const ChatbotPopup = () => {
|
|
|
367
418
|
timestamp: formatTimestamp(),
|
|
368
419
|
},
|
|
369
420
|
]);
|
|
370
|
-
toast.info(
|
|
421
|
+
toast.info(effectiveLang === "ar"
|
|
371
422
|
? `عرض السلة (${cart.length} منتج)`
|
|
372
423
|
: `Showing cart (${cart.length} items)`);
|
|
373
424
|
};
|
|
374
|
-
const ProductCard = ({ product }) => (_jsx(Card, { className: "mb-3 border border-gray-200 shadow-sm hover:shadow-md transition-shadow", children: _jsx(CardContent, { className: "p-4", children: _jsxs("div", { className: "flex justify-between items-start", children: [_jsxs("div", { className: "flex-1", children: [_jsx("h4", { className: "font-semibold text-gray-800 text-sm", children: product.name }), _jsx("p", { className: "text-xs text-gray-600 mt-1 line-clamp-2", children: product.description }), _jsxs("div", { className: "flex items-center gap-2 mt-2", children: [_jsxs(Badge, { variant: "secondary", className: "text-xs", children: [product.price, " ",
|
|
425
|
+
const ProductCard = ({ product }) => (_jsx(Card, { className: "mb-3 border border-gray-200 shadow-sm hover:shadow-md transition-shadow", children: _jsx(CardContent, { className: "p-4", children: _jsxs("div", { className: "flex justify-between items-start", children: [_jsxs("div", { className: "flex-1", children: [_jsx("h4", { className: "font-semibold text-gray-800 text-sm", children: product.name }), _jsx("p", { className: "text-xs text-gray-600 mt-1 line-clamp-2", children: product.description }), _jsxs("div", { className: "flex items-center gap-2 mt-2", children: [_jsxs(Badge, { variant: "secondary", className: "text-xs", children: [product.price, " ", effectiveLang === "ar" ? "جنيه" : "EGP"] }), _jsxs(Badge, { variant: "outline", className: "text-xs", children: ["ID: ", product.id] })] })] }), _jsx(Button, { size: "sm", variant: "outline", className: "text-xs h-8 px-3", onClick: () => {
|
|
375
426
|
const cart = JSON.parse(localStorage.getItem("cart") || "[]");
|
|
376
427
|
cart.push(product);
|
|
377
428
|
localStorage.setItem("cart", JSON.stringify(cart));
|
|
378
|
-
toast.success(
|
|
429
|
+
toast.success(effectiveLang === "ar"
|
|
379
430
|
? "تم إضافة المنتج للسلة!"
|
|
380
431
|
: "Product added to cart!");
|
|
381
|
-
}, children:
|
|
432
|
+
}, children: effectiveLang === "ar" ? "إضافة للسلة" : "Add to Cart" })] }) }) }));
|
|
382
433
|
const MessageBubble = ({ message }) => {
|
|
383
434
|
const isUser = message.role === "user";
|
|
384
435
|
return (_jsx("div", { className: `flex mb-4 ${isUser ? "justify-end" : "justify-start"}`, children: _jsxs("div", { className: `flex max-w-[85%] ${isUser ? "flex-row-reverse" : "flex-row"}`, children: [_jsx("div", { className: `w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${isUser ? "bg-blue-500 ml-3" : "bg-gray-200 mr-3"}`, children: isUser ? (_jsx(User, { className: "w-4 h-4 text-white" })) : (_jsx(Bot, { className: "w-4 h-4 text-gray-600" })) }), _jsxs("div", { className: `p-3 rounded-2xl ${isUser
|
|
385
436
|
? "bg-blue-500 text-white rounded-br-md"
|
|
386
|
-
: "bg-gray-100 text-gray-800 rounded-bl-md"}`, children: [typeof message.content === "string" ? (_jsx("p", { className: "text-sm leading-relaxed", children: message.content })) : message.content.products ? (_jsxs("div", { children: [_jsx("p", { className: "text-sm mb-3 font-medium", children:
|
|
437
|
+
: "bg-gray-100 text-gray-800 rounded-bl-md"}`, children: [typeof message.content === "string" ? (_jsx("p", { className: "text-sm leading-relaxed", children: message.content })) : message.content.products ? (_jsxs("div", { children: [_jsx("p", { className: "text-sm mb-3 font-medium", children: effectiveLang === "ar"
|
|
387
438
|
? "المنتجات المتاحة:"
|
|
388
439
|
: "Available products:" }), _jsx("div", { className: "space-y-2", children: message.content.products.map((product, index) => (_jsx(ProductCard, { product: product }, product.id || index))) })] })) : null, _jsx("p", { className: `text-xs mt-2 ${isUser ? "text-blue-100" : "text-gray-500"}`, children: message.timestamp })] })] }) }));
|
|
389
440
|
};
|
|
390
441
|
if (!isOpen) {
|
|
391
|
-
return (_jsx("div", { className: "fixed bottom-6 right-6 z-50", children: _jsx(Button, { onClick: () => setIsOpen(true), className: "w-16 h-16 rounded-full shadow-xl bg-black hover:bg-gray-800 transition-all duration-300 hover:scale-105 flex items-center justify-center group cursor-pointer", children: _jsxs("div", { className: "flex items-center", children: [_jsx(Sparkles, { className: "text-white" }), _jsx("span", { className: "text-white font-medium text-sm opacity-0 group-hover:opacity-100 transition-opacity absolute -left-20 bg-black px-3 py-1 rounded-full whitespace-nowrap", children:
|
|
442
|
+
return (_jsx("div", { className: "fixed bottom-6 right-6 z-50", children: _jsx(Button, { onClick: () => setIsOpen(true), className: "w-16 h-16 rounded-full shadow-xl bg-black hover:bg-gray-800 transition-all duration-300 hover:scale-105 flex items-center justify-center group cursor-pointer", children: _jsxs("div", { className: "flex items-center", children: [_jsx(Sparkles, { className: "text-white" }), _jsx("span", { className: "text-white font-medium text-sm opacity-0 group-hover:opacity-100 transition-opacity absolute -left-20 bg-black px-3 py-1 rounded-full whitespace-nowrap", children: effectiveLang === "ar" ? "اسأل الذكاء الاصطناعي" : "Ask AI" })] }) }) }));
|
|
392
443
|
}
|
|
393
444
|
const chatClasses = isExpanded
|
|
394
445
|
? "fixed inset-0 z-50 animate-in slide-in-from-right-4 duration-300"
|
|
395
446
|
: "fixed bottom-0 right-0 w-96 h-screen z-50 animate-in slide-in-right-bottom-4 slide-in-from-right-4 duration-300";
|
|
396
|
-
return (_jsx("div", { className: chatClasses, children: _jsxs(Card, { className: "h-full shadow-2xl border-0 overflow-hidden bg-white flex flex-col", children: [_jsx(CardHeader, { className: "bg-white border-b p-4 flex-shrink-0", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center space-x-3 rtl:space-x-reverse", children: [_jsx("div", { className: "w-8 h-8 rounded-full bg-red-500 flex items-center justify-center text-white font-bold text-sm", children: "tb" }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-gray-800 text-sm", children:
|
|
447
|
+
return (_jsx("div", { className: chatClasses, children: _jsxs(Card, { className: "h-full shadow-2xl border-0 overflow-hidden bg-white flex flex-col", children: [_jsx(CardHeader, { className: "bg-white border-b p-4 flex-shrink-0", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center space-x-3 rtl:space-x-reverse", children: [_jsx("div", { className: "w-8 h-8 rounded-full bg-red-500 flex items-center justify-center text-white font-bold text-sm", children: "tb" }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-gray-800 text-sm", children: effectiveLang === "ar" ? "اسأل Tigerbase" : "Ask Tigerbase" }), _jsx("p", { className: "text-xs text-gray-500", children: effectiveLang === "ar"
|
|
397
448
|
? "متاح الآن للمساعدة"
|
|
398
|
-
: "Available now to assist" })] })] }), _jsxs("div", { className: "flex items-center space-x-2 rtl:space-x-reverse", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsExpanded(!isExpanded), className: "text-gray-500 hover:bg-gray-100 w-8 h-8", children: isExpanded ? (_jsx(Minimize2, { className: "w-4 h-4" })) : (_jsx(Maximize2, { className: "w-4 h-4" })) }), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsOpen(false), className: "text-gray-500 hover:bg-gray-100 w-8 h-8", children: _jsx(X, { className: "w-4 h-4" }) })] })] }) }), _jsxs(CardContent, { className: "flex-1 p-0 flex flex-col overflow-hidden", children: [_jsx("div", { className: "flex-1 overflow-hidden", children: _jsx(ScrollArea, { className: "h-full", children: _jsxs("div", { className: "p-4", children: [messages.length === 1 && (_jsxs("div", { className: "text-center py-12", children: [_jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-gradient-to-br from-purple-500 to-blue-600 rounded-full flex items-center justify-center", children: _jsx(Sparkles, { className: "w-8 h-8 text-white" }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-800 mb-2", children:
|
|
449
|
+
: "Available now to assist" })] })] }), _jsxs("div", { className: "flex items-center space-x-2 rtl:space-x-reverse", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsExpanded(!isExpanded), className: "text-gray-500 hover:bg-gray-100 w-8 h-8", children: isExpanded ? (_jsx(Minimize2, { className: "w-4 h-4" })) : (_jsx(Maximize2, { className: "w-4 h-4" })) }), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsOpen(false), className: "text-gray-500 hover:bg-gray-100 w-8 h-8", children: _jsx(X, { className: "w-4 h-4" }) })] })] }) }), _jsxs(CardContent, { className: "flex-1 p-0 flex flex-col overflow-hidden", children: [_jsx("div", { className: "flex-1 overflow-hidden", children: _jsx(ScrollArea, { className: "h-full", children: _jsxs("div", { className: "p-4", children: [messages.length === 1 && (_jsxs("div", { className: "text-center py-12", children: [_jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-gradient-to-br from-purple-500 to-blue-600 rounded-full flex items-center justify-center", children: _jsx(Sparkles, { className: "w-8 h-8 text-white" }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-800 mb-2", children: effectiveLang === "ar"
|
|
399
450
|
? "اسأل أي شيء عن Tigerbase"
|
|
400
|
-
: "Ask anything about Tigerbase" }), _jsx("p", { className: "text-sm text-gray-500 max-w-xs mx-auto", children:
|
|
451
|
+
: "Ask anything about Tigerbase" }), _jsx("p", { className: "text-sm text-gray-500 max-w-xs mx-auto", children: effectiveLang === "ar"
|
|
401
452
|
? "يستخدم Tigerbase أحدث البيانات في التوثيق للإجابة على أسئلتك."
|
|
402
|
-
: "Tigerbase uses the latest data in the documentation to answer your questions." })] })), messages.map((message, index) => (_jsx(MessageBubble, { message: message }, index))), loading && (_jsx("div", { className: "flex justify-start mb-4", children: _jsxs("div", { className: "flex", children: [_jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 mr-3 flex items-center justify-center", children: _jsx(Bot, { className: "w-4 h-4 text-gray-600" }) }), _jsx("div", { className: "bg-gray-100 p-3 rounded-2xl rounded-bl-md", children: _jsxs("div", { className: "flex space-x-1", children: [_jsx("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce" }), _jsx("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }), _jsx("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })] }) })] }) })), _jsx("div", { ref: messagesEndRef })] }) }) }), messages.length > 1 && (_jsx("div", { className: "border-t bg-gray-50 p-3 flex-shrink-0", children: _jsxs("div", { className: "flex space-x-2 rtl:space-x-reverse mb-0 flex-wrap gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: refreshProducts, className: "text-xs h-8 px-3 flex items-center gap-1", disabled: loading, children: [_jsx(RefreshCw, { className: "w-3 h-3" }),
|
|
453
|
+
: "Tigerbase uses the latest data in the documentation to answer your questions." })] })), messages.map((message, index) => (_jsx(MessageBubble, { message: message }, index))), loading && (_jsx("div", { className: "flex justify-start mb-4", children: _jsxs("div", { className: "flex", children: [_jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 mr-3 flex items-center justify-center", children: _jsx(Bot, { className: "w-4 h-4 text-gray-600" }) }), _jsx("div", { className: "bg-gray-100 p-3 rounded-2xl rounded-bl-md", children: _jsxs("div", { className: "flex space-x-1", children: [_jsx("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce" }), _jsx("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }), _jsx("div", { className: "w-2 h-2 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })] }) })] }) })), _jsx("div", { ref: messagesEndRef })] }) }) }), messages.length > 1 && (_jsx("div", { className: "border-t bg-gray-50 p-3 flex-shrink-0", children: _jsxs("div", { className: "flex space-x-2 rtl:space-x-reverse mb-0 flex-wrap gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: refreshProducts, className: "text-xs h-8 px-3 flex items-center gap-1", disabled: loading, children: [_jsx(RefreshCw, { className: "w-3 h-3" }), effectiveLang === "ar" ? "المنتجات" : "Products"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: showCart, className: "text-xs h-8 px-3 flex items-center gap-1", children: [_jsx(ShoppingCart, { className: "w-3 h-3" }), effectiveLang === "ar" ? "السلة" : "Cart"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: clearChat, className: "text-xs h-8 px-3 flex items-center gap-1", children: [_jsx(Trash2, { className: "w-3 h-3" }), effectiveLang === "ar" ? "مسح" : "Clear"] })] }) })), _jsxs("div", { className: "border-t bg-white p-4 flex-shrink-0", children: [_jsxs("div", { className: "flex space-x-2 rtl:space-x-reverse items-center", children: [_jsx(Input, { value: input, onChange: (e) => setInput(e.target.value), onKeyPress: handleKeyPress, placeholder: effectiveLang === "ar" ? "اسأل أي شيء" : "Ask anything", className: "flex-1 border-0 bg-gray-100 focus:bg-white transition-colors text-right placeholder:text-gray-500 text-sm", disabled: loading }), _jsx(Button, { onClick: () => handleSend(1), disabled: loading || !input.trim(), size: "icon", className: "bg-gray-300 hover:bg-gray-400 text-gray-600 w-8 h-8 rounded-full shrink-0", children: _jsx(Send, { className: "w-4 h-4" }) })] }), _jsx("div", { className: "mt-3 text-center", children: _jsxs("p", { className: "text-xs text-gray-500", children: [effectiveLang === "ar" ? "مدعوم بواسطة" : "Powered by", " ", _jsx("span", { className: "text-red-500 font-semibold", children: "Tigerbase" })] }) })] })] })] }) }));
|
|
403
454
|
};
|
|
404
455
|
export default ChatbotPopup;
|
package/package.json
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "tigerbase-chatbot",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "TigerBase Chatbot Client - AI-powered chatbot for product management",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "tsc",
|
|
10
|
-
"prepublishOnly": "npm run build"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"@google/generative-ai": "^0.21.0",
|
|
14
|
-
"@radix-ui/react-dialog": "^1.1.15",
|
|
15
|
-
"@radix-ui/react-scroll-area": "^1.0.5",
|
|
16
|
-
"@radix-ui/react-slot": "^1.2.3",
|
|
17
|
-
"class-variance-authority": "^0.7.1",
|
|
18
|
-
"clsx": "^2.0.0",
|
|
19
|
-
"lucide-react": "^0.441.0",
|
|
20
|
-
"react-toastify": "^10.0.6",
|
|
21
|
-
"tailwind-merge": "^2.3.0"
|
|
22
|
-
},
|
|
23
|
-
"devDependencies": {
|
|
24
|
-
"@types/node": "^20.14.2",
|
|
25
|
-
"@types/react": "^18.3.3",
|
|
26
|
-
"@types/react-dom": "^18.3.0",
|
|
27
|
-
"typescript": "^5.5.4"
|
|
28
|
-
},
|
|
29
|
-
"peerDependencies": {
|
|
30
|
-
"react": "^18.2.0 || ^19.0.0",
|
|
31
|
-
"react-dom": "^18.2.0 || ^19.0.0"
|
|
32
|
-
},
|
|
33
|
-
"author": "SolomDev00",
|
|
34
|
-
"license": "MIT",
|
|
35
|
-
"repository": {
|
|
36
|
-
"type": "git",
|
|
37
|
-
"url": "git+https://github.com/SolomDev00/Tigerbase.git"
|
|
38
|
-
},
|
|
39
|
-
"homepage": "https://tigerbase.cloud",
|
|
40
|
-
"files": [
|
|
41
|
-
"dist"
|
|
42
|
-
],
|
|
43
|
-
"keywords": [
|
|
44
|
-
"tigerbase",
|
|
45
|
-
"chatbot",
|
|
46
|
-
"react",
|
|
47
|
-
"ai",
|
|
48
|
-
"gemini",
|
|
49
|
-
"product-management",
|
|
50
|
-
"mcp"
|
|
51
|
-
],
|
|
52
|
-
"publishConfig": {
|
|
53
|
-
"access": "public"
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "tigerbase-chatbot",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "TigerBase Chatbot Client - AI-powered chatbot for product management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@google/generative-ai": "^0.21.0",
|
|
14
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
15
|
+
"@radix-ui/react-scroll-area": "^1.0.5",
|
|
16
|
+
"@radix-ui/react-slot": "^1.2.3",
|
|
17
|
+
"class-variance-authority": "^0.7.1",
|
|
18
|
+
"clsx": "^2.0.0",
|
|
19
|
+
"lucide-react": "^0.441.0",
|
|
20
|
+
"react-toastify": "^10.0.6",
|
|
21
|
+
"tailwind-merge": "^2.3.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^20.14.2",
|
|
25
|
+
"@types/react": "^18.3.3",
|
|
26
|
+
"@types/react-dom": "^18.3.0",
|
|
27
|
+
"typescript": "^5.5.4"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
31
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
32
|
+
},
|
|
33
|
+
"author": "SolomDev00",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/SolomDev00/Tigerbase.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://tigerbase.cloud",
|
|
40
|
+
"files": [
|
|
41
|
+
"dist"
|
|
42
|
+
],
|
|
43
|
+
"keywords": [
|
|
44
|
+
"tigerbase",
|
|
45
|
+
"chatbot",
|
|
46
|
+
"react",
|
|
47
|
+
"ai",
|
|
48
|
+
"gemini",
|
|
49
|
+
"product-management",
|
|
50
|
+
"mcp"
|
|
51
|
+
],
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
}
|
|
55
|
+
}
|